Compare commits

...

7 Commits

Author SHA1 Message Date
Xavier Roche
a22b7a0e54 Run the oversized-$HOME case only where HOME survives the shell
MSYS rewrites HOME into a path of its own, so the engine never saw the long
value: it expanded ~/foo against the build directory instead of bailing. Gate
the case on the engine reporting the HOME we set; it still runs, and still
fails without the guard, on every platform that passes HOME through.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
2026-07-17 09:02:35 +02:00
Xavier Roche
5944feed9d Keep the oversized-$HOME case inside Windows' environment limit
70000 chars cannot be set as an environment variable on Windows, so the case
failed the MSVC legs, and $(seq 1 70000) flooded the -x log. The buffer is
2 * HTS_URLMAXSIZE, so 4096 clears it and still kills the no-guard mutant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
2026-07-17 08:43:38 +02:00
Xavier Roche
223a8fc27a Pin what the expandhome test could not distinguish
A hts_gethome() that ignored $HOME and always returned the fallback passed
the whole suite: the empty-HOME cases expect ./foo, which a constant "."
satisfies. That is the same silent no-op the fix exists to remove. Also cover
the oversized-$HOME bail, which had no coverage at all.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
2026-07-17 08:24:42 +02:00
Xavier Roche
de09705732 Ask the engine for $HOME rather than pinning it in the expandhome test
MSYS rewrites $HOME into a cwd-relative Windows path before the native
httrack.exe reads it (HTSHOME became D:\a\httrack\httrack\tests\HTSHOME), so
no pinned value survives the Win32 leg. Take the expansion of a bare '~' as
the reference instead, and assert it moved off '~' so the derived cases cannot
go vacuous. The ~user/ and a~/ negatives are literals and stay exact.

Signed-off-by: Xavier Roche <xroche@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
2026-07-17 07:47:01 +02:00
Xavier Roche
96b0555522 Restore the clang-format run over the gate condition
Signed-off-by: Xavier Roche <xroche@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
2026-07-17 07:27:05 +02:00
Xavier Roche
9bbfa39d2a Pin the expandhome test to a $HOME that MSYS leaves alone
The Win32 leg spawns a native httrack.exe, and MSYS rewrites a POSIX absolute
$HOME into a Windows path on the way in, so the engine read
C:\Program Files\Git\home\smith and the pinned /home/smith never matched. A
$HOME with no leading '/' is passed through verbatim; expand_home only
concatenates, so the sentinel exercises the same code.

Signed-off-by: Xavier Roche <xroche@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
2026-07-17 07:25:37 +02:00
Xavier Roche
b10c6eaf5c Restore ~/ expansion in the -O base path
expand_home() has never fired since 660b569 (3.41.2) refactored it from char*
to String: the correct str[0] == '~' became StringSub(*str, 1) == '~', but the
body still skips a single leading character. "~/foo"[1] is '/', so the guard
never matches, while any path whose *second* char is '~' silently lost its
first character and gained $HOME ("a~/x" -> "/home/smith~/x").

Index from 0 and gate on a following '/' so ~user/ is left alone rather than
mangled into $HOME + "user/" -- resolving it needs getpwnam, which this does
not do. An empty $HOME now falls back to '.' like an unset one, so ~/foo can
no longer expand to the absolute /foo, and an oversized $HOME leaves the path
untouched instead of aborting inside strcatbuff.

Signed-off-by: Xavier Roche <xroche@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Xavier Roche <roche@httrack.com>
2026-07-17 06:54:52 +02:00
4 changed files with 86 additions and 10 deletions

View File

@@ -567,24 +567,29 @@ int optinclude_file(const char *name, int *argc, char **argv, char *x_argvblk,
return 0;
}
/* Get home directory, '.' if failed */
/* Get home directory, '.' if unset or empty */
/* example: /home/smith */
const char *hts_gethome(void) {
const char *home = getenv("HOME");
if (home)
return home;
else
return ".";
/* An empty $HOME would expand ~/foo into the absolute /foo */
return strnotempty(home) ? home : ".";
}
/* Convert ~/foo into /home/smith/foo */
/* Convert ~/foo into /home/smith/foo (~user/ left alone: no getpwnam here) */
void expand_home(String * str) {
if (StringSub(*str, 1) == '~') {
if (StringNotEmpty(*str) && StringSub(*str, 0) == '~' &&
(StringLength(*str) == 1 || StringSub(*str, 1) == '/')) {
char BIGSTK tempo[HTS_URLMAXSIZE * 2];
const char *const home = hts_gethome();
const size_t homelen = strlen(home);
const size_t taillen = StringLength(*str) - 1;
strcpybuff(tempo, hts_gethome());
strcatbuff(tempo, StringBuff(*str) + 1);
StringCopy(*str, tempo);
/* Leave untouched rather than abort() in strcatbuff on a huge $HOME */
if (taillen < sizeof(tempo) && homelen < sizeof(tempo) - taillen) {
strcpybuff(tempo, home);
strcatbuff(tempo, StringBuff(*str) + 1);
StringCopy(*str, tempo);
}
}
}

View File

@@ -45,6 +45,7 @@ Please visit our Website: http://www.httrack.com
#include "htscore.h"
#include "htsdefines.h"
#include "htslib.h"
#include "htsalias.h"
#include "htsparse.h"
#include "htscache.h"
#include "htscache_selftest.h"
@@ -825,6 +826,21 @@ static int st_simplify(httrackp *opt, int argc, char **argv) {
return 0;
}
static int st_expandhome(httrackp *opt, int argc, char **argv) {
String path = STRING_EMPTY;
(void) opt;
if (argc < 1) {
fprintf(stderr, "expandhome: needs a path\n");
return 1;
}
StringCopy(path, argv[0]);
expand_home(&path);
printf("expanded=%s\n", StringBuff(path));
StringFree(path);
return 0;
}
static int st_mime(httrackp *opt, int argc, char **argv) {
char mime[256];
@@ -3079,6 +3095,7 @@ static const struct selftest_entry {
{"filterbounds", "", "matcher length/work caps reject hostile patterns",
st_filterbounds},
{"simplify", "<path>", "collapse ./ and ../ in a path", st_simplify},
{"expandhome", "<path>", "expand a leading ~/ into $HOME", st_expandhome},
{"stripquery", "", "--strip-query pattern/key stripping self-test",
st_stripquery},
{"urlhack", "", "-%u url-hack sub-flag (www/slash/query) self-test",

View File

@@ -0,0 +1,53 @@
#!/bin/bash
#
# SC2088: the literal, unexpanded '~' is the input under test.
# shellcheck disable=SC2088
set -euo pipefail
# ~ expansion for the -O base path (expand_home). $HOME is pinned so the cases
# cannot depend on the caller's, but MSYS rewrites it into a Windows path
# before the native httrack.exe reads it: ask the engine what it saw rather
# than hardcoding the value.
ask() {
HOME=HTSHOME httrack -O /dev/null -#test=expandhome "$1"
}
exp() {
test "$(ask "$1")" == "expanded=$2" || exit 1
}
home=$(ask '~')
home=${home#expanded=}
# or every case below is vacuous: '~' means expansion never fired, '.' means it
# fell back to the default without ever reading $HOME
test "$home" != '~' || exit 1
test "$home" != '.' || exit 1
exp '~' "$home"
exp '~/foo' "$home/foo"
exp '~/foo/bar/#' "$home/foo/bar/#"
exp '~/' "$home/"
exp '~/../x' "$home/../x"
# ~user/ needs getpwnam: left alone rather than mangled into $HOME + "user/"
exp '~smith/foo' '~smith/foo'
exp '~root' '~root'
# only a leading '~' expands; anything else is a literal path component
exp 'a~/x' 'a~/x'
exp './~/x' './~/x'
exp 'foo~bar' 'foo~bar'
# an unset or empty $HOME must not turn ~/foo into the absolute /foo
test "$(env -u HOME httrack -O /dev/null -#test=expandhome '~/foo')" == "expanded=./foo" || exit 1
test "$(HOME='' httrack -O /dev/null -#test=expandhome '~/foo')" == "expanded=./foo" || exit 1
# A $HOME past the 2 * HTS_URLMAXSIZE buffer is left alone: strcatbuff aborts
# rather than truncates. Only meaningful where the engine sees the value we set:
# MSYS rewrites HOME into a path of its own choosing, long or not.
if test "$home" = HTSHOME; then
long=$(printf '%04096d' 0 | tr '0' 'A')
test "$(HOME="$long" httrack -O /dev/null -#test=expandhome '~/foo')" == "expanded=~/foo" || exit 1
fi

View File

@@ -59,6 +59,7 @@ TESTS = \
01_engine-pause.test \
01_engine-rcfile.test \
01_engine-reconcile.test \
01_engine-expandhome.test \
01_engine-fsize.test \
01_engine-redirect.test \
01_engine-relative.test \