[PATCH] cmd: test: add bug-compatibility special case for 'test -n'
Rasmus Villemoes
ravi at prevas.dk
Mon Mar 30 16:01:06 CEST 2026
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 <franz.schnyder at toradex.com>
Signed-off-by: Rasmus Villemoes <ravi at prevas.dk>
---
I'm offline for the next 7+ days, so wanted to send this out now
since v2026.04 is about to be released and next merged to master.
I'm not sure this is the best fix, an alternative is to just drop the
argc < 3 support and rely on the previous quirk.
cmd/test.c | 15 ++++++++++++++-
test/hush/if.c | 8 ++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
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 <arg>' should be equivalent to 'test -n <arg>',
* i.e. true if and only if <arg> 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);
--
2.53.0
More information about the U-Boot
mailing list