Git fork

alloc: fix dangling pointer in alloc_state cleanup

All callers of clear_alloc_state() immediately free what they
cleared, so currently it does not hurt anybody that the
alloc_state is left in an unreusable state, but it is an
error-prone API. Replace it with a new function that clears but
in addition frees the structure, as well as NULLing the pointer
that points at it and adjust existing callers.

As it is a moral equivalent of FREE_AND_NULL(), except that what it
frees has internal structure that needs to be cleaned, allow the
helper to be called twice in a row, by making a call with a pointer
to a pointer variable that already is NULLed.

While at it, rename allocate_alloc_state() and name the new
function alloc_state_free_and_null(), to follow more closely the
function naming convention specified in the CodingGuidelines
(namely, functions about S are named with S_ prefix and then
verb).

Signed-off-by: ノウラ | Flare <nouraellm@gmail.com>
Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

ノウラ | Flare and committed by
Junio C Hamano
5e2feb5c 42bc2244

+20 -20
+8 -2
alloc.c
··· 36 int slab_nr, slab_alloc; 37 }; 38 39 - struct alloc_state *allocate_alloc_state(void) 40 { 41 return xcalloc(1, sizeof(struct alloc_state)); 42 } 43 44 - void clear_alloc_state(struct alloc_state *s) 45 { 46 while (s->slab_nr > 0) { 47 s->slab_nr--; 48 free(s->slabs[s->slab_nr]); 49 } 50 51 FREE_AND_NULL(s->slabs); 52 } 53 54 static inline void *alloc_node(struct alloc_state *s, size_t node_size)
··· 36 int slab_nr, slab_alloc; 37 }; 38 39 + struct alloc_state *alloc_state_alloc(void) 40 { 41 return xcalloc(1, sizeof(struct alloc_state)); 42 } 43 44 + void alloc_state_free_and_null(struct alloc_state **s_) 45 { 46 + struct alloc_state *s = *s_; 47 + 48 + if (!s) 49 + return; 50 + 51 while (s->slab_nr > 0) { 52 s->slab_nr--; 53 free(s->slabs[s->slab_nr]); 54 } 55 56 FREE_AND_NULL(s->slabs); 57 + FREE_AND_NULL(*s_); 58 } 59 60 static inline void *alloc_node(struct alloc_state *s, size_t node_size)
+2 -2
alloc.h
··· 14 void *alloc_tag_node(struct repository *r); 15 void *alloc_object_node(struct repository *r); 16 17 - struct alloc_state *allocate_alloc_state(void); 18 - void clear_alloc_state(struct alloc_state *s); 19 20 #endif
··· 14 void *alloc_tag_node(struct repository *r); 15 void *alloc_object_node(struct repository *r); 16 17 + struct alloc_state *alloc_state_alloc(void); 18 + void alloc_state_free_and_null(struct alloc_state **s_); 19 20 #endif
+10 -16
object.c
··· 517 memset(o, 0, sizeof(*o)); 518 519 o->repo = repo; 520 - o->blob_state = allocate_alloc_state(); 521 - o->tree_state = allocate_alloc_state(); 522 - o->commit_state = allocate_alloc_state(); 523 - o->tag_state = allocate_alloc_state(); 524 - o->object_state = allocate_alloc_state(); 525 - 526 o->is_shallow = -1; 527 CALLOC_ARRAY(o->shallow_stat, 1); 528 ··· 573 o->buffer_slab = NULL; 574 575 parsed_object_pool_reset_commit_grafts(o); 576 - clear_alloc_state(o->blob_state); 577 - clear_alloc_state(o->tree_state); 578 - clear_alloc_state(o->commit_state); 579 - clear_alloc_state(o->tag_state); 580 - clear_alloc_state(o->object_state); 581 stat_validity_clear(o->shallow_stat); 582 - FREE_AND_NULL(o->blob_state); 583 - FREE_AND_NULL(o->tree_state); 584 - FREE_AND_NULL(o->commit_state); 585 - FREE_AND_NULL(o->tag_state); 586 - FREE_AND_NULL(o->object_state); 587 FREE_AND_NULL(o->shallow_stat); 588 }
··· 517 memset(o, 0, sizeof(*o)); 518 519 o->repo = repo; 520 + o->blob_state = alloc_state_alloc(); 521 + o->tree_state = alloc_state_alloc(); 522 + o->commit_state = alloc_state_alloc(); 523 + o->tag_state = alloc_state_alloc(); 524 + o->object_state = alloc_state_alloc(); 525 o->is_shallow = -1; 526 CALLOC_ARRAY(o->shallow_stat, 1); 527 ··· 572 o->buffer_slab = NULL; 573 574 parsed_object_pool_reset_commit_grafts(o); 575 + alloc_state_free_and_null(&o->blob_state); 576 + alloc_state_free_and_null(&o->tree_state); 577 + alloc_state_free_and_null(&o->commit_state); 578 + alloc_state_free_and_null(&o->tag_state); 579 + alloc_state_free_and_null(&o->object_state); 580 stat_validity_clear(o->shallow_stat); 581 FREE_AND_NULL(o->shallow_stat); 582 }