[PATCH] ash: fix out-of-bounds read in ifsbreakup()
Sanghyun Park via busybox <[email protected]> Tue, 16 Jun 2026 12:19:01 +0900
| Newsgroups | gmane.linux.busybox |
|---|---|
| Message-ID | <[email protected]> |
ifsbreakup() skips over CTLESC before testing the following byte against IFS. If CTLESC is the last byte in the recorded region, the scan advances to the region end and can dereference one byte past it. The recorded region can also be stale after error unwinding, so cap each scan to the current stack block before walking it and make the final empty-string check respect the same bound. Signed-off-by: Sanghyun Park <[email protected]> --- shell/ash.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index fb887f3..cda6c85 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6412,13 +6412,16 @@ ifsbreakup(char *string, struct arglist *arglist) struct ifsregion *ifsp; struct strlist *sp; char *start; + char *end; char *p; char *q; + char *stack_end; const char *ifs, *realifs; int ifsspc; int nulonly; start = string; + stack_end = (char *)stackblock() + stackblocksize(); if (ifslastp != NULL) { ifsspc = 0; nulonly = 0; @@ -6428,14 +6431,26 @@ ifsbreakup(char *string, struct arglist *arglist) int afternul; p = string + ifsp->begoff; + end = string + ifsp->endoff; + if (end > stack_end) + end = stack_end; + if (p >= end) { + ifsp = ifsp->next; + continue; + } afternul = nulonly; nulonly = ifsp->nulonly; ifs = nulonly ? nullstr : realifs; ifsspc = 0; - while (p < string + ifsp->endoff) { + while (p < end) { q = p; - if ((unsigned char)*p == CTLESC) + if ((unsigned char)*p == CTLESC) { p++; + if (p >= end) { + p = q; + break; + } + } if (!strchr(ifs, *p)) { p++; continue; @@ -6456,12 +6471,17 @@ ifsbreakup(char *string, struct arglist *arglist) p++; if (!nulonly) { for (;;) { - if (p >= string + ifsp->endoff) { + if (p >= end) { break; } q = p; - if ((unsigned char)*p == CTLESC) + if ((unsigned char)*p == CTLESC) { p++; + if (p >= end) { + p = q; + break; + } + } if (strchr(ifs, *p) == NULL) { p = q; break; @@ -6486,7 +6506,7 @@ ifsbreakup(char *string, struct arglist *arglist) goto add; } - if (!*start) + if (start >= stack_end || !*start) return; add: -- 2.48.1