diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2024-05-20 17:55:28 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2024-07-09 02:34:00 +0200 |
commit | fb08d43d44d1fea1f741fafb9aa7e1958a5f69aa (patch) | |
tree | 62fe6944c08f62705be848c0931b80fa0ba2534d | |
parent | eba9b33b4595fbb5f2a64148b1ff3daeab9b3813 (diff) | |
download | busybox-w32-fb08d43d44d1fea1f741fafb9aa7e1958a5f69aa.tar.gz busybox-w32-fb08d43d44d1fea1f741fafb9aa7e1958a5f69aa.tar.bz2 busybox-w32-fb08d43d44d1fea1f741fafb9aa7e1958a5f69aa.zip |
awk: fix use after free (CVE-2023-42363)
function old new delta
evaluate 3377 3385 +8
Fixes https://bugs.busybox.net/show_bug.cgi?id=15865
Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/editors/awk.c b/editors/awk.c index 0981c6735..ff6d6350b 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -2981,19 +2981,14 @@ static var *evaluate(node *op, var *res) | |||
2981 | /* yes, remember where Fields[] is */ | 2981 | /* yes, remember where Fields[] is */ |
2982 | old_Fields_ptr = Fields; | 2982 | old_Fields_ptr = Fields; |
2983 | } | 2983 | } |
2984 | if (opinfo & OF_STR1) { | ||
2985 | L.s = getvar_s(L.v); | ||
2986 | debug_printf_eval("L.s:'%s'\n", L.s); | ||
2987 | } | ||
2988 | if (opinfo & OF_NUM1) { | 2984 | if (opinfo & OF_NUM1) { |
2989 | L_d = getvar_i(L.v); | 2985 | L_d = getvar_i(L.v); |
2990 | debug_printf_eval("L_d:%f\n", L_d); | 2986 | debug_printf_eval("L_d:%f\n", L_d); |
2991 | } | 2987 | } |
2992 | } | 2988 | } |
2993 | /* NB: Must get string/numeric values of L (done above) | 2989 | /* NB: if both L and R are $NNNs, and right one is large, |
2994 | * _before_ evaluate()'ing R.v: if both L and R are $NNNs, | 2990 | * then at this pint L.v points to Fields[NNN1], second |
2995 | * and right one is large, then L.v points to Fields[NNN1], | 2991 | * evaluate() below reallocates and moves (!) Fields[], |
2996 | * second evaluate() reallocates and moves (!) Fields[], | ||
2997 | * R.v points to Fields[NNN2] but L.v now points to freed mem! | 2992 | * R.v points to Fields[NNN2] but L.v now points to freed mem! |
2998 | * (Seen trying to evaluate "$444 $44444") | 2993 | * (Seen trying to evaluate "$444 $44444") |
2999 | */ | 2994 | */ |
@@ -3013,6 +3008,16 @@ static var *evaluate(node *op, var *res) | |||
3013 | debug_printf_eval("R.s:'%s'\n", R.s); | 3008 | debug_printf_eval("R.s:'%s'\n", R.s); |
3014 | } | 3009 | } |
3015 | } | 3010 | } |
3011 | /* Get L.s _after_ R.v is evaluated: it may have realloc'd L.v | ||
3012 | * so we must get the string after "old_Fields_ptr" correction | ||
3013 | * above. Testcase: x = (v = "abc", gsub("b", "X", v)); | ||
3014 | */ | ||
3015 | if (opinfo & OF_RES1) { | ||
3016 | if (opinfo & OF_STR1) { | ||
3017 | L.s = getvar_s(L.v); | ||
3018 | debug_printf_eval("L.s:'%s'\n", L.s); | ||
3019 | } | ||
3020 | } | ||
3016 | 3021 | ||
3017 | debug_printf_eval("switch(0x%x)\n", XC(opinfo & OPCLSMASK)); | 3022 | debug_printf_eval("switch(0x%x)\n", XC(opinfo & OPCLSMASK)); |
3018 | switch (XC(opinfo & OPCLSMASK)) { | 3023 | switch (XC(opinfo & OPCLSMASK)) { |