Signed-off-by: liuxu <liuxu156@huawei.com> (cherry picked from commit 5bdec6d07aad71a4f8be4e43076a290b72c2cd96)
100 lines
2.9 KiB
Diff
100 lines
2.9 KiB
Diff
From 09656b9beb583eee73b58f64e0e43c0df262c99c Mon Sep 17 00:00:00 2001
|
|
From: liuxu <liuxu156@huawei.com>
|
|
Date: Wed, 19 Jun 2024 11:32:49 +0800
|
|
Subject: [PATCH 3/4] awk: fix use-after-realloc (CVE-2021-42380), closes 15601
|
|
|
|
backport from upstream:
|
|
https://git.alpinelinux.org/aports/plain/main/busybox/0029-awk-fix-use-after-realloc-CVE-2021-42380-closes-1560.patch
|
|
|
|
Signed-off-by: liuxu <liuxu156@huawei.com>
|
|
---
|
|
editors/awk.c | 34 ++++++++++++++++++++++++++++------
|
|
1 file changed, 28 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/editors/awk.c b/editors/awk.c
|
|
index e1d510c..7a73f04 100644
|
|
--- a/editors/awk.c
|
|
+++ b/editors/awk.c
|
|
@@ -558,7 +558,7 @@ struct globals {
|
|
const char *g_progname;
|
|
int g_lineno;
|
|
int nfields;
|
|
- int maxfields; /* used in fsrealloc() only */
|
|
+ unsigned maxfields;
|
|
var *Fields;
|
|
char *g_pos;
|
|
char g_saved_ch;
|
|
@@ -1965,9 +1965,9 @@ static void fsrealloc(int size)
|
|
{
|
|
int i, newsize;
|
|
|
|
- if (size >= maxfields) {
|
|
- /* Sanity cap, easier than catering for overflows */
|
|
- if (size > 0xffffff)
|
|
+ if ((unsigned)size >= maxfields) {
|
|
+ /* Sanity cap, easier than catering for over/underflows */
|
|
+ if ((unsigned)size > 0xffffff)
|
|
bb_die_memory_exhausted();
|
|
|
|
i = maxfields;
|
|
@@ -2925,6 +2925,7 @@ static var *evaluate(node *op, var *res)
|
|
uint32_t opinfo;
|
|
int opn;
|
|
node *op1;
|
|
+ var *old_Fields_ptr;
|
|
|
|
opinfo = op->info;
|
|
opn = (opinfo & OPNMASK);
|
|
@@ -2933,10 +2934,16 @@ static var *evaluate(node *op, var *res)
|
|
debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn);
|
|
|
|
/* execute inevitable things */
|
|
+ old_Fields_ptr = NULL;
|
|
if (opinfo & OF_RES1) {
|
|
if ((opinfo & OF_REQUIRED) && !op1)
|
|
syntax_error(EMSG_TOO_FEW_ARGS);
|
|
L.v = evaluate(op1, TMPVAR0);
|
|
+ /* Does L.v point to $n variable? */
|
|
+ if ((size_t)(L.v - Fields) < maxfields) {
|
|
+ /* yes, remember where Fields[] is */
|
|
+ old_Fields_ptr = Fields;
|
|
+ }
|
|
if (opinfo & OF_STR1) {
|
|
L.s = getvar_s(L.v);
|
|
debug_printf_eval("L.s:'%s'\n", L.s);
|
|
@@ -2955,14 +2962,29 @@ static var *evaluate(node *op, var *res)
|
|
*/
|
|
if (opinfo & OF_RES2) {
|
|
R.v = evaluate(op->r.n, TMPVAR1);
|
|
- //TODO: L.v may be invalid now, set L.v to NULL to catch bugs?
|
|
- //L.v = NULL;
|
|
+ /* Seen in $5=$$5=$0:
|
|
+ * Evaluation of R.v ($$5=$0 expression)
|
|
+ * made L.v ($5) invalid. It's detected here.
|
|
+ */
|
|
+ if (old_Fields_ptr) {
|
|
+ //if (old_Fields_ptr != Fields)
|
|
+ // debug_printf_eval("L.v moved\n");
|
|
+ L.v += Fields - old_Fields_ptr;
|
|
+ }
|
|
if (opinfo & OF_STR2) {
|
|
R.s = getvar_s(R.v);
|
|
debug_printf_eval("R.s:'%s'\n", R.s);
|
|
}
|
|
}
|
|
|
|
+ /* Must get L.s after R.v is evaluated in case it realloc's L.v.
|
|
+ * eg: x = (v = "abc", gsub("b", "X", v));
|
|
+ */
|
|
+ if ((opinfo & OF_RES1) && (opinfo & OF_STR1)) {
|
|
+ L.s = getvar_s(L.v);
|
|
+ debug_printf_eval("L.s:'%s'\n", L.s);
|
|
+ }
|
|
+
|
|
debug_printf_eval("switch(0x%x)\n", XC(opinfo & OPCLSMASK));
|
|
switch (XC(opinfo & OPCLSMASK)) {
|
|
|
|
--
|
|
2.43.0
|
|
|