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 <grishale...@gmail.com>
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

Reply via email to