[PATCH] skip_to_histexp: fix out-of-range access

Grisha Levit <[email protected]> Thu, 5 Mar 2026 15:38:12 -0500
Newsgroups gmane.comp.shells.bash.bugs
Message-ID <[email protected]>
Fix grouping in new[1] conditional in skip_to_histexp to avoid overflow:

    $ ./bash --norc -in <<< $': !-1:0'
    bash-5.3$ : !-1:0
    subst.c:2508:20: runtime error: addition of unsigned offset to 0x611000003240 overflowed to 0x61100000323f
    ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61100000323f at pc 0x000104881e24 bp 0x00016b71fb70 sp 0x00016b71fb68

Also fix the length check for values of slen < 4 (since slen is unsigned).
Alternatively, the check can just be removed since a shorter string will
fail the checks on the next line anyway.

[1]: https://git.gnu.org/cgit/bash.git/diff/subst.c?h=devel&id=044c1acc
---
 subst.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/subst.c b/subst.c
index 67677d33..5cbe5d34 100644
--- a/subst.c
+++ b/subst.c
@@ -2505,8 +2505,8 @@ skip_to_histexp (const char *string, int start, const char *delims, int flags)
 	  continue;
 	}
       else if (histexp_comsub && c == 'c' &&
-	      (i == 0) || shellbreak (string[i-1]) &&	/* incomplete reserved word eligibility test */
-	      (i <= slen - 4) &&
+	      (i == 0 || shellbreak (string[i-1])) &&	/* incomplete reserved word eligibility test */
+	      (i + 4 <= slen) &&
 	      string[i+1] == 'a' && string[i+2] == 's' && string[i+3] == 'e' &&
 	      (shellblank (string[i+4]) || string[i+4] == '\0'))
 	{
@@ -2516,8 +2516,8 @@ skip_to_histexp (const char *string, int start, const char *delims, int flags)
 	  continue;
 	}
       else if (histexp_comsub && c == 'e' &&
-	      (i == 0) || shellbreak (string[i-1]) &&	/* incomplete reserved word eligibility test */
-	      (i <= slen - 4) &&
+	      (i == 0 || shellbreak (string[i-1])) &&	/* incomplete reserved word eligibility test */
+	      (i + 4 <= slen) &&
 	      string[i+1] == 's' && string[i+2] == 'a' && string[i+3] == 'c' &&
 	      (shellbreak (string[i+4]) || string[i+4] == '\0'))
 	{
-- 
2.53.0