From 6e5be14727843d441f7c69a6e49473eabf049a9a Mon Sep 17 00:00:00 2001 From: Grisha Levit Date: Fri, 8 Sep 2023 11:10:16 -0400 Subject: [PATCH] fix [[ -t X ]] segfault Since the change that made `test -t FD' report an error for non-numeric values of FD: $ [[ -t X ]] bash: [[: X: integer expected Segmentation fault Below patch wraps all [[ test execution in a new function that provides a jump target and returns an exit status usable directly by the cond_node code -- so the above now has an exit status of 2 like the test builtin. --- execute_cmd.c | 6 ++---- test.c | 25 +++++++++++++++++++++++-- test.h | 3 +-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/execute_cmd.c b/execute_cmd.c index 2c99493b..6cbb00df 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -3942,7 +3942,7 @@ execute_cond_node (COND_COM *cond) if (varop) oa = set_expand_once (0, 0); /* no-op for compatibility levels <= 51 */ #endif - result = unary_test (cond->op->word, arg1, varflag) ? EXECUTION_SUCCESS : EXECUTION_FAILURE; + result = test_run_test (cond->op->word, arg1, NULL, varflag); #if defined (ARRAY_VARS) if (varop) array_expand_once = oa; @@ -4022,9 +4022,7 @@ execute_cond_node (COND_COM *cond) #endif /* COND_REGEXP */ { extended_glob = 1; - result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP|TEST_LOCALE) - ? EXECUTION_SUCCESS - : EXECUTION_FAILURE; + result = test_run_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP|TEST_LOCALE); extended_glob = extglob_flag; } if (arg1 != nullstr) diff --git a/test.c b/test.c index aa01926c..d3906c6e 100644 --- a/test.c +++ b/test.c @@ -118,6 +118,9 @@ static void test_syntax_error (char *, char *) __attribute__((__noreturn__)); static void beyond (void) __attribute__((__noreturn__)); static void integer_expected_error (char *) __attribute__((__noreturn__)); +static int unary_test (char *, char *, int); +static int binary_test (char *, char *, char *, int); + static int unary_operator (void); static int binary_operator (void); static int two_arguments (void); @@ -376,7 +379,7 @@ patcomp (char *string, char *pat, int op) return ((op == EQ) ? (m == 0) : (m != 0)); } -int +static int binary_test (char *op, char *arg1, char *arg2, int flags) { int patmatch; @@ -509,7 +512,7 @@ unary_operator (void) return (unary_test (op, argv[pos - 1], 0)); } -int +static int unary_test (char *op, char *arg, int flags) { intmax_t r; @@ -857,6 +860,24 @@ posixtest (void) return (value); } +/* If ARG2 is not NULL, dispatch a binary test, otherwise a unary test. + For use by execute_cond_node. */ +int +test_run_test (char *op, char *arg1, char *arg2, int flags) +{ + int code, ret; + + code = setjmp_nosigs (test_exit_buf); + + if (code) + return test_error_return; + + ret = arg2 ? binary_test (op, arg1, arg2, flags) + : unary_test (op, arg1, flags); + + return (ret ? EXECUTION_SUCCESS : EXECUTION_FAILURE); +} + /* * [: * '[' expr ']' diff --git a/test.h b/test.h index 2a816892..aa04c7a7 100644 --- a/test.h +++ b/test.h @@ -32,8 +32,7 @@ extern int test_unop (char *); extern int test_binop (char *); -extern int unary_test (char *, char *, int); -extern int binary_test (char *, char *, char *, int); +extern int test_run_test (char *, char *, char *, int); extern int test_command (int, char **); -- 2.42.0