aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorozan yigit <ozan.yigit@gmail.com>2024-05-03 15:50:54 -0400
committerozan yigit <ozan.yigit@gmail.com>2024-05-03 15:50:54 -0400
commit829f5258e66609a91efebe72e18d7cd5e80987f9 (patch)
tree5e30da22841dceb001c73b7821ebba1279e6a5c1
parentd11704b3c3ce8ce47d4b839529fc54ae7f18bc29 (diff)
parentdd2f1c63518aa68b606921dd3ccb01db6b9cf31a (diff)
downloadone-true-awk-829f5258e66609a91efebe72e18d7cd5e80987f9.tar.gz
merge todd's ARGV use-after-free fixes into staging
-rw-r--r--lib.c8
-rwxr-xr-xtestdir/T.argv14
-rw-r--r--tran.c22
3 files changed, 31 insertions, 13 deletions
diff --git a/lib.c b/lib.c
index 0dac1f9..81582d3 100644
--- a/lib.c
+++ b/lib.c
@@ -335,14 +335,16 @@ int readcsvrec(char **pbuf, int *pbufsize, FILE *inf, bool newflag) /* csv can h
char *getargv(int n) /* get ARGV[n] */
{
+ Array *ap;
Cell *x;
char *s, temp[50];
- extern Array *ARGVtab;
+ extern Cell *ARGVcell;
+ ap = (Array *)ARGVcell->sval;
snprintf(temp, sizeof(temp), "%d", n);
- if (lookup(temp, ARGVtab) == NULL)
+ if (lookup(temp, ap) == NULL)
return NULL;
- x = setsymtab(temp, "", 0.0, STR, ARGVtab);
+ x = setsymtab(temp, "", 0.0, STR, ap);
s = getsval(x);
DPRINTF("getargv(%d) returns |%s|\n", n, s);
return s;
diff --git a/testdir/T.argv b/testdir/T.argv
index 55e2754..48ef826 100755
--- a/testdir/T.argv
+++ b/testdir/T.argv
@@ -148,3 +148,17 @@ END {
printf("ARGV[%d] is %s\n", i, ARGV[i])
}' >foo2
diff foo1 foo2 || echo 'BAD: T.argv delete ARGV[2]'
+
+# deleting ARGV used to trigger a use-after-free crash when awk
+# iterates over it to read files.
+printf '' >foo1
+$awk 'BEGIN {
+ delete ARGV
+ ARGV[0] = "awk"
+ ARGV[1] = "/dev/null"
+ ARGC = 2
+} {
+ # this should not be executed
+ print "bad"
+}' foo bar baz >foo2
+diff foo1 foo2 || echo 'BAD: T.argv delete ARGV'
diff --git a/tran.c b/tran.c
index 482eede..ad8234a 100644
--- a/tran.c
+++ b/tran.c
@@ -57,8 +57,7 @@ Cell *fnrloc; /* FNR */
Cell *ofsloc; /* OFS */
Cell *orsloc; /* ORS */
Cell *rsloc; /* RS */
-Array *ARGVtab; /* symbol table containing ARGV[...] */
-Array *ENVtab; /* symbol table containing ENVIRON[...] */
+Cell *ARGVcell; /* cell with symbol table containing ARGV[...] */
Cell *rstartloc; /* RSTART */
Cell *rlengthloc; /* RLENGTH */
Cell *subseploc; /* SUBSEP */
@@ -107,36 +106,39 @@ void syminit(void) /* initialize symbol table with builtin vars */
void arginit(int ac, char **av) /* set up ARGV and ARGC */
{
+ Array *ap;
Cell *cp;
int i;
char temp[50];
ARGC = &setsymtab("ARGC", "", (Awkfloat) ac, NUM, symtab)->fval;
cp = setsymtab("ARGV", "", 0.0, ARR, symtab);
- ARGVtab = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
+ ap = makesymtab(NSYMTAB); /* could be (int) ARGC as well */
free(cp->sval);
- cp->sval = (char *) ARGVtab;
+ cp->sval = (char *) ap;
for (i = 0; i < ac; i++) {
double result;
sprintf(temp, "%d", i);
if (is_number(*av, & result))
- setsymtab(temp, *av, result, STR|NUM, ARGVtab);
+ setsymtab(temp, *av, result, STR|NUM, ap);
else
- setsymtab(temp, *av, 0.0, STR, ARGVtab);
+ setsymtab(temp, *av, 0.0, STR, ap);
av++;
}
+ ARGVcell = cp;
}
void envinit(char **envp) /* set up ENVIRON variable */
{
+ Array *ap;
Cell *cp;
char *p;
cp = setsymtab("ENVIRON", "", 0.0, ARR, symtab);
- ENVtab = makesymtab(NSYMTAB);
+ ap = makesymtab(NSYMTAB);
free(cp->sval);
- cp->sval = (char *) ENVtab;
+ cp->sval = (char *) ap;
for ( ; *envp; envp++) {
double result;
@@ -146,9 +148,9 @@ void envinit(char **envp) /* set up ENVIRON variable */
continue;
*p++ = 0; /* split into two strings at = */
if (is_number(p, & result))
- setsymtab(*envp, p, result, STR|NUM, ENVtab);
+ setsymtab(*envp, p, result, STR|NUM, ap);
else
- setsymtab(*envp, p, 0.0, STR, ENVtab);
+ setsymtab(*envp, p, 0.0, STR, ap);
p[-1] = '='; /* restore in case env is passed down to a shell */
}
}