diff options
author | ozan yigit <ozan.yigit@gmail.com> | 2024-03-11 19:46:47 -0400 |
---|---|---|
committer | ozan yigit <ozan.yigit@gmail.com> | 2024-03-11 19:46:47 -0400 |
commit | 77c8ffa70db4e9819881ec676d3f13f550d02055 (patch) | |
tree | 334d72c9239d50a8c2c547b9ff1f33dd983ca3ac | |
parent | 6a07a6d3bb6313714625f667470290e71545b270 (diff) | |
download | one-true-awk-77c8ffa70db4e9819881ec676d3f13f550d02055.tar.gz |
fix for fnematch use-after-free bug resulting from adjbuf invalidating
the pointers to buf. this is Miguel Pineiro Jr.'s code.
thanks to github user caffe for spotting this.
this code demonstrates the problem:
printf "%8192s\n" | tr " " "=" | ./a.out 'BEGIN{RS="th[^h]+"}{}'
MAX_UTF_BYTES in fnematch has been replaced with awk_mb_cur_max.
-rw-r--r-- | b.c | 28 |
1 files changed, 17 insertions, 11 deletions
@@ -830,8 +830,6 @@ int nematch(fa *f, const char *p0) /* non-empty match, for sub */ } -#define MAX_UTF_BYTES 4 // UTF-8 is up to 4 bytes long - /* * NAME * fnematch @@ -868,16 +866,28 @@ bool fnematch(fa *pfa, FILE *f, char **pbuf, int *pbufsize, int quantum) do { /* - * Call u8_rune with at least MAX_UTF_BYTES ahead in + * Call u8_rune with at least awk_mb_cur_max ahead in * the buffer until EOF interferes. */ - if (k - j < MAX_UTF_BYTES) { - if (k + MAX_UTF_BYTES > buf + bufsize) { + if (k - j < awk_mb_cur_max) { + if (k + awk_mb_cur_max > buf + bufsize) { + char *obuf = buf; adjbuf((char **) &buf, &bufsize, - bufsize + MAX_UTF_BYTES, + bufsize + awk_mb_cur_max, quantum, 0, "fnematch"); + + /* buf resized, maybe moved. update pointers */ + *pbufsize = bufsize; + if (obuf != buf) { + i = buf + (i - obuf); + j = buf + (j - obuf); + k = buf + (k - obuf); + *pbuf = buf; + if (patlen) + patbeg = buf + (patbeg - obuf); + } } - for (n = MAX_UTF_BYTES ; n > 0; n--) { + for (n = awk_mb_cur_max ; n > 0; n--) { *k++ = (c = getc(f)) != EOF ? c : 0; if (c == EOF) { if (ferror(f)) @@ -914,10 +924,6 @@ bool fnematch(fa *pfa, FILE *f, char **pbuf, int *pbufsize, int quantum) s = 2; } while (1); - /* adjbuf() may have relocated a resized buffer. Inform the world. */ - *pbuf = buf; - *pbufsize = bufsize; - if (patlen) { /* * Under no circumstances is the last character fed to |