ref: 77c8ffa70db4e9819881ec676d3f13f550d02055
parent: 6a07a6d3bb6313714625f667470290e71545b270
author: ozan yigit <ozan.yigit@gmail.com>
date: Mon Mar 11 15:46:47 EDT 2024
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.
--- a/b.c
+++ b/b.c
@@ -830,8 +830,6 @@
}
-#define MAX_UTF_BYTES 4 // UTF-8 is up to 4 bytes long
-
/*
* NAME
* fnematch
@@ -868,16 +866,28 @@
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))
@@ -913,10 +923,6 @@
j = i;
s = 2;
} while (1);
-
- /* adjbuf() may have relocated a resized buffer. Inform the world. */
- *pbuf = buf;
- *pbufsize = bufsize;
if (patlen) {/*
--
⑨