Message ID | 20221214233921.m6hpt5a6kb3wgyjl@tarta.nabijaczleweli.xyz (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Herbert Xu |
Headers | show |
Series | parser: don't keep alloca()ing in a loop for substitutions | expand |
наб <nabijaczleweli@nabijaczleweli.xyz> wrote: > > diff --git a/src/parser.c b/src/parser.c > index a552c47..3f7e50a 100644 > --- a/src/parser.c > +++ b/src/parser.c > @@ -898,6 +898,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs) > struct nodelist *bqlist; > int quotef; > int oldstyle; > + char *parsebackq_save; > /* syntax stack */ > struct synstack synbase = { .syntax = syntax }; > struct synstack *synstack = &synbase; > @@ -906,6 +907,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs) > synstack->dblquote = 1; > quotef = 0; > bqlist = NULL; > + parsebackq_save = NULL; > > STARTSTACKSTR(out); > loop: { /* for each line, until end of word */ > @@ -1355,15 +1357,18 @@ badsub: > parsebackq: { > struct nodelist **nlpp; > union node *n; > - char *str; > + char *str, *mstr; > size_t savelen; > struct heredoc *saveheredoclist; > int uninitialized_var(saveprompt); > > - str = NULL; > + str = mstr = NULL; > savelen = out - (char *)stackblock(); > if (savelen > 0) { > - str = alloca(savelen); > + if (savelen > 1024) > + str = mstr = ckmalloc(savelen); > + else > + str = parsebackq_save ?: (parsebackq_save = alloca(1024)); > memcpy(str, stackblock(), savelen); > } > if (oldstyle) { > @@ -1449,6 +1454,7 @@ done: > if (str) { > memcpy(out, str, savelen); > STADJUST(savelen, out); > + free(mstr); You can't just call ckmalloc because that memory will be leaked if there is a longjmp (such as sh_error) before you free it. Cheers,
diff --git a/src/parser.c b/src/parser.c index a552c47..3f7e50a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -898,6 +898,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs) struct nodelist *bqlist; int quotef; int oldstyle; + char *parsebackq_save; /* syntax stack */ struct synstack synbase = { .syntax = syntax }; struct synstack *synstack = &synbase; @@ -906,6 +907,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs) synstack->dblquote = 1; quotef = 0; bqlist = NULL; + parsebackq_save = NULL; STARTSTACKSTR(out); loop: { /* for each line, until end of word */ @@ -1355,15 +1357,18 @@ badsub: parsebackq: { struct nodelist **nlpp; union node *n; - char *str; + char *str, *mstr; size_t savelen; struct heredoc *saveheredoclist; int uninitialized_var(saveprompt); - str = NULL; + str = mstr = NULL; savelen = out - (char *)stackblock(); if (savelen > 0) { - str = alloca(savelen); + if (savelen > 1024) + str = mstr = ckmalloc(savelen); + else + str = parsebackq_save ?: (parsebackq_save = alloca(1024)); memcpy(str, stackblock(), savelen); } if (oldstyle) { @@ -1449,6 +1454,7 @@ done: if (str) { memcpy(out, str, savelen); STADJUST(savelen, out); + free(mstr); } USTPUTC(CTLBACKQ, out); if (oldstyle)