awk: fix off-by-one string buffer overflow from gsub
the bug happens when we did the fast exit thru "done" label, where we would not make sure that theres space in the buffer for the NUL terminator. instead, avoid the fast exit and always do the final adjbuf() that makes sure we have space for the NUL terminator. remove the pointless pb checks, they'r wrong (should'v been bp >= buf+bufsz) and adjbuf() already makes sure this can never happen.
This commit is contained in:
parent
af6f03e528
commit
c14ea9fdd1
1 changed files with 7 additions and 14 deletions
|
@ -1865,16 +1865,12 @@ Cell *sub(Node **a, int) /* substitute command */
|
||||||
*pb++ = *sptr++;
|
*pb++ = *sptr++;
|
||||||
}
|
}
|
||||||
*pb = '\0';
|
*pb = '\0';
|
||||||
if (pb > buf + bufsz)
|
|
||||||
FATAL("sub result1 %.30s too big; can't happen", buf);
|
|
||||||
sptr = patbeg + patlen;
|
sptr = patbeg + patlen;
|
||||||
if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
|
if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
|
||||||
adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
|
adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
|
||||||
while ((*pb++ = *sptr++) != 0)
|
while ((*pb++ = *sptr++) != 0)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
if (pb > buf + bufsz)
|
|
||||||
FATAL("sub result2 %.30s too big; can't happen", buf);
|
|
||||||
setsval(x, buf); /* BUG: should be able to avoid copy */
|
setsval(x, buf); /* BUG: should be able to avoid copy */
|
||||||
result = True;;
|
result = True;;
|
||||||
}
|
}
|
||||||
|
@ -1934,11 +1930,9 @@ Cell *gsub(Node **a, int) /* global substitute */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*c == 0) /* at end */
|
if (*c == 0) /* at end */
|
||||||
goto done;
|
break;
|
||||||
adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
|
adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
|
||||||
*pb++ = *c++;
|
*pb++ = *c++;
|
||||||
if (pb > buf + bufsz) /* BUG: not sure of this test */
|
|
||||||
FATAL("gsub result0 %.30s too big; can't happen", buf);
|
|
||||||
mflag = 0;
|
mflag = 0;
|
||||||
}
|
}
|
||||||
else { /* matched nonempty string */
|
else { /* matched nonempty string */
|
||||||
|
@ -1962,10 +1956,12 @@ Cell *gsub(Node **a, int) /* global substitute */
|
||||||
*pb++ = *sptr++;
|
*pb++ = *sptr++;
|
||||||
}
|
}
|
||||||
c = patbeg + patlen;
|
c = patbeg + patlen;
|
||||||
if ((c[-1] == 0) || (*c == 0))
|
if (c[-1] == 0){
|
||||||
goto done;
|
c--;
|
||||||
if (pb > buf + bufsz)
|
break;
|
||||||
FATAL("gsub result1 %.30s too big; can't happen", buf);
|
}
|
||||||
|
if (*c == 0)
|
||||||
|
break;
|
||||||
mflag = 1;
|
mflag = 1;
|
||||||
}
|
}
|
||||||
} while (pmatch(p, t, c));
|
} while (pmatch(p, t, c));
|
||||||
|
@ -1973,9 +1969,6 @@ Cell *gsub(Node **a, int) /* global substitute */
|
||||||
adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
|
adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
|
||||||
while ((*pb++ = *sptr++) != 0)
|
while ((*pb++ = *sptr++) != 0)
|
||||||
;
|
;
|
||||||
done: if (pb > buf + bufsz)
|
|
||||||
FATAL("gsub result2 %.30s too big; can't happen", buf);
|
|
||||||
*pb = '\0';
|
|
||||||
setsval(x, buf); /* BUG: should be able to avoid copy + free */
|
setsval(x, buf); /* BUG: should be able to avoid copy + free */
|
||||||
}
|
}
|
||||||
if (istemp(x))
|
if (istemp(x))
|
||||||
|
|
Loading…
Reference in a new issue