Skip to content

A param option's value is bounded by length where a magnitude is meant - #1439

Merged
xroche merged 2 commits into
masterfrom
fix-1437
Aug 25, 2026
Merged

A param option's value is bounded by length where a magnitude is meant#1439
xroche merged 2 commits into
masterfrom
fix-1437

Conversation

@xroche

@xroche xroche commented Aug 25, 2026

Copy link
Copy Markdown
Owner

optalias_param_takes() (#1427) bounded a param row's value at 16 characters, which is a length where a magnitude is meant. It refused --depth=0000000000000000001 for its padding alone, and accepted --sockets=1234567890123456, sixteen digits that sscanf("%d") then read as 1015724736 simultaneous connections. Each digit run is now converted with strtoll and range-checked against what the option's own parser holds: INT_MAX for the rows reading an int, INT64_MAX for -m, -M and -G on their LLint and for -%c, whose float takes any run strtoll converts. The check runs per operand, so the second half of -m N,N2 and -%c 0.5 is covered too. optalias_suffix() carried a copy of the same bare 16, so the six level rows get the same treatment.

The behaviour change is the fix rather than a side effect of it, and it goes both ways. Refused from now on: a value on an int-valued long form whose digit run exceeds 2147483647 and which the old cap let through, so no longer than 16 characters. --sockets=1234567890123456, --max-rate=3000000000, --depth=2147483648, --timeout=99999999999, --generate-errors=3000000000, and every value of that shape on the other int rows. All of them were undefined at sscanf("%d") and wrapped in practice: 1015724736 sockets, a rate of -1294967296, a depth of -2147483648, a timeout of 1215752191 seconds. None landed on a sane value by accident either, since -c clamps its wrapped negative back to one socket, which is still not what was asked for.

Accepted from now on: a zero-padded value wherever its magnitude fits, and on -m, -M, -G and -%c any 17-to-19-digit run up to INT64_MAX. --max-size=9223372036854775807 is refused on master and taken here, which is right, because that is what the LLint behind it holds.

The old cap was also the only thing keeping a value short enough to glue into the 1024-byte expansion buffer, where strlcatbuff aborts rather than clips. So a length bound stays, at the glue site and sized to the room the short form leaves: without it httrack --depth $(printf '0%.0s' $(seq 1022)) exits 134 with a backtrace where master printed a syntax error. It now also reaches a class the old cap never covered, the param0 rows, where httrack --allow <1023 chars> aborts on master and draws the same syntax error here.

369 asserts both directions, through the engine's own expansion and on disk, and reds on six mutants: the length cap put back, optalias_run_fits forced true or stripped of its max, the LLint arm narrowed to -M and -%c, a leading sign accepted, the capacity guard removed, and optalias_suffix reverted. st_optalias's table-wide loop carries the padding, INT_MAX and sign probes across all 27 param rows.

Closes #1437

xroche and others added 2 commits August 25, 2026 11:18
optalias_param_takes() capped a "param" row's value at 16 characters, which
refused --depth=0000000000000000001 while --structure=0000000001 works since
#1436, and accepted --sockets=1234567890123456, whose sixteen digits reach
sscanf("%d") as 1015724736 sockets. Range-check each digit run with strtoll
against what the option's own parser holds instead.

Closes #1437

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
The 16-character cap was doing two jobs. Dropping it let a long padded run
reach the 1024-byte expansion buffer, where strlcatbuff aborts: --depth with
1022 zeros exited 134 with a backtrace where master printed a syntax error.
Bound the value against the room the short form leaves, at the glue site, which
also covers the param0 rows that abort on master today (--allow, 1023 chars).

optalias_suffix() carried a copy of the same bare 16, so --generate-errors=
3000000000 still reached sscanf("%d") as -1294967296; it now takes the same
magnitude bound. Also: the errno != ERANGE idiom the tree already spells, LLint
over int64_t, and mirror_names/mirror_has_name shared with 362.

The PR body's claim about #1436 was wrong: optalias_digits_fit() is on that
branch, not in the tree, so --structure=0000000001 is refused here too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
@xroche
xroche enabled auto-merge (squash) August 25, 2026 09:57
@xroche
xroche merged commit c4cd49c into master Aug 25, 2026
44 checks passed
@xroche
xroche deleted the fix-1437 branch August 25, 2026 10:08
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.

A zero-padded value is refused on the param rows, where --structure now takes it

1 participant