Commit 8860909e by alokp@chromium.org

Fixed infinite loops and buffer overflow in byte_scan when scanning for integers…

Fixed infinite loops and buffer overflow in byte_scan when scanning for integers and floating-point numbers. - The byte_scan and associated functions are not very well written. I tried to clean them as much as possible without re-writing the whole thing. - Replaced lBuildFloatValue function with atof. lBuildFloatValue was returning incorrect value anyway. The only reason it was working so far because we never used that value. BUG=59623(crbug.com), 603333(bugzilla.mozilla.org) Review URL: http://codereview.appspot.com/2655042 git-svn-id: https://angleproject.googlecode.com/svn/trunk@469 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 78477fc0
...@@ -191,119 +191,63 @@ int ScanFromString(const char *s) ...@@ -191,119 +191,63 @@ int ScanFromString(const char *s)
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// Floating point constants: ///////////////////////////////// /////////////////////////////////// Floating point constants: /////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/*
* lBuildFloatValue() - Quick and dirty conversion to floating point. Since all
* we need is single precision this should be quite precise.
*/
static float lBuildFloatValue(const char *str, int len, int exp) #define APPEND_CHAR_S(ch, str, len, max_len) \
{ if (len < max_len) { \
double val, expval, ten; str[len++] = ch; \
int ii, llen, absexp; } else if (!alreadyComplained) { \
float rv; CPPErrorToInfoLog("BUFFER OVERFLOW"); \
alreadyComplained = 1; \
val = 0.0;
llen = len;
for (ii = 0; ii < len; ii++)
val = val*10.0 + (str[ii] - '0');
if (exp != 0) {
absexp = exp > 0 ? exp : -exp;
expval = 1.0f;
ten = 10.0;
while (absexp) {
if (absexp & 1)
expval *= ten;
ten *= ten;
absexp >>= 1;
}
if (exp >= 0) {
val *= expval;
} else {
val /= expval;
}
}
rv = (float)val;
if (isinff(rv)) {
CPPErrorToInfoLog(" ERROR___FP_CONST_OVERFLOW");
} }
return rv;
} // lBuildFloatValue
/* /*
* lFloatConst() - Scan a floating point constant. Assumes that the scanner * lFloatConst() - Scan a floating point constant. Assumes that the scanner
* has seen at least one digit, followed by either a decimal '.' or the * has seen at least one digit, followed by either a decimal '.' or the
* letter 'e'. * letter 'e'.
* ch - '.' or 'e'
* len - length of string already copied into yylvalpp->symbol_name.
*/ */
static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp) static int lFloatConst(int ch, int len, yystypepp * yylvalpp)
{ {
int HasDecimal, declen, exp, ExpSign; int alreadyComplained = 0;
int str_len; assert((ch == '.') || (ch == 'e') || (ch == 'E'));
float lval;
HasDecimal = 0;
declen = 0;
exp = 0;
str_len=len;
if (ch == '.') { if (ch == '.') {
str[len++]=ch; do {
HasDecimal = 1; APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
while (ch >= '0' && ch <= '9') {
if (len < MAX_SYMBOL_NAME_LEN) {
declen++;
if (len > 0 || ch != '0') {
str[len] = ch;
len++;str_len++;
}
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} else { } while (ch >= '0' && ch <= '9');
CPPErrorToInfoLog("ERROR___FP_CONST_TOO_LONG");
len = 1,str_len=1;
}
}
} }
// Exponent: // Exponent:
if (ch == 'e' || ch == 'E') { if (ch == 'e' || ch == 'E') {
ExpSign = 1; APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
str[len++]=ch;
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if (ch == '+') { if (ch == '+') {
str[len++]=ch; APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} else if (ch == '-') { } else if (ch == '-') {
ExpSign = -1; APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
str[len++]=ch;
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} }
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
while (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9') {
exp = exp*10 + ch - '0'; APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
str[len++]=ch;
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} }
} else { } else {
CPPErrorToInfoLog("ERROR___ERROR_IN_EXPONENT"); CPPErrorToInfoLog("EXPONENT INVALID");
} }
exp *= ExpSign;
} }
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
if (len == 0) { assert(len <= MAX_SYMBOL_NAME_LEN);
lval = 0.0f; yylvalpp->symbol_name[len] = '\0';
strcpy(str,"0.0"); yylvalpp->sc_fval = (float) atof(yylvalpp->symbol_name);
} else { if (isinff(yylvalpp->sc_fval)) {
str[len]='\0'; CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW");
lval = lBuildFloatValue(str, str_len, exp - declen);
} }
// Suffix:
yylvalpp->sc_fval = lval;
strcpy(yylvalpp->symbol_name,str);
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
return CPP_FLOATCONSTANT; return CPP_FLOATCONSTANT;
} // lFloatConst } // lFloatConst
...@@ -313,9 +257,8 @@ static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp) ...@@ -313,9 +257,8 @@ static int lFloatConst(char *str, int len, int ch, yystypepp * yylvalpp)
static int byte_scan(InputSrc *in, yystypepp * yylvalpp) static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
{ {
char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
char string_val[MAX_STRING_LEN + 1]; char string_val[MAX_STRING_LEN + 1];
int AlreadyComplained; int alreadyComplained = 0;
int len, ch, ii, ival = 0; int len, ch, ii, ival = 0;
for (;;) { for (;;) {
...@@ -329,6 +272,7 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ...@@ -329,6 +272,7 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
cpp->ltokenLoc.file = cpp->currentInput->name; cpp->ltokenLoc.file = cpp->currentInput->name;
cpp->ltokenLoc.line = cpp->currentInput->line; cpp->ltokenLoc.line = cpp->currentInput->line;
alreadyComplained = 0;
len = 0; len = 0;
switch (ch) { switch (ch) {
default: default:
...@@ -348,35 +292,32 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ...@@ -348,35 +292,32 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
case 'u': case 'v': case 'w': case 'x': case 'y': case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z': case 'z':
do { do {
if (len < MAX_SYMBOL_NAME_LEN) { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
symbol_name[len++] = ch;
}
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} while ((ch >= 'a' && ch <= 'z') || } while ((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') || (ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') || (ch >= '0' && ch <= '9') ||
ch == '_'); ch == '_');
assert(len <= MAX_SYMBOL_NAME_LEN); assert(len <= MAX_SYMBOL_NAME_LEN);
symbol_name[len] = '\0'; yylvalpp->symbol_name[len] = '\0';
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
yylvalpp->sc_ident = LookUpAddString(atable, symbol_name); yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name);
return CPP_IDENTIFIER; return CPP_IDENTIFIER;
break; break;
case '0': case '0':
yylvalpp->symbol_name[len++] = ch; APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if (ch == 'x' || ch == 'X') { if (ch == 'x' || ch == 'X') { // hexadecimal integer constants
yylvalpp->symbol_name[len++] = ch; APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if ((ch >= '0' && ch <= '9') || if ((ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'F') || (ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f')) (ch >= 'a' && ch <= 'f'))
{ {
AlreadyComplained = 0;
ival = 0; ival = 0;
do { do {
if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
yylvalpp->symbol_name[len++] = ch; yylvalpp->symbol_name[len++] = ch;
if (ival <= 0x0fffffff) {
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
ii = ch - '0'; ii = ch - '0';
} else if (ch >= 'A' && ch <= 'F') { } else if (ch >= 'A' && ch <= 'F') {
...@@ -385,39 +326,38 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ...@@ -385,39 +326,38 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
ii = ch - 'a' + 10; ii = ch - 'a' + 10;
} }
ival = (ival << 4) | ii; ival = (ival << 4) | ii;
} else { } else if (!alreadyComplained) {
if (!AlreadyComplained) CPPErrorToInfoLog("HEX CONSTANT OVERFLOW");
CPPErrorToInfoLog("ERROR___HEX_CONST_OVERFLOW"); alreadyComplained = 1;
AlreadyComplained = 1;
} }
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} while ((ch >= '0' && ch <= '9') || } while ((ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'F') || (ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f')); (ch >= 'a' && ch <= 'f'));
} else { } else {
CPPErrorToInfoLog("ERROR___ERROR_IN_HEX_CONSTANT"); CPPErrorToInfoLog("HEX CONSTANT INVALID");
} }
assert(len <= MAX_SYMBOL_NAME_LEN);
yylvalpp->symbol_name[len] = '\0'; yylvalpp->symbol_name[len] = '\0';
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
yylvalpp->sc_int = ival; yylvalpp->sc_int = ival;
return CPP_INTCONSTANT; return CPP_INTCONSTANT;
} else if (ch >= '0' && ch <= '7') { // octal integer constants } else if (ch >= '0' && ch <= '7') { // octal integer constants
AlreadyComplained = 0;
ival = 0; ival = 0;
do { do {
if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
yylvalpp->symbol_name[len++] = ch; yylvalpp->symbol_name[len++] = ch;
if (ival <= 0x1fffffff) {
ii = ch - '0'; ii = ch - '0';
ival = (ival << 3) | ii; ival = (ival << 3) | ii;
} else { } else if (!alreadyComplained) {
if (!AlreadyComplained) CPPErrorToInfoLog("OCT CONSTANT OVERFLOW");
CPPErrorToInfoLog("ERROR___OCT_CONST_OVERFLOW"); alreadyComplained = 1;
AlreadyComplained = 1;
} }
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} while (ch >= '0' && ch <= '7'); } while (ch >= '0' && ch <= '7');
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E')
return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp); return lFloatConst(ch, len, yylvalpp);
assert(len <= MAX_SYMBOL_NAME_LEN);
yylvalpp->symbol_name[len] = '\0'; yylvalpp->symbol_name[len] = '\0';
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
yylvalpp->sc_int = ival; yylvalpp->sc_int = ival;
...@@ -430,28 +370,23 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ...@@ -430,28 +370,23 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
case '1': case '2': case '3': case '4': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
do { do {
if (len < MAX_SYMBOL_NAME_LEN) { APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
if (len > 0 || ch != '0') {
yylvalpp->symbol_name[len++] = ch;
}
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
}
} while (ch >= '0' && ch <= '9'); } while (ch >= '0' && ch <= '9');
if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') { if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') {
return lFloatConst(yylvalpp->symbol_name, len, ch, yylvalpp); return lFloatConst(ch, len, yylvalpp);
} else { } else {
assert(len <= MAX_SYMBOL_NAME_LEN);
yylvalpp->symbol_name[len] = '\0'; yylvalpp->symbol_name[len] = '\0';
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
ival = 0; ival = 0;
AlreadyComplained = 0;
for (ii = 0; ii < len; ii++) { for (ii = 0; ii < len; ii++) {
ch = yylvalpp->symbol_name[ii] - '0'; ch = yylvalpp->symbol_name[ii] - '0';
ival = ival*10 + ch;
if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) { if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
if (!AlreadyComplained) CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW");
CPPErrorToInfoLog("ERROR___INTEGER_CONST_OVERFLOW"); break;
AlreadyComplained = 1;
} }
ival = ival*10 + ch;
} }
yylvalpp->sc_int = ival; yylvalpp->sc_int = ival;
if(ival==0) if(ival==0)
...@@ -604,7 +539,7 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ...@@ -604,7 +539,7 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
return lFloatConst(yylvalpp->symbol_name, 0, '.', yylvalpp); return lFloatConst('.', 0, yylvalpp);
} else { } else {
if (ch == '.') { if (ch == '.') {
return -1; // Special EOF hack return -1; // Special EOF hack
...@@ -629,14 +564,14 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ...@@ -629,14 +564,14 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
while (ch != '*') { while (ch != '*') {
if (ch == '\n') nlcount++; if (ch == '\n') nlcount++;
if (ch == EOF) { if (ch == EOF) {
CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT"); CPPErrorToInfoLog("EOF IN COMMENT");
return -1; return -1;
} }
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} }
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if (ch == EOF) { if (ch == EOF) {
CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT"); CPPErrorToInfoLog("EOF IN COMMENT");
return -1; return -1;
} }
} while (ch != '/'); } while (ch != '/');
...@@ -658,19 +593,19 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp) ...@@ -658,19 +593,19 @@ static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
return -1; return -1;
} }
if (len < MAX_STRING_LEN) { APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN);
string_val[len++] = ch;
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
}
}; };
assert(len <= MAX_STRING_LEN);
string_val[len] = '\0'; string_val[len] = '\0';
if (ch == '"') { if (ch == '"') {
yylvalpp->sc_ident = LookUpAddString(atable, string_val); yylvalpp->sc_ident = LookUpAddString(atable, string_val);
return CPP_STRCONSTANT; return CPP_STRCONSTANT;
} else { } else {
CPPErrorToInfoLog("ERROR___CPP_EOL_IN_STRING"); CPPErrorToInfoLog("EOL IN STRING");
return ERROR_SY; return ERROR_SY;
} }
break;
} }
} }
} // byte_scan } // byte_scan
...@@ -706,26 +641,24 @@ int yylex_CPP(char* buf, int maxSize) ...@@ -706,26 +641,24 @@ int yylex_CPP(char* buf, int maxSize)
if (token == '\n') if (token == '\n')
continue; continue;
cpp->pastFirstStatement = 1;
if (token == CPP_IDENTIFIER) { if (token == CPP_IDENTIFIER) {
cpp->pastFirstStatement = 1;
tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident); tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
} else if (token == CPP_FLOATCONSTANT||token == CPP_INTCONSTANT){ } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
cpp->pastFirstStatement = 1;
tokenString = yylvalpp.symbol_name; tokenString = yylvalpp.symbol_name;
} else { } else {
cpp->pastFirstStatement = 1;
tokenString = GetStringOfAtom(atable,token); tokenString = GetStringOfAtom(atable,token);
} }
if (tokenString) { if (tokenString) {
if ((signed)strlen(tokenString) >= maxSize) { int len = strlen(tokenString);
cpp->tokensBeforeEOF = 1; cpp->tokensBeforeEOF = 1;
if (len >= maxSize) {
return maxSize; return maxSize;
} else if (strlen(tokenString) > 0) { } else if (len > 0) {
strcpy(buf, tokenString); strcpy(buf, tokenString);
cpp->tokensBeforeEOF = 1; return len;
return (int)strlen(tokenString);
} }
return 0; return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment