Skip to content

lienrelatif() reads one byte before its stack buffer on an empty path#729

Merged
xroche merged 1 commit into
masterfrom
fix/lienrelatif-empty-path
Jul 26, 2026
Merged

lienrelatif() reads one byte before its stack buffer on an empty path#729
xroche merged 1 commit into
masterfrom
fix/lienrelatif-empty-path

Conversation

@xroche

@xroche xroche commented Jul 26, 2026

Copy link
Copy Markdown
Owner

lienrelatif() trims its current-path argument back to the last /, starting from curr + strlen(curr) - 1. When the path is empty that is curr - 1, and the loop dereferences it before the bounds test stops it.

The empty path is not hypothetical. The pre-pass that strips a query does strncatbuff(newcurr_fil, curr_fil, a - curr_fil), so any curr_fil beginning with ? hands the trim an empty string. httrack -#test=relative "dir/page.html" "?x" under ASan reports the underflow on current master.

The read is a single byte and the loop exits on its a > curr test whatever that byte holds, so the guard is behaviour-preserving rather than a behaviour change. Checked rather than assumed: 484 ordered pairs from a 22-value path corpus, run against builds that force the byte before the buffer to 0 and to '/', produce output identical to the guarded build in both states.

Found while working on #712, which reaches the same path from a document with no save name.

The trim that walks back to the last '/' starts at `curr + strlen(curr) - 1`,
which is `curr - 1` when the path is empty. The loop then dereferences it.

An empty path is reachable today: the pre-pass that strips a query does
`strncatbuff(newcurr_fil, curr_fil, a - curr_fil)`, so any `curr_fil` starting
with '?' hands the walk an empty string. `-#test=relative "dir/page.html" "?x"`
under ASan reports the underflow.

The read is one byte and the loop stops immediately either way, so the guard
changes no output: over the 484 ordered pairs of a 22-value path corpus, run
against builds that force the byte before the buffer to 0 and to '/', the
guarded and unguarded results are identical.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
@xroche
xroche merged commit a75f437 into master Jul 26, 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