diff options
author | Stephen Dolan <mu@netsoc.tcd.ie> | 2012-12-24 17:11:18 +0000 |
---|---|---|
committer | Stephen Dolan <mu@netsoc.tcd.ie> | 2012-12-24 17:11:18 +0000 |
commit | cedda2084d2f6b331ba0a73e05f0b77ee7995c86 (patch) | |
tree | 8a91fd88b2ce655780f3399954c7c37d2c368b95 /forkable_stack.h | |
parent | 0fed03f35a63c01e89c0ba91cfe92dfc226d1e86 (diff) |
Sneaky valgrind trick to detect stack memory issues.
After something is popped from a stack, we overwrite the memory
with uninitialised data (if JQ_DEBUG is on). This means that
valgrind reports use-after-pop as an uninitialised memory error.
Diffstat (limited to 'forkable_stack.h')
-rw-r--r-- | forkable_stack.h | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/forkable_stack.h b/forkable_stack.h index c96c132e..74fcf433 100644 --- a/forkable_stack.h +++ b/forkable_stack.h @@ -100,13 +100,22 @@ static void* forkable_stack_peek_next(struct forkable_stack* s, void* top) { // Returns 1 if the next forkable_stack_pop will permanently remove an // object from the stack (i.e. the top object was not saved with a fork) static int forkable_stack_pop_will_free(struct forkable_stack* s) { - return s->pos < s->savedlimit ? 1 : 0; + return s->pos < s->savedlimit; } static void forkable_stack_pop(struct forkable_stack* s) { forkable_stack_check(s); struct forkable_stack_header* elem = forkable_stack_peek(s); - s->pos += elem->next_delta; + int reclaim_upto = s->pos + elem->next_delta < s->savedlimit ? + s->pos + elem->next_delta : s->savedlimit; + assert(reclaim_upto <= s->length); + int reclaimed = reclaim_upto > s->pos ? reclaim_upto - s->pos : 0; + assert(0 <= reclaimed && s->pos + reclaimed <= s->length); + // s->pos <= i < reclaim_upto means that position i is to be freed + assert((reclaimed > 0) == forkable_stack_pop_will_free(s)); + int new_pos = s->pos + elem->next_delta; + jv_mem_invalidate(elem, reclaimed); + s->pos = new_pos; } |