Skip to content

size_t i = strlen(s) - 1: the (i > 0) guard cannot see the underflow - #832

Merged
xroche merged 3 commits into
fix/strlen-pointer-form-781from
fix/strlen-size-t-form-821
Jul 27, 2026
Merged

size_t i = strlen(s) - 1: the (i > 0) guard cannot see the underflow#832
xroche merged 3 commits into
fix/strlen-pointer-form-781from
fix/strlen-size-t-form-821

Conversation

@xroche

@xroche xroche commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Seven sites in htswizard.c seed a size_t index with strlen(x) - 1 and then guard the walk-back with (i > 0). SIZE_MAX satisfies that, so the check the author meant as the emptiness test does nothing. They now seed from hts_lastcharoffset(), which #819 adds. On any non-empty string it is the same value, so the only behaviour that moves is the empty case that used to read below the buffer.

Nothing reaches them today. ident_url_absolute() returns -1 on an empty adr and substitutes default-index.html for an empty fil, and that is where the whole invariant lives, since no caller checks fil itself. A producer of an empty fil added later would turn three of the sites live at once.

punycode.c is the exception and the only out-of-bounds write in the set. RFC 3492's sample harness wants both PUNYCODE_COSTELLO_RFC3492_INCLUDE_TEST and ..._MAIN, and nothing in the tree or the build defines either, so it never compiles. Define both and a stdin line whose first byte is NUL leaves strlen() at 0, which segfaults on the read at input[input_length] and would write there next. Checked under ASan against both versions.

Every site being latent, the barrier against the idiom coming back is the source guard rather than a crawl: the self-test picks up the size_t spelling and 01_engine-lastchar.test grows a grep for it.

Based on #819 for the helper. A live crash turned up in the same sweep and went out separately as #829.

Closes #821

xroche and others added 3 commits July 27, 2026 14:52
An unsigned index seeded with strlen(s) - 1 becomes SIZE_MAX on an empty
string, and SIZE_MAX passes the (i > 0) the sites carry. Seed from
hts_lastcharoffset() instead, and cover the spelling in the lastchar
self-test and its source guard.

Closes #821

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
The declaration pattern cannot see punycode.c, where input_length is
declared a dozen lines above the subtraction, so reverting that fix alone
left the guard silent. Match an uncast assignment too; the (int) casts in
htscore.c and htstools.c are the safe form and stay out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
@xroche
xroche merged commit 4d056aa into fix/strlen-pointer-form-781 Jul 27, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant