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
diff --git a/src/compiler/preprocessor/scanner.c b/src/compiler/preprocessor/scanner.c
index 6dc1797..b6b9820 100644
--- a/src/compiler/preprocessor/scanner.c
+++ b/src/compiler/preprocessor/scanner.c
@@ -191,119 +191,63 @@
///////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// 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)
-{
- double val, expval, ten;
- int ii, llen, absexp;
- float rv;
-
- 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
-
+#define APPEND_CHAR_S(ch, str, len, max_len) \
+ if (len < max_len) { \
+ str[len++] = ch; \
+ } else if (!alreadyComplained) { \
+ CPPErrorToInfoLog("BUFFER OVERFLOW"); \
+ alreadyComplained = 1; \
+ }
/*
* lFloatConst() - Scan a floating point constant. Assumes that the scanner
* has seen at least one digit, followed by either a decimal '.' or the
* 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 str_len;
- float lval;
-
- HasDecimal = 0;
- declen = 0;
- exp = 0;
-
- str_len=len;
+ int alreadyComplained = 0;
+ assert((ch == '.') || (ch == 'e') || (ch == 'E'));
+
if (ch == '.') {
- str[len++]=ch;
- HasDecimal = 1;
- 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);
- } else {
- CPPErrorToInfoLog("ERROR___FP_CONST_TOO_LONG");
- len = 1,str_len=1;
- }
- }
+ do {
+ APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
+ } while (ch >= '0' && ch <= '9');
}
// Exponent:
-
if (ch == 'e' || ch == 'E') {
- ExpSign = 1;
- str[len++]=ch;
+ APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if (ch == '+') {
- str[len++]=ch;
+ APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} else if (ch == '-') {
- ExpSign = -1;
- str[len++]=ch;
+ APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
}
if (ch >= '0' && ch <= '9') {
while (ch >= '0' && ch <= '9') {
- exp = exp*10 + ch - '0';
- str[len++]=ch;
+ APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
}
} else {
- CPPErrorToInfoLog("ERROR___ERROR_IN_EXPONENT");
+ CPPErrorToInfoLog("EXPONENT INVALID");
}
- exp *= ExpSign;
}
-
- if (len == 0) {
- lval = 0.0f;
- strcpy(str,"0.0");
- } else {
- str[len]='\0';
- lval = lBuildFloatValue(str, str_len, exp - declen);
+ cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
+
+ assert(len <= MAX_SYMBOL_NAME_LEN);
+ yylvalpp->symbol_name[len] = '\0';
+ yylvalpp->sc_fval = (float) atof(yylvalpp->symbol_name);
+ if (isinff(yylvalpp->sc_fval)) {
+ CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW");
}
- // Suffix:
-
- yylvalpp->sc_fval = lval;
- strcpy(yylvalpp->symbol_name,str);
- cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
return CPP_FLOATCONSTANT;
} // lFloatConst
@@ -313,15 +257,14 @@
static int byte_scan(InputSrc *in, yystypepp * yylvalpp)
{
- char symbol_name[MAX_SYMBOL_NAME_LEN + 1];
char string_val[MAX_STRING_LEN + 1];
- int AlreadyComplained;
+ int alreadyComplained = 0;
int len, ch, ii, ival = 0;
for (;;) {
yylvalpp->sc_int = 0;
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
-
+
while (ch == ' ' || ch == '\t' || ch == '\r') {
yylvalpp->sc_int = 1;
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
@@ -329,6 +272,7 @@
cpp->ltokenLoc.file = cpp->currentInput->name;
cpp->ltokenLoc.line = cpp->currentInput->line;
+ alreadyComplained = 0;
len = 0;
switch (ch) {
default:
@@ -348,35 +292,32 @@
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z':
do {
- if (len < MAX_SYMBOL_NAME_LEN) {
- symbol_name[len++] = ch;
- }
+ APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} while ((ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') ||
ch == '_');
assert(len <= MAX_SYMBOL_NAME_LEN);
- symbol_name[len] = '\0';
+ yylvalpp->symbol_name[len] = '\0';
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;
break;
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);
- if (ch == 'x' || ch == 'X') {
- yylvalpp->symbol_name[len++] = ch;
+ if (ch == 'x' || ch == 'X') { // hexadecimal integer constants
+ APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN);
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if ((ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f'))
{
- AlreadyComplained = 0;
ival = 0;
do {
- yylvalpp->symbol_name[len++] = ch;
- if (ival <= 0x0fffffff) {
+ if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
+ yylvalpp->symbol_name[len++] = ch;
if (ch >= '0' && ch <= '9') {
ii = ch - '0';
} else if (ch >= 'A' && ch <= 'F') {
@@ -385,39 +326,38 @@
ii = ch - 'a' + 10;
}
ival = (ival << 4) | ii;
- } else {
- if (!AlreadyComplained)
- CPPErrorToInfoLog("ERROR___HEX_CONST_OVERFLOW");
- AlreadyComplained = 1;
+ } else if (!alreadyComplained) {
+ CPPErrorToInfoLog("HEX CONSTANT OVERFLOW");
+ alreadyComplained = 1;
}
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} while ((ch >= '0' && ch <= '9') ||
(ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f'));
} else {
- CPPErrorToInfoLog("ERROR___ERROR_IN_HEX_CONSTANT");
+ CPPErrorToInfoLog("HEX CONSTANT INVALID");
}
+ assert(len <= MAX_SYMBOL_NAME_LEN);
yylvalpp->symbol_name[len] = '\0';
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
yylvalpp->sc_int = ival;
return CPP_INTCONSTANT;
} else if (ch >= '0' && ch <= '7') { // octal integer constants
- AlreadyComplained = 0;
ival = 0;
do {
- yylvalpp->symbol_name[len++] = ch;
- if (ival <= 0x1fffffff) {
+ if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) {
+ yylvalpp->symbol_name[len++] = ch;
ii = ch - '0';
ival = (ival << 3) | ii;
- } else {
- if (!AlreadyComplained)
- CPPErrorToInfoLog("ERROR___OCT_CONST_OVERFLOW");
- AlreadyComplained = 1;
+ } else if (!alreadyComplained) {
+ CPPErrorToInfoLog("OCT CONSTANT OVERFLOW");
+ alreadyComplained = 1;
}
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
} while (ch >= '0' && ch <= '7');
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';
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
yylvalpp->sc_int = ival;
@@ -430,28 +370,23 @@
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
do {
- if (len < MAX_SYMBOL_NAME_LEN) {
- if (len > 0 || ch != '0') {
- yylvalpp->symbol_name[len++] = ch;
- }
- ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
- }
+ 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 (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 {
+ assert(len <= MAX_SYMBOL_NAME_LEN);
yylvalpp->symbol_name[len] = '\0';
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
ival = 0;
- AlreadyComplained = 0;
for (ii = 0; ii < len; ii++) {
ch = yylvalpp->symbol_name[ii] - '0';
- if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
- if (!AlreadyComplained)
- CPPErrorToInfoLog("ERROR___INTEGER_CONST_OVERFLOW");
- AlreadyComplained = 1;
- }
ival = ival*10 + ch;
+ if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) {
+ CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW");
+ break;
+ }
}
yylvalpp->sc_int = ival;
if(ival==0)
@@ -604,7 +539,7 @@
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if (ch >= '0' && ch <= '9') {
cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp);
- return lFloatConst(yylvalpp->symbol_name, 0, '.', yylvalpp);
+ return lFloatConst('.', 0, yylvalpp);
} else {
if (ch == '.') {
return -1; // Special EOF hack
@@ -629,14 +564,14 @@
while (ch != '*') {
if (ch == '\n') nlcount++;
if (ch == EOF) {
- CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+ CPPErrorToInfoLog("EOF IN COMMENT");
return -1;
}
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
}
ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
if (ch == EOF) {
- CPPErrorToInfoLog("ERROR___EOF_IN_COMMENT");
+ CPPErrorToInfoLog("EOF IN COMMENT");
return -1;
}
} while (ch != '/');
@@ -658,19 +593,19 @@
CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language");
return -1;
}
- if (len < MAX_STRING_LEN) {
- string_val[len++] = ch;
- ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
- }
+ APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN);
+ ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp);
};
+ assert(len <= MAX_STRING_LEN);
string_val[len] = '\0';
if (ch == '"') {
yylvalpp->sc_ident = LookUpAddString(atable, string_val);
return CPP_STRCONSTANT;
} else {
- CPPErrorToInfoLog("ERROR___CPP_EOL_IN_STRING");
+ CPPErrorToInfoLog("EOL IN STRING");
return ERROR_SY;
}
+ break;
}
}
} // byte_scan
@@ -703,30 +638,28 @@
cpp->pastFirstStatement = 1;
continue;
}
-
+
if (token == '\n')
continue;
-
- if (token == CPP_IDENTIFIER) {
- cpp->pastFirstStatement = 1;
+ cpp->pastFirstStatement = 1;
+
+ if (token == CPP_IDENTIFIER) {
tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident);
- } else if (token == CPP_FLOATCONSTANT||token == CPP_INTCONSTANT){
- cpp->pastFirstStatement = 1;
+ } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){
tokenString = yylvalpp.symbol_name;
- } else {
- cpp->pastFirstStatement = 1;
+ } else {
tokenString = GetStringOfAtom(atable,token);
}
if (tokenString) {
- if ((signed)strlen(tokenString) >= maxSize) {
- cpp->tokensBeforeEOF = 1;
- return maxSize;
- } else if (strlen(tokenString) > 0) {
+ int len = strlen(tokenString);
+ cpp->tokensBeforeEOF = 1;
+ if (len >= maxSize) {
+ return maxSize;
+ } else if (len > 0) {
strcpy(buf, tokenString);
- cpp->tokensBeforeEOF = 1;
- return (int)strlen(tokenString);
- }
+ return len;
+ }
return 0;
}