From: Rasmus Villemoes Date: Mon, 30 Mar 2026 14:01:06 +0000 (+0200) Subject: cmd: test: add bug-compatibility special case for 'test -n' X-Git-Tag: v2026.07-rc1~21^2~27 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=f7e7c55e53e8;p=thirdparty%2Fu-boot.git cmd: test: add bug-compatibility special case for 'test -n' It turns out that there is lots of code in the wild, including in the U-Boot tree itself, which used to rely on test -n $somevar to yield false when $somevar is not defined or empty. See for example all the occurrences of 'test -n $fdtfile'. That was really only a quirk of the implementation that refused calls with argc < 3, and not because it was interpreted as test -n "$somevar" which is how this should be spelled. While not exactly conforming to POSIX, we can accomodate such scripts by special-casing a single argument "-n" to be interpreted as if it comes from code as above with empty $somevar. Since we only just added the ability to test a string for emptiness using the single-argument form, it is very unlikely that there is code doing test "$str" which would now fail if $str happens to be exactly "-n"; such a test should really always be spelled test -n "$str" Fixes: 8b0619579b2 ("cmd: test: fix handling of single-argument form of test") Reported-by: Franz Schnyder Signed-off-by: Rasmus Villemoes Reviewed-by: Simon Glass --- diff --git a/cmd/test.c b/cmd/test.c index 0d0f090386c..c76ebf800ee 100644 --- a/cmd/test.c +++ b/cmd/test.c @@ -75,12 +75,25 @@ static int do_test(struct cmd_tbl *cmdtp, int flag, int argc, * Per POSIX, 'test' with 0 arguments should return 1, while * 'test ' should be equivalent to 'test -n ', * i.e. true if and only if is not empty. + * + * However, due to previous versions of U-Boot unconditionally + * returning false when 'test' was given less than two + * arguments, there are existing scripts that do + * + * test -n $somevar + * + * (i.e. without properly quoting $somevar) and expecting that + * to return false when $somevar expands to nothing. It is + * quite unlikely that anyone would use the single-argument + * form to test a string for being empty and a possible + * non-empty value for that string to be exactly "-n". So we + * interpret 'test -n' as if it was 'test -n ""'. */ if (argc < 2) return 1; if (argc == 2) - return !strcmp(argv[1], ""); + return !strcmp(argv[1], "") || !strcmp(argv[1], "-n"); #ifdef DEBUG { diff --git a/test/hush/if.c b/test/hush/if.c index 6129e2c530c..6117c37e53c 100644 --- a/test/hush/if.c +++ b/test/hush/if.c @@ -41,6 +41,10 @@ static int hush_test_if_base(struct unit_test_state *uts) sprintf(if_formatted, if_format, "test 'abc'"); ut_assertok(run_command(if_formatted, 0)); + /* Special case: 'test -n' interpreted as 'test -n ""'. */ + sprintf(if_formatted, if_format, "test '-n'"); + ut_asserteq(1, run_command(if_formatted, 0)); + return 0; } HUSH_TEST(hush_test_if_base, 0); @@ -385,6 +389,10 @@ static int hush_test_lbracket_alias(struct unit_test_state *uts) ut_asserteq(1, run_command(if_formatted, 0)); ut_assert_nextline(missing_rbracket_error); + /* Special case: '[ -n ]' interpreted as '[ -n "" ]'. */ + sprintf(if_formatted, if_format, "[ -n ]"); + ut_asserteq(1, run_command(if_formatted, 0)); + return 0; } HUSH_TEST(hush_test_lbracket_alias, UTF_CONSOLE);