aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorozan yigit <ozan.yigit@gmail.com>2024-03-11 19:46:47 -0400
committerozan yigit <ozan.yigit@gmail.com>2024-03-11 19:46:47 -0400
commit77c8ffa70db4e9819881ec676d3f13f550d02055 (patch)
tree334d72c9239d50a8c2c547b9ff1f33dd983ca3ac
parent6a07a6d3bb6313714625f667470290e71545b270 (diff)
downloadone-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.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/b.c b/b.c
index 4c438fa..870eecf 100644
--- a/b.c
+++ b/b.c
@@ -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