]> git.ozlabs.org Git - ccan/blobdiff - ccan/foreach/foreach.c
foreach: fix case where iterators are not on the stack.
[ccan] / ccan / foreach / foreach.c
index 70040ee986a5116bb407ea5ebc3ab703d51abd98..de79eb59af782e8544520e19b6750212a132ac97 100644 (file)
@@ -12,19 +12,28 @@ struct iter_info {
        struct list_node list;
        const void *index;
        unsigned int i, num;
        struct list_node list;
        const void *index;
        unsigned int i, num;
+       bool onstack;
 };
 
 };
 
+/* Is pointer still downstack from some other onstack var? */
+static bool on_stack(const void *ptr, const void *onstack)
+{
+#if HAVE_STACK_GROWS_UPWARDS
+       return ptr < onstack;
+#else
+       return ptr > onstack;
+#endif
+}
+
 static void free_old_iters(const void *index)
 {
        struct iter_info *i, *next;
 
        list_for_each_safe(&iters, i, next, list) {
                /* If we're re-using an index, free the old one.
 static void free_old_iters(const void *index)
 {
        struct iter_info *i, *next;
 
        list_for_each_safe(&iters, i, next, list) {
                /* If we're re-using an index, free the old one.
-                * Otherwise, if it's past i on the stack, it's old.  Don't
-                * assume stack direction, but we know index is downstack. */
+                * Otherwise, discard if it's passed off stack. */
                if (i->index == index
                if (i->index == index
-                   || (((uintptr_t)index < (uintptr_t)&i)
-                       == ((uintptr_t)&i < (uintptr_t)i->index))) {
+                   || (i->onstack && !on_stack(i->index, &i))) {
                        list_del(&i->list);
                        free(i);
                }
                        list_del(&i->list);
                        free(i);
                }
@@ -47,6 +56,7 @@ static struct iter_info *new_iter(const void *index)
        struct iter_info *info = malloc(sizeof *info);
        info->index = index;
        info->i = info->num = 0;
        struct iter_info *info = malloc(sizeof *info);
        info->index = index;
        info->i = info->num = 0;
+       info->onstack = on_stack(index, &info);
        list_add(&iters, &info->list);
        return info;
 };
        list_add(&iters, &info->list);
        return info;
 };