The attached patch should fix the issue. We were treating "-o" and "-a" as if they could be unary operators, which they cannot be. They are either a string operand or a binary operator.
Will push it in a bit. Collin
>From 4150550035a3978a5c63884c497d0cd29863283e Mon Sep 17 00:00:00 2001 Message-ID: <4150550035a3978a5c63884c497d0cd29863283e.1785002034.git.collin.fu...@gmail.com> From: Collin Funk <[email protected]> Date: Thu, 23 Jul 2026 21:12:42 -0700 Subject: [PATCH] test: handle adjacent binary operators * NEWS: Mention the bug fix. * cfg.mk (exclude_file_name_regexp--sc_prohibit_test_minus_ao): Exclude NEWS. * src/test.c (term): Treat '-a' and '-o' as strings instead of expecting them to be valid unary operators. (two_arguments): Don't treat '-a' and '-o' as possible unary operators. * tests/test/test.pl: Add some test cases. --- NEWS | 5 +++++ cfg.mk | 2 +- src/test.c | 8 ++++---- tests/test/test.pl | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index d47d9517e..059027625 100644 --- a/NEWS +++ b/NEWS @@ -44,6 +44,11 @@ GNU coreutils NEWS -*- outline -*- 'tee' no longer treats short writes as errors. [bug introduced in coreutils-9.11] + 'test' no longer treats '-a' and '-o' as binary operators when given as + strings to a binary operator. E.g., 'test -a -a -a' exits successfully + instead of exiting with an error. + [This bug was present in "the beginning".] + 'unexpand -t' no longer overflows a heap buffer, for tab values > SIZE_MAX/16, or with multi-byte blank characters longer than the tab value. [bugs introduced in coreutils-9.11] diff --git a/cfg.mk b/cfg.mk index 90e6a21d1..b21b7dc03 100644 --- a/cfg.mk +++ b/cfg.mk @@ -950,7 +950,7 @@ exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \ ^m4/stat-prog\.m4$$ exclude_file_name_regexp--sc_prohibit_fail_0 = \ (^.*/git-hooks/commit-msg|^tests/init\.sh|Makefile\.am|\.mk|.*\.texi)$$ -exclude_file_name_regexp--sc_prohibit_test_minus_ao = doc/.*\.texi$$ +exclude_file_name_regexp--sc_prohibit_test_minus_ao = NEWS|doc/.*\.texi$$ exclude_file_name_regexp--sc_prohibit_atoi_atof = ^lib/euidaccess-stat\.c$$ # longlong.h is maintained elsewhere. diff --git a/src/test.c b/src/test.c index 692c37263..3cf314276 100644 --- a/src/test.c +++ b/src/test.c @@ -265,7 +265,8 @@ term (void) value = binary_operator (false, bop); /* It might be a switch type argument. */ - else if (argv[pos][0] == '-' && argv[pos][1] && argv[pos][2] == '\0') + else if (argv[pos][0] == '-' && argv[pos][1] && argv[pos][1] != 'a' + && argv[pos][1] != 'o' && argv[pos][2] == '\0') value = unary_operator (); else { @@ -565,9 +566,8 @@ two_arguments (void) advance (false); value = ! one_argument (); } - else if (argv[pos][0] == '-' - && argv[pos][1] != '\0' - && argv[pos][2] == '\0') + else if (argv[pos][0] == '-' && argv[pos][1] && argv[pos][1] != 'a' + && argv[pos][1] != 'o' && argv[pos][2] == '\0') { value = unary_operator (); } diff --git a/tests/test/test.pl b/tests/test/test.pl index 0f0a93d67..9b722191d 100755 --- a/tests/test/test.pl +++ b/tests/test/test.pl @@ -204,6 +204,24 @@ my @Tests = ['greater-collate-3', "'a' '>' 'b'", {EXIT=>1}], ); +# Test the behavior of multiple adjacent binary operators. +# These would not behave correctly in coreutils-9.11 and earlier. +my $i = 1; +my @operands = ('-a', '-o', "''"); +for my $b ('-a', '-o') + { + for my $a (@operands) + { + for my $c (@operands) + { + push @Tests, ["multiple-binary-" . ++$i, "$a $b $c", + {EXIT=>0 + (($b eq '-o') + ? ($a eq "''" && $c eq "''") + : ($a eq "''" || $c eq "''"))}]; + } + } + } + @Tests = add_inverse_op_tests \@Tests; @Tests = add_pn_tests \@Tests; -- 2.55.0
