It's safe because all the environ_*() calls operate on the result of 
nih_str_array_new(). That function will return a block of memory big enough to 
hold a single 'char *' pointer, and set it to NULL. The NihAllocCtx is situated 
_below_ the return value of nih_str_array_new() in memory and that single 
NihAllocCtx will be used to keep track of the size and child allocations of the 
entire array (should it grow bigger than its current size of zero (the 
terminator is not counted)).

Subsequent to nih_str_array_new() being called, that zero-sized array will be 
increased in size by calls to environ_add(), which in turn calls 
nih_str_array_addp(). That latter function then calls nih_realloc() to increase 
the size of the single NihAllocCtx previously mentioned.

So, if the array contains pointers to 10 env vars, it has size 11 (10 + 1 for 
the NULL terminator), and has a single NihAllocCtx just before the zeroth 
element. So it's actual byte size is:

  sizeof (NihAllocCtx) + (sizeof (char *) * (number_of_elements + 1))

As such, it is safe to call memmove to shuffle those pointers since they are 
the user-accessible way to reference the strings the array points to - Nih 
keeps track itself using the NihAllocCtx object.

I've added a call to nih_relloc() to compact the size of the array (from NIH's 
perspective) as it is wasteful (but not actually incorrect) not to call 
nih_realloc() and leave 'sizeof (char *)' bytes lying around until the array 
eventually gets deallocated.


-- 
https://code.launchpad.net/~jamesodhunt/upstart/bug-1222705-reprise/+merge/226983
Your team Upstart Reviewers is subscribed to branch lp:upstart.

-- 
upstart-devel mailing list
upstart-devel@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/upstart-devel

Reply via email to