mirror of
https://github.com/xroche/httrack.git
synced 2026-07-28 19:43:02 +03:00
master
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0984aa2530 |
grep -q SIGPIPEs the producer feeding it, so an assertion that held reports failure (#822)
* Match captured output with a here-string, not a pipe into grep -q grep -q exits on the first match, so whatever the producer still had to write takes SIGPIPE; under pipefail that becomes the pipeline's status and an assertion that held reports failure. bash issues one write() per line, so any match that is not on the last line is exposed. Converts every test assertion whose producer is a shell builtin or shell function, including two pipelines used as an if condition where the SIGPIPE silently flips the branch. Generalizes the AGENTS.md bullet, which only covered the "&& fail" spelling. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * Convert the remaining pipe-into-grep -q sites The self-test drivers survive only because the matched line is the last thing httrack prints; one added line of output turns a pass into 141. Nothing in tests/ pipes into grep -q now. The two zlib drivers claimed the harness might run them under a POSIX /bin/sh: it does not. configure resolves $(BASH) to bash, test-timeout.sh execs it, and 01_zlib-warc-wacz.test already uses "set -o pipefail" (which dash lacks) on the macOS leg. Kept the half that is true, BSD tool flags. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> --------- Signed-off-by: Xavier Roche <roche@httrack.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
6579436607 |
webhttrack: the command line overflows its argv vector and a quoted value can inject flags (#710)
* htsserver builds the redirect Location header in a 256-byte stack buffer The POST redirect path checks strlen(file) but sprintf's newfile, which comes straight from the client's "redirect" POST field with no length cap. A 300-byte value overflows tmp[256]. The same value reached the Location header with no CR/LF check, so it could split the response and inject headers. Append into the dynamic String the other headers already use, and drop the header entirely when the value carries a CR or LF. The listen socket was SOCaddr_initany, so the server answered the LAN and not just the local browser it exists to serve. Bind 127.0.0.1 by default, with --bind <addr> to widen it again, resolved through the existing gethost() helper the way proxytrack already does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * tests: satisfy shellcheck and shfmt in the new server test Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * tests: drop the pre-fix narration from the oversized-value comment Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * tests: assert the bound socket, not the announced URL The listen-address assertions only compared the URL= banner, which is a literal echo of argv: a build that announced 127.0.0.1 while binding the wildcard passed. Probe 127.0.0.2 on the same port instead, which a wildcard listener takes and a loopback-only one leaves free. Also refuse an empty --bind, which fell through to every interface and silently undid the new default. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * tests: bound the response read and the empty --bind run The recv() loop had no timeout and read until EOF; htsserver need not close the connection after responding, which wedged the macOS runner for over an hour. Stop at the end of the header block, which is all the test reads. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * htsserver: the session id must gate the request body, not the reply Every field of a POST body is written straight into the one global key store the templates and the command dispatcher both read, and "command" from there reaches the engine. The gate ran after that write and compared "sid" against "_sid" -- but "_sid" is copied into "sid" beforehand so the templates can render it, so a request that simply omitted the field compared equal to itself. Only a wrong id was refused; an absent one passed. Clearing the reply afterwards does not help either, because the dispatcher sits outside the reply guard. Authenticate before parsing instead: scan the raw body for "sid", require at least one occurrence and reject if any of them differs, and drop the body untouched when it does not match. That leaves the shared template key alone, and it closes the dispatcher for free. A refused request also emitted only a Content-length line, since the status line for that branch was behind _DEBUG. Any client reads that as a protocol error, which is how test 68 failed rather than reporting the refusal. Send a 403 instead. Tests 68 and 77 posted without an id, which is what the engine used to accept, so both now fetch the one the server renders into the form. Test 78 covers accept, missing, empty and wrong, asserts the 403, and probes the key store through ${projname} rather than the suppressed reply -- a reply-only assertion passes even when the write goes through. Also fix a leak that hung macOS CI: start() runs inside a command substitution, so its $! never reached the parent and stop() guarded on an empty variable, leaving one htsserver per call. Test 77 starts four, which is exactly the four orphans the runner reported while sitting for half an hour behind a green test log. Take the pid from the PID= line the server already announces. Signed-off-by: Xavier Roche <xroche@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * webhttrack: bound the argv vector and escape quotes in the wizard command line The wizard hands its httrack command line to the engine as one string, which back_launch_cmd() split back into argv. Two things were wrong with that split. It wrote into a fixed 1024-pointer vector with no bound, and every unquoted space in the posted string yields an entry, so an ordinary mirror with a few hundred URLs walked off the allocation. The split now lives in htscmdline.c as hts_split_cmdline(), which sizes the vector from the separator count before filling it, and the engine self-tests can reach it. Quotes were also purely advisory: they toggled the "inside an argument" state but nothing escaped them, so a double quote typed into a wizard field (user agent, footer, path, project name) closed the argument early and the rest of the value was parsed as fresh options -- among them -V, which reaches system(). Escaping has to happen where the argument boundary is known, so the template gets its own ${arg:} filter for that context; ${html:} keeps its meaning for the HTML attributes it is used in everywhere else, and HTML escaping would not help anyway since the browser undoes it when it posts the command line back. ${arg:} backslash-escapes a quote and a backslash, and the splitter reads those inside a quoted run, the same convention next_token() already implements for doit.log. A value containing a quote now survives it intact instead of turning into options. Signed-off-by: Xavier Roche <xroche@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * webhttrack: keep a stray quote in an unquoted field out of the split The url and wildcard-filter fields go into the command line outside quotes, where no backslash can escape anything: a single quote there flips the parity of every quote after it, so a later escaped value ends up split as flags and the escaping buys nothing. Emit %22 for those fields instead. NULL-terminate the argv vector while here, matching the convention the tree documents in htscharset.c, and fold the third copy of the entity table into one helper. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> * tests: do not feed snprintf's return value back as its size argument snprintf returns the length it wanted to write, so accumulating it blind lets the next size argument wrap. The buffer is sized well past what the loop needs, but the pattern is the one the project forbids. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com> --------- Signed-off-by: Xavier Roche <roche@httrack.com> Signed-off-by: Xavier Roche <xroche@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |