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.
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