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

Re: [PATCH v2] refs/ref-cache: fix SEGFAULT when seeking in empty directories

From
Karthik Nayak <karthik.188@gmail.com>
Date
Sep 26, 2025, 07:41 UTC
Message-ID
<CAOLa=ZSfL1CVCNjD0Vi3kpQqLM6t7YVa=G2ChGpaza6WOjZTCw@mail.gmail.com>
In-Reply-To
<xmqqbjmyh353.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> writes:
Show 31 quoted lines
> Karthik Nayak <karthik.188@gmail.com> writes:
>
>> diff --git a/refs/ref-cache.c b/refs/ref-cache.c
>> index c180e0aad7..e5e5df16d8 100644
>> --- a/refs/ref-cache.c
>> +++ b/refs/ref-cache.c
>> @@ -539,7 +539,7 @@ static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator,
>>  				 */
>>  				break;
>>  			}
>> -		} while (slash);
>> +		} while (slash && dir->nr);
>>  	}
>
> This is at the tail of a "do { ... } while (...);" loop, but inside
> the loop I see this construct:
>
> 			for (idx = 0; idx < dir->nr; idx++) {
> 				cmp = strncmp(refname, dir->entries[idx]->name, len);
> 				if (cmp <= 0)
> 					break;
> 			}
> 			/* don't overflow the index */
> 			idx = idx >= dir->nr ? dir->nr - 1 : idx;
>
> i.e., if we scan all the dir->entries[] elements in the innter loop
> and did not find any hit, idx would become dir->nr and this inner
> loop runs to the end.  If (dir->nr == 0), then ?: operator [*] would
> become the idx = (dir->nr - 1);  And that idx is used for a while
> before we get to this "while (slash && dir->nr)".
>
This wouldn't happen because before the loop starts, we set:
   dir = get_ref_dir(iter->cache->root);

So, `dir` will always have an entry (i.e. 'refs') in the first iteration, after that, the checks in the while section of the 'do {} while (...)' loop will kick in.

Show 14 quoted lines
> And then tha tis used like this.
>
> 			if (slash)
> 				slash = slash + 1;
>
> 			level->index = idx;
> 			if (dir->entries[idx]->flag & REF_DIR) {
> 				...
>
> IOW, isn't this check a bit too late?  I wonder if we can leave at
> the beginning of the outer loop, even before sort_ref_dir(dir), when
> dir->nr is zero, or something?
>
>

We could add it there too. I can't see the merit of one over the other. But if you see it being more readable. I'll happily make that change.

As the author of this code, I do find it complex already.
Show 16 quoted lines
>
> [Side note]
>
>  * I found the problematic ?: extremely hard to read, given its
>    contrast with the terminating condnition of for loop.  If you
>    apply the discipline to keep the textual order match the actual
>    order, i.e.
>
> 	for (idx = 0; idx < dir->nr; idx++)
> 		...;
>
> 	idx = dir->nr <= idx ? dir->nr - 1 : idx;
>
>    people would have spotted this more easily.
>
>    But perhaps that may be just me.  Anyway...

I'm not really sold on this being easier to read. But that could be me, So I'll make a second commit to make this change, we can drop it if unwanted.

Previous: Junio C HamanoNext: Karthik Nayak
Message 6 of 10 in “refs/ref-cache: stop seeking into empty directories”
  1. refs/ref-cache: stop seeking into empty directoriesKarthik Nayak, Sep 24, 2025
  2. Patrick SteinhardtSep 24, 2025
  3. Karthik NayakSep 25, 2025
  4. refs/ref-cache: fix SEGFAULT when seeking in empty directoriesKarthik Nayak, Sep 25, 2025
  5. Junio C HamanoSep 25, 2025
  6. Karthik NayakSep 26, 2025
  7. Karthik NayakSep 26, 2025
  8. Junio C HamanoSep 26, 2025
  9. Karthik NayakSep 29, 2025
  10. refs/ref-cache: fix SEGFAULT when seeking in empty directoriesKarthik Nayak, Oct 1, 2025

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.