[PATCH #62] Fixed buffer overrun. Reworked to not use dstring for more

efficient parsing.
This commit is contained in:
Jim Monte 2019-06-01 19:41:42 +02:00 committed by Holger Vogt
parent 24a13736bd
commit e92e2c7362
2 changed files with 93 additions and 53 deletions

View File

@ -22,7 +22,7 @@ int cieq(const char *p, const char *s);
int ciprefix(const char *p, const char *s); int ciprefix(const char *p, const char *s);
void strtolower(char *str); void strtolower(char *str);
void strtoupper(char *str); void strtoupper(char *str);
char * stripWhiteSpacesInsideParens(char *str); char * stripWhiteSpacesInsideParens(const char *str);
char * gettok(char **s); char * gettok(char **s);
char * gettok_instance(char **); char * gettok_instance(char **);
char * gettok_char(char **s, char p, bool inc_p, bool nested); char * gettok_char(char **s, char p, bool inc_p, bool nested);

View File

@ -275,7 +275,6 @@ cimatch(char *p, char *s)
* since I didn't want to break any fcns which called it from elsewhere than * since I didn't want to break any fcns which called it from elsewhere than
* subckt.c. -- SDB 12.3.2003. * subckt.c. -- SDB 12.3.2003.
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/
char * char *
gettok(char **s) gettok(char **s)
{ {
@ -350,44 +349,63 @@ nexttok(const char *s)
char * char *
gettok_iv(char **s) gettok_iv(char **s)
{ {
char c; char *p_src = *s; /* location in source string */
int paren; char c; /* current char */
char *token; /* return token */
SPICE_DSTRING buf; /* allow any length string */
paren = 0; /* Step past whitespace and '=' */
while (isspace_c(**s) || (**s == '=')) while (isspace_c(c = *p_src) || (c == '=')) {
(*s)++; p_src++;
}
if ((!**s) || ((**s != 'v') && (**s != 'i') && (**s != 'V') && (**s != 'I'))) /* Test for valid leading character */
return NULL; if (((c =*p_src) == '\0') ||
((c != 'v') && (c != 'i') && (c != 'V') && (c != 'I'))) {
*s = p_src; /* update position in string */
return (char *) NULL;
}
/* Allocate buffer for token being returned */
char * const token = TMALLOC(char, strlen(p_src) + 1);
char *p_dst = token; /* location in token */
// initialize string
spice_dstring_init(&buf);
// add v or i to buf // add v or i to buf
spice_dstring_append_char(&buf, *(*s)++); *p_dst++ = *p_src++;
while ((c = **s) != '\0') { {
if (c == '(') int n_paren = 0;
paren += 1; /* Skip any space between v/V/i/I and '(' */
else if (c == ')') p_src = skip_ws(p_src);
paren -= 1;
if (isspace_c(c)) while ((c = *p_src) != '\0') {
(*s)++; /* Keep track of nesting level */
if (c == '(') {
n_paren++;
}
else if (c == ')') {
n_paren--;
}
if (isspace_c(c)) { /* Do not copy whitespace to output */
p_src++;
}
else { else {
spice_dstring_append_char(&buf, *(*s)++); *p_dst++ = *p_src++;
if (paren == 0) if (n_paren == 0) {
break; break;
} }
} }
while (isspace_c(**s) || **s == ',')
(*s)++;
token = copy(spice_dstring_value(&buf));
spice_dstring_free(&buf);
return token;
} }
}
/* Step past whitespace and ',' */
while (isspace_c(c = *p_src) || (c == ',')) {
p_src++;
}
*s = p_src; /* update position in string */
return token;
} /* end of function gettok_iv */
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
@ -650,37 +668,56 @@ get_r_paren(char **s)
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
* this function strips all white space inside parens * this function strips all white space inside parens
* is needed in gettoks (dotcards.c) for right processing of expressions * is needed in gettoks (dotcards.c) for correct processing of expressions
* like ".plot v( 5,4) v(6)" * like " .plot v( 5 , 4 ) v( 6 )" -> .plot v(5,4) v(6)"
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/
char * char *
stripWhiteSpacesInsideParens(char *str) stripWhiteSpacesInsideParens(const char *str)
{ {
char *token; /* return token */ str = skip_ws(str); /* Skip leading whitespace */
SPICE_DSTRING buf; /* allow any length string */ const size_t n_char_str = strlen(str);
int i = 0; /* index into string */
while ((str[i] == ' ') || (str[i] == '\t')) /* Allocate buffer for string being built */
i++; char * const str_out = TMALLOC(char, n_char_str + 1);
char *p_dst = str_out; /* location in str_out */
char ch; /* current char */
spice_dstring_init(&buf); /* Process input string until its end */
for (; str[i]; i++) for ( ; ; ) {
if (str[i] != '(') { /* Add char. If at end of input string, return the string
spice_dstring_append_char(&buf, str[i]); * that was built */
} else { if ((*p_dst++ = (ch = *str++)) == '\0') {
spice_dstring_append_char(&buf, str[i]); return str_out;
while (str[i++] != ')')
if (str[i] != ' ')
spice_dstring_append_char(&buf, str[i]);
i--;
} }
token = copy(spice_dstring_value(&buf)); /* If the char is a ')' add all non-whitespace until ')' or,
spice_dstring_free(&buf); * if the string is malformed, until '\0' */
return token; if (ch == '(') {
for ( ; ; ) {
/* If at end of input string, the closing ') was missing.
* The caller will need to resolve this issue. */
if ((ch = *str++) == '\0') {
*p_dst = '\0';
return str_out;
} }
if (isspace((int) ch)) { /* skip whitespace */
continue;
}
/* Not whitespace, so add next character */
*p_dst++ = ch;
/* If the char that was added was ')', done */
if (ch == ')') {
break;
}
} /* end of loop processing () */
} /* end of case of '(' found */
} /* end of loop over chars in input string */
} /* end of function stripWhiteSpacesInsideParens */
bool bool
isquote(char ch) isquote(char ch)
@ -761,3 +798,6 @@ model_name_match(const char *token, const char *model_name)
return 2; return 2;
} }