66 lines
2.1 KiB
Diff
66 lines
2.1 KiB
Diff
From aa7272a6e1184cdd21ab8f89200219abd8053eda Mon Sep 17 00:00:00 2001
|
|
From: "Arnold D. Robbins" <arnold@skeeve.com>
|
|
Date: Mon, 6 Apr 2026 10:56:38 +0300
|
|
Subject: [PATCH] Add overflow checking in do_sub for 32 bit systems.
|
|
|
|
---
|
|
ChangeLog | 9 +++++++++
|
|
builtin.c | 25 ++++++++++++++++++++-----
|
|
2 files changed, 29 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/builtin.c b/builtin.c
|
|
index f6a37ac76..f33525d5b 100644
|
|
--- a/builtin.c
|
|
+++ b/builtin.c
|
|
@@ -1819,11 +1819,13 @@ do_sub(int nargs, unsigned int flags)
|
|
long current;
|
|
bool lastmatchnonzero;
|
|
char *mb_indices = NULL;
|
|
+ const char *fname = NULL; // for fatal message, below
|
|
|
|
if ((flags & GENSUB) != 0) {
|
|
double d;
|
|
NODE *glob_flag;
|
|
|
|
+ fname = "gensub";
|
|
check_exact_args(nargs, "gensub", 4);
|
|
|
|
tmp = PEEK(3);
|
|
@@ -1855,11 +1857,9 @@ do_sub(int nargs, unsigned int flags)
|
|
}
|
|
DEREF(glob_flag);
|
|
} else {
|
|
- if ((flags & GSUB) != 0) {
|
|
- check_exact_args(nargs, "gsub", 3);
|
|
- } else {
|
|
- check_exact_args(nargs, "sub", 3);
|
|
- }
|
|
+ fname = ((flags & GSUB) != 0) ? "gsub" : "sub";
|
|
+
|
|
+ check_exact_args(nargs, fname, 3);
|
|
|
|
/* take care of regexp early, in case re_update is fatal */
|
|
|
|
@@ -1975,6 +1975,21 @@ do_sub(int nargs, unsigned int flags)
|
|
* vary since ampersand is actual text of regexp match.
|
|
*/
|
|
|
|
+ // 4/2026: This overflow check simply provides a fatal
|
|
+ // message instead of letting realloc() die later after
|
|
+ // a buffer overrun. It simply makes the user experience better,
|
|
+ // but does not prevent gawk from dying miserably. I suppose
|
|
+ // it's worth the trouble, but just barely.
|
|
+
|
|
+ /* uint64_t so the product is 64-bit even on 32-bit ILP32 builds */
|
|
+ uint64_t repl_contribution =
|
|
+ (uint64_t)(unsigned int)ampersands
|
|
+ * (uint64_t)(uintptr_t)(matchend - matchstart);
|
|
+ if (repl_contribution > (uint64_t)SIZE_MAX
|
|
+ || repl_contribution > (uint64_t)SIZE_MAX - (size_t)(matchend - text)
|
|
+ - repllen - 1)
|
|
+ fatal(_("%s: replacement expansion too large"), fname);
|
|
+
|
|
/*
|
|
* add 1 to len to handle "empty" case where
|
|
* matchend == matchstart and we force a match on a single
|