Browse Source

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

efficient parsing.
pre-master-46
Jim Monte 7 years ago
committed by Holger Vogt
parent
commit
e92e2c7362
  1. 2
      src/include/ngspice/stringutil.h
  2. 150
      src/misc/string.c

2
src/include/ngspice/stringutil.h

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

150
src/misc/string.c

@ -275,7 +275,6 @@ cimatch(char *p, char *s)
* since I didn't want to break any fcns which called it from elsewhere than
* subckt.c. -- SDB 12.3.2003.
*-------------------------------------------------------------------------*/
char *
gettok(char **s)
{
@ -350,44 +349,63 @@ nexttok(const char *s)
char *
gettok_iv(char **s)
{
char c;
int paren;
char *token; /* return token */
SPICE_DSTRING buf; /* allow any length string */
char *p_src = *s; /* location in source string */
char c; /* current char */
paren = 0;
while (isspace_c(**s) || (**s == '='))
(*s)++;
/* Step past whitespace and '=' */
while (isspace_c(c = *p_src) || (c == '=')) {
p_src++;
}
if ((!**s) || ((**s != 'v') && (**s != 'i') && (**s != 'V') && (**s != 'I')))
return NULL;
/* Test for valid leading character */
if (((c =*p_src) == '\0') ||
((c != 'v') && (c != 'i') && (c != 'V') && (c != 'I'))) {
*s = p_src; /* update position in string */
return (char *) NULL;
}
// initialize string
spice_dstring_init(&buf);
// add v or i to buf
spice_dstring_append_char(&buf, *(*s)++);
/* Allocate buffer for token being returned */
char * const token = TMALLOC(char, strlen(p_src) + 1);
char *p_dst = token; /* location in token */
while ((c = **s) != '\0') {
if (c == '(')
paren += 1;
else if (c == ')')
paren -= 1;
if (isspace_c(c))
(*s)++;
else {
spice_dstring_append_char(&buf, *(*s)++);
if (paren == 0)
break;
// add v or i to buf
*p_dst++ = *p_src++;
{
int n_paren = 0;
/* Skip any space between v/V/i/I and '(' */
p_src = skip_ws(p_src);
while ((c = *p_src) != '\0') {
/* 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 {
*p_dst++ = *p_src++;
if (n_paren == 0) {
break;
}
}
}
}
while (isspace_c(**s) || **s == ',')
(*s)++;
/* Step past whitespace and ',' */
while (isspace_c(c = *p_src) || (c == ',')) {
p_src++;
}
token = copy(spice_dstring_value(&buf));
spice_dstring_free(&buf);
*s = p_src; /* update position in string */
return token;
}
} /* end of function gettok_iv */
/*-------------------------------------------------------------------------*
@ -650,36 +668,55 @@ get_r_paren(char **s)
/*-------------------------------------------------------------------------*
* this function strips all white space inside parens
* is needed in gettoks (dotcards.c) for right processing of expressions
* like ".plot v( 5,4) v(6)"
* is needed in gettoks (dotcards.c) for correct processing of expressions
* like " .plot v( 5 , 4 ) v( 6 )" -> .plot v(5,4) v(6)"
*-------------------------------------------------------------------------*/
char *
stripWhiteSpacesInsideParens(char *str)
stripWhiteSpacesInsideParens(const char *str)
{
char *token; /* return token */
SPICE_DSTRING buf; /* allow any length string */
int i = 0; /* index into string */
while ((str[i] == ' ') || (str[i] == '\t'))
i++;
spice_dstring_init(&buf);
for (; str[i]; i++)
if (str[i] != '(') {
spice_dstring_append_char(&buf, str[i]);
} else {
spice_dstring_append_char(&buf, str[i]);
while (str[i++] != ')')
if (str[i] != ' ')
spice_dstring_append_char(&buf, str[i]);
i--;
str = skip_ws(str); /* Skip leading whitespace */
const size_t n_char_str = strlen(str);
/* Allocate buffer for string being built */
char * const str_out = TMALLOC(char, n_char_str + 1);
char *p_dst = str_out; /* location in str_out */
char ch; /* current char */
/* Process input string until its end */
for ( ; ; ) {
/* Add char. If at end of input string, return the string
* that was built */
if ((*p_dst++ = (ch = *str++)) == '\0') {
return str_out;
}
token = copy(spice_dstring_value(&buf));
spice_dstring_free(&buf);
return token;
}
/* If the char is a ')' add all non-whitespace until ')' or,
* if the string is malformed, until '\0' */
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
@ -761,3 +798,6 @@ model_name_match(const char *token, const char *model_name)
return 2;
}
Loading…
Cancel
Save