Fix iteration after expiring a list entry
authorBen Hutchings <ben@decadent.org.uk>
Fri, 22 Jan 2016 19:34:41 +0000 (19:34 +0000)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 28 Jan 2016 15:38:28 +0000 (15:38 +0000)
After removing an entry, the next entry will be at the same offset as
the entry we just removed.  Also the total length will have changed.

Update the length when we remove an entry, and advance the offset only
when we don't.

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
src/odhcp6c.c

index 1714d629b7cc38a7b3816cfaac58af5a2420baa0..59f6390801152d82264e3a45516e8979a8ca5a4e 100644 (file)
@@ -619,7 +619,7 @@ static void odhcp6c_expire_list(enum odhcp6c_state state, uint32_t elapsed)
        uint8_t *start = odhcp6c_get_state(state, &len);
        for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
                        (uint8_t*)c < &start[len] && &c->auxtarget[c->auxlen] <= &start[len];
-                       c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen])) {
+                       ) {
                if (c->t1 < elapsed)
                        c->t1 = 0;
                else if (c->t1 != UINT32_MAX)
@@ -640,8 +640,12 @@ static void odhcp6c_expire_list(enum odhcp6c_state state, uint32_t elapsed)
                else if (c->valid != UINT32_MAX)
                        c->valid -= elapsed;
 
-               if (!c->valid)
+               if (!c->valid) {
                        odhcp6c_remove_state(state, ((uint8_t*)c) - start, sizeof(*c) + c->auxlen);
+                       start = odhcp6c_get_state(state, &len);
+               } else {
+                       c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen]);
+               }
        }
 }