git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 2/4] avoid computing zero offsets from NULL pointer

From
Junio C Hamano <gitster@pobox.com>
Date
Jan 28, 2020, 18:03 UTC
Message-ID
<xmqqtv4f8nlm.fsf@gitster-ct.c.googlers.com>
In-Reply-To
<20200127211933.GA3794@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
Show 36 quoted lines
>> >  	const int blk = 1024;
>> >  	long trimmed = 0, recovered = 0;
>> > -	char *ap = a->ptr + a->size;
>> > -	char *bp = b->ptr + b->size;
>> > +	char *ap = a->ptr ? a->ptr + a->size : a->ptr;
>> > +	char *bp = b->ptr ? b->ptr + b->size : b->ptr;
>> >  	long smaller = (a->size < b->size) ? a->size : b->size;
>> >  
>> >  	while (blk + trimmed <= smaller && !memcmp(ap - blk, bp - blk, blk)) {
>> 
>> Isn't it a bug for a->ptr or b->ptr to be NULL here?  Even if we
>> manage to assign ap = a->ptr = NULL without complaints, how would
>> that memcmp work?
>> 
>> Is it that the corresponding .size would always be 0 if .ptr is NULL
>> that protects us?
>
> If we want to be more defensive, we could do something like this:
>
>   /* dual inline/macro magic to avoid evaluating ptr twice but knowing
>    * enough about the type of *ptr to get the size. */
>   #define SAFE_END_PTR(ptr, len) safe_end_ptr(ptr, len, sizeof(*ptr))
>   static inline void *safe_end_ptr(void *ptr, size_t nr, size_t elem_size)
>   {
> 	if (!ptr) {
> 		if (nr)
> 			BUG("non-zero size coupled with NULL pointer");
> 		return NULL;
> 	}
> 	return (char *)ptr + nr * elem_size;
>   }
>
>   ...
>   char *ap = SAFE_END_PTR(a->ptr, a->size);
>
> I'm not sure if it's worth it, though.

As long as we make it clear to those who add new callers that any mmfile_t with .ptr==NULL must come with .size==0, it is fine.

> Yet another alternative is to consider it a bug to use an mmfile_t with
> a NULL pointer, figure out where that's being set up, and fix it.

But that would still require us to make it clear to those who add new callers that mmfile_t with .ptr==NULL is a bug, and the current callers must be using that as it is convenient for them, I presume, so I think a simple comment should probably be sufficient.

> As an aside, I also wondered whether we could run into problems with
> "memcmp(NULL, ..., 0)", which is also undefined behavior. But we don't
> here because the first half of the while() condition wouldn't trigger.
Yes, although the details slightly differ ;-)

What is problematic actually is "memcmp(NULL - 1024, ..., 1024)", which is guarded with "1024 + trimmed <= smaller &&" that will never be true as long as "mmfile_t with .ptr==NULL must have .size==0" holds true, right?

Thanks.
Previous: Jeff KingNext: Jeff King
Message 11 of 17 in “more clang/sanitizer fixes”
  1. 0/4 more clang/sanitizer fixesJeff King, Jan 25, 2020
  2. 1/4 merge-recursive: silence -Wxor-used-as-pow warningJeff King, Jan 25, 2020
  3. Junio C HamanoJan 25, 2020
  4. Jeff KingJan 25, 2020
  5. Elijah NewrenJan 25, 2020
  6. Jeff KingJan 25, 2020
  7. Junio C HamanoJan 27, 2020
  8. 2/4 avoid computing zero offsets from NULL pointerJeff King, Jan 25, 2020
  9. Junio C HamanoJan 27, 2020
  10. Jeff KingJan 27, 2020
  11. Junio C HamanoJan 28, 2020
  12. Jeff KingJan 29, 2020
  13. Junio C HamanoJan 29, 2020
  14. Jeff KingJan 29, 2020
  15. 3/4 xdiff: avoid computing non-zero offset from NULL pointerJeff King, Jan 25, 2020
  16. 4/4 obstack: avoid computing offsets from NULL pointerJeff King, Jan 25, 2020
  17. 4/4 obstack: avoid computing offsets from NULL pointerJeff King, Jan 25, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.