ref: 681f270acd130d2c0d6aa78e1caf9dc3a1fcc3fb
parent: 11e0cd792213373300d37a6a7ad3157f28416299
author: qwx <qwx@sciops.net>
date: Sun Oct 26 18:00:39 EDT 2025
awk: fix use-after-free in split when the string passed to split is an element of the array also passed, e.g. `split(a[x], a)', we don't want to lose the string value when reseting the array. however, the cell is freed during the reset, and y is now invalid anyway. instead, detect this case and strdup the string if needed. the alternative solution is to always strdup the string, but this has no practical performance impact even for large arrays, the intent is clearer and avoids the allocation in all other cases. revealed by crash in t.split2a.
--- a/run.c
+++ b/run.c
@@ -1238,12 +1238,13 @@
Cell *split(Node **a, int) /* split(a[0], a[1], a[2]); a[3] is type */
{Cell *x = 0, *y, *ap;
- char *s, *t, *fs = 0;
+ char *s, *ds, *t, *fs = 0;
char temp, num[50];
Awkfloat f;
int n, nb, sep, arg3type;
y = execute(a[0]); /* source string */
+ ds = nil;
s = getsval(y);
arg3type = ptoi(a[3]);
if (a[2] == 0) /* fs string */
@@ -1257,10 +1258,9 @@
FATAL("illegal type of split");sep = *fs;
ap = execute(a[1]); /* array name */
- n = y->tval;
- y->tval |= DONTFREE; /* split(a[x], a); */
+ if (isarr(ap) && lookup(y->nval, (Array *)ap->sval) != nil)
+ ds = s = tostring(s);
freesymtab(ap);
- y->tval = n;
dprint( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) );ap->tval &= ~STR;
ap->tval |= ARR;
@@ -1359,6 +1359,7 @@
break;
}
}
+ free(ds);
if (istemp(ap))
tfree(ap);
if (istemp(y))
--
⑨