mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-19 03:31:14 +02:00
45025: fix re-entrancy problem with memory management in readoutput().
This could cause a signal received during $(...) to corrupt memory.
This commit is contained in:
parent
b540d74b2b
commit
1baf0d1f55
2 changed files with 42 additions and 25 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2019-12-15 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||||
|
|
||||||
|
* 45025: Src/exec.c: fix re-entrancy problem with memory
|
||||||
|
management in readoutput(). This could cause a signal
|
||||||
|
received during $(...) to corrupt memory.
|
||||||
|
|
||||||
2019-12-14 dana <dana@dana.is>
|
2019-12-14 dana <dana@dana.is>
|
||||||
|
|
||||||
* unposted: Config/version.mk, Etc/FAQ.yo, README: Update for
|
* unposted: Config/version.mk, Etc/FAQ.yo, README: Update for
|
||||||
|
|
61
Src/exec.c
61
Src/exec.c
|
@ -4646,19 +4646,25 @@ getoutput(char *cmd, int qt)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read output of command substitution */
|
/* read output of command substitution
|
||||||
|
*
|
||||||
|
* The file descriptor "in" is closed by the function.
|
||||||
|
*
|
||||||
|
* "qt" indicates if the substitution was in double quotes.
|
||||||
|
*
|
||||||
|
* "readerror", if not NULL, is used to return any error that
|
||||||
|
* occurred during the read.
|
||||||
|
*/
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
mod_export LinkList
|
mod_export LinkList
|
||||||
readoutput(int in, int qt, int *readerror)
|
readoutput(int in, int qt, int *readerror)
|
||||||
{
|
{
|
||||||
LinkList ret;
|
LinkList ret;
|
||||||
char *buf, *ptr;
|
char *buf, *bufptr, *ptr, inbuf[64];
|
||||||
int bsiz, c, cnt = 0;
|
int bsiz, c, cnt = 0, readret;
|
||||||
FILE *fin;
|
|
||||||
int q = queue_signal_level();
|
int q = queue_signal_level();
|
||||||
|
|
||||||
fin = fdopen(in, "r");
|
|
||||||
ret = newlinklist();
|
ret = newlinklist();
|
||||||
ptr = buf = (char *) hcalloc(bsiz = 64);
|
ptr = buf = (char *) hcalloc(bsiz = 64);
|
||||||
/*
|
/*
|
||||||
|
@ -4670,33 +4676,38 @@ readoutput(int in, int qt, int *readerror)
|
||||||
*/
|
*/
|
||||||
dont_queue_signals();
|
dont_queue_signals();
|
||||||
child_unblock();
|
child_unblock();
|
||||||
while ((c = fgetc(fin)) != EOF || errno == EINTR) {
|
for (;;) {
|
||||||
if (c == EOF) {
|
readret = read(in, inbuf, 64);
|
||||||
errno = 0;
|
if (readret <= 0) {
|
||||||
clearerr(fin);
|
if (readret < 0 && errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (imeta(c)) {
|
for (bufptr = inbuf; bufptr < inbuf + readret; bufptr++) {
|
||||||
*ptr++ = Meta;
|
c = *bufptr;
|
||||||
c ^= 32;
|
if (imeta(c)) {
|
||||||
cnt++;
|
*ptr++ = Meta;
|
||||||
}
|
c ^= 32;
|
||||||
if (++cnt >= bsiz) {
|
cnt++;
|
||||||
char *pp;
|
}
|
||||||
queue_signals();
|
if (++cnt >= bsiz) {
|
||||||
pp = (char *) hcalloc(bsiz *= 2);
|
char *pp;
|
||||||
dont_queue_signals();
|
queue_signals();
|
||||||
|
pp = (char *) hcalloc(bsiz *= 2);
|
||||||
|
dont_queue_signals();
|
||||||
|
|
||||||
memcpy(pp, buf, cnt - 1);
|
memcpy(pp, buf, cnt - 1);
|
||||||
ptr = (buf = pp) + cnt - 1;
|
ptr = (buf = pp) + cnt - 1;
|
||||||
|
}
|
||||||
|
*ptr++ = c;
|
||||||
}
|
}
|
||||||
*ptr++ = c;
|
|
||||||
}
|
}
|
||||||
child_block();
|
child_block();
|
||||||
restore_queue_signals(q);
|
restore_queue_signals(q);
|
||||||
if (readerror)
|
if (readerror)
|
||||||
*readerror = ferror(fin) ? errno : 0;
|
*readerror = readret < 0 ? errno : 0;
|
||||||
fclose(fin);
|
close(in);
|
||||||
while (cnt && ptr[-1] == '\n')
|
while (cnt && ptr[-1] == '\n')
|
||||||
ptr--, cnt--;
|
ptr--, cnt--;
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
|
Loading…
Reference in a new issue