Fix a buffer over-read of an unfinished macro "%{!" expansion
Problem was in a buffer over-read of the memory right after
the end of the allocated area when expanding of an unfinished macro
starting "%{" that can contain only exclamation marks and question
marks. Like "%{", or "%{!", or "%{??!".
Similar problem as in commit 54f24ec548
with the difference that this problem was not found by a memory
sanitizer.
This is a good opportunity to refactor the corresponding code
(setting variables according to the number of exclamation marks and
question mark after % an before the macro).
This commit is contained in:
parent
57899bd3bf
commit
03909fc4d3
|
@ -1174,6 +1174,20 @@ static void doTrace(MacroBuf mb, int chkexist, int negate,
|
|||
}
|
||||
}
|
||||
|
||||
static const char *setNegateAndCheck(const char *str, int *pnegate, int *pchkexist) {
|
||||
|
||||
*pnegate = 0;
|
||||
*pchkexist = 0;
|
||||
while ((*str == '?') || (*str == '!')) {
|
||||
if (*str == '!')
|
||||
*pnegate = !*pnegate;
|
||||
else
|
||||
(*pchkexist)++;
|
||||
str++;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main macro recursion loop.
|
||||
* @param mb macro expansion state
|
||||
|
@ -1255,21 +1269,10 @@ expandMacro(MacroBuf mb, const char *src, size_t slen)
|
|||
g = ge = NULL;
|
||||
if (mb->depth > 1) /* XXX full expansion for outermost level */
|
||||
tpos = mb->tpos; /* save expansion pointer for printExpand */
|
||||
negate = 0;
|
||||
lastc = NULL;
|
||||
chkexist = 0;
|
||||
switch ((c = *s)) {
|
||||
default: /* %name substitution */
|
||||
while (*s != '\0' && strchr("!?", *s) != NULL) {
|
||||
switch (*s++) {
|
||||
case '!':
|
||||
negate = ((negate + 1) % 2);
|
||||
break;
|
||||
case '?':
|
||||
chkexist++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s = setNegateAndCheck(s, &negate, &chkexist);
|
||||
f = se = s;
|
||||
if (*se == '-')
|
||||
se++;
|
||||
|
@ -1317,16 +1320,7 @@ expandMacro(MacroBuf mb, const char *src, size_t slen)
|
|||
}
|
||||
f = s+1;/* skip { */
|
||||
se++; /* skip } */
|
||||
while (strchr("!?", *f) != NULL) {
|
||||
switch (*f++) {
|
||||
case '!':
|
||||
negate = ((negate + 1) % 2);
|
||||
break;
|
||||
case '?':
|
||||
chkexist++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
f = setNegateAndCheck(f, &negate, &chkexist);
|
||||
for (fe = f; (c = *fe) && !strchr(" :}", c);)
|
||||
fe++;
|
||||
switch (c) {
|
||||
|
|
Loading…
Reference in New Issue