diff options
author | Todd C. Miller <Todd.Miller@sudo.ws> | 2020-07-27 01:03:58 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-27 10:03:58 +0300 |
commit | b82b649aa65fbdff45869d1fd6d72fd2b85946cd (patch) | |
tree | 7c03c0af92460196857a670d65d716c578109c97 /run.c | |
parent | 2a4146ec3027d12e375209e03ed1c5a9ab230da4 (diff) | |
download | one-true-awk-b82b649aa65fbdff45869d1fd6d72fd2b85946cd.tar.gz |
Avoid using stdio streams after they have been closed. (#89)
* In closeall(), skip stdin and flush std{err,out} instead of closing.
Otherwise awk could fclose(stdin) twice (it may appear more than once)
and closing stderr means awk cannot report errors with other streams.
For example, "awk 'BEGIN { getline < "-" }' < /dev/null" will call
fclose(stdin) twice, with undefined results.
* If closefile() is called on std{in,out,err}, freopen() /dev/null instead.
Otherwise, awk will continue trying to perform I/O on a closed stdio
stream, the behavior of which is undefined.
Diffstat (limited to 'run.c')
-rw-r--r-- | run.c | 10 |
1 files changed, 9 insertions, 1 deletions
@@ -1846,7 +1846,10 @@ const char *filename(FILE *fp) continue; if (ferror(files[i].fp)) FATAL("i/o error occurred on %s", files[i].fname); - if (files[i].mode == '|' || files[i].mode == LE) + if (files[i].fp == stdin || files[i].fp == stdout || + files[i].fp == stderr) + stat = freopen("/dev/null", "r+", files[i].fp) == NULL; + else if (files[i].mode == '|' || files[i].mode == LE) stat = pclose(files[i].fp) == -1; else stat = fclose(files[i].fp) == EOF; @@ -1856,6 +1859,7 @@ const char *filename(FILE *fp) xfree(files[i].fname); files[i].fname = NULL; /* watch out for ref thru this */ files[i].fp = NULL; + break; } tempfree(x); x = gettemp(); @@ -1873,8 +1877,12 @@ void closeall(void) continue; if (ferror(files[i].fp)) FATAL( "i/o error occurred on %s", files[i].fname ); + if (files[i].fp == stdin) + continue; if (files[i].mode == '|' || files[i].mode == LE) stat = pclose(files[i].fp) == -1; + else if (files[i].fp == stdout || files[i].fp == stderr) + stat = fflush(files[i].fp) == EOF; else stat = fclose(files[i].fp) == EOF; if (stat) |