Commit 521c8364 by Zhenyao Mo

Clamp numeric overflow rather than failing with an error

BUG=249086 ANGLEBUG=468 TEST= R=alokp@chromium.org, kbr@chromium.org Review URL: https://codereview.appspot.com/13195043
parent 6440d14b
#define MAJOR_VERSION 1 #define MAJOR_VERSION 1
#define MINOR_VERSION 2 #define MINOR_VERSION 2
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 2441 #define BUILD_REVISION 2442
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -57,6 +57,8 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). ...@@ -57,6 +57,8 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
static int check_type(yyscan_t yyscanner); static int check_type(yyscan_t yyscanner);
static int reserved_word(yyscan_t yyscanner); static int reserved_word(yyscan_t yyscanner);
static int int_constant(yyscan_t yyscanner);
static int float_constant(yyscan_t yyscanner);
%} %}
%option noyywrap nounput never-interactive %option noyywrap nounput never-interactive
...@@ -189,13 +191,13 @@ O [0-7] ...@@ -189,13 +191,13 @@ O [0-7]
return check_type(yyscanner); return check_type(yyscanner);
} }
0[xX]{H}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } 0[xX]{H}+ { return int_constant(yyscanner); }
0{O}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } 0{O}+ { return int_constant(yyscanner); }
{D}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } {D}+ { return int_constant(yyscanner); }
{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } {D}+{E} { return float_constant(yyscanner); }
{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } {D}+"."{D}*({E})? { return float_constant(yyscanner); }
"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } "."{D}+({E})? { return float_constant(yyscanner); }
"+=" { return ADD_ASSIGN; } "+=" { return ADD_ASSIGN; }
"-=" { return SUB_ASSIGN; } "-=" { return SUB_ASSIGN; }
...@@ -293,6 +295,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { ...@@ -293,6 +295,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
context->recover(); context->recover();
} }
int int_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return INTCONSTANT;
}
int float_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(*yylloc, "Float overflow", yytext, "");
return FLOATCONSTANT;
}
int glslang_initialize(TParseContext* context) { int glslang_initialize(TParseContext* context) {
yyscan_t scanner = NULL; yyscan_t scanner = NULL;
if (yylex_init_extra(context, &scanner)) if (yylex_init_extra(context, &scanner))
......
...@@ -802,6 +802,8 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). ...@@ -802,6 +802,8 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
static int check_type(yyscan_t yyscanner); static int check_type(yyscan_t yyscanner);
static int reserved_word(yyscan_t yyscanner); static int reserved_word(yyscan_t yyscanner);
static int int_constant(yyscan_t yyscanner);
static int float_constant(yyscan_t yyscanner);
#define INITIAL 0 #define INITIAL 0
...@@ -1500,27 +1502,27 @@ YY_RULE_SETUP ...@@ -1500,27 +1502,27 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 94: case 94:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } { return int_constant(yyscanner); }
YY_BREAK YY_BREAK
case 95: case 95:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } { return int_constant(yyscanner); }
YY_BREAK YY_BREAK
case 96: case 96:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; } { return int_constant(yyscanner); }
YY_BREAK YY_BREAK
case 97: case 97:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } { return float_constant(yyscanner); }
YY_BREAK YY_BREAK
case 98: case 98:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } { return float_constant(yyscanner); }
YY_BREAK YY_BREAK
case 99: case 99:
YY_RULE_SETUP YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; } { return float_constant(yyscanner); }
YY_BREAK YY_BREAK
case 100: case 100:
YY_RULE_SETUP YY_RULE_SETUP
...@@ -2902,6 +2904,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { ...@@ -2902,6 +2904,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
context->recover(); context->recover();
} }
int int_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atoi_clamp(yytext, &(yylval->lex.i)))
yyextra->warning(*yylloc, "Integer overflow", yytext, "");
return INTCONSTANT;
}
int float_constant(yyscan_t yyscanner) {
struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
if (!atof_clamp(yytext, &(yylval->lex.f)))
yyextra->warning(*yylloc, "Float overflow", yytext, "");
return FLOATCONSTANT;
}
int glslang_initialize(TParseContext* context) { int glslang_initialize(TParseContext* context) {
yyscan_t scanner = NULL; yyscan_t scanner = NULL;
if (yylex_init_extra(context,&scanner)) if (yylex_init_extra(context,&scanner))
......
...@@ -100,34 +100,6 @@ void Preprocessor::lex(Token* token) ...@@ -100,34 +100,6 @@ void Preprocessor::lex(Token* token)
case Token::PP_HASH: case Token::PP_HASH:
assert(false); assert(false);
break; break;
case Token::CONST_INT:
{
int val = 0;
if (!token->iValue(&val))
{
// Do not mark the token as invalid.
// Just emit the diagnostic and reset value to 0.
mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW,
token->location, token->text);
token->text.assign("0");
}
validToken = true;
break;
}
case Token::CONST_FLOAT:
{
float val = 0;
if (!token->fValue(&val))
{
// Do not mark the token as invalid.
// Just emit the diagnostic and reset value to 0.0.
mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW,
token->location, token->text);
token->text.assign("0.0");
}
validToken = true;
break;
}
case Token::PP_NUMBER: case Token::PP_NUMBER:
mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
token->location, token->text); token->location, token->text);
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <cerrno>
#include <limits>
#include "util.h" #include "util.h"
#ifdef _MSC_VER #ifdef _MSC_VER
...@@ -15,19 +18,39 @@ ...@@ -15,19 +18,39 @@
#include <sstream> #include <sstream>
#endif #endif
double atof_dot(const char *str) bool atof_clamp(const char *str, float *value)
{ {
bool success = true;
#ifdef _MSC_VER #ifdef _MSC_VER
_locale_t l = _create_locale(LC_NUMERIC, "C"); _locale_t l = _create_locale(LC_NUMERIC, "C");
double result = _atof_l(str, l); double dvalue = _atof_l(str, l);
_free_locale(l); _free_locale(l);
return result; if (errno == ERANGE || dvalue > std::numeric_limits<float>::max())
success = false;
else
*value = static_cast<float>(dvalue);
#else #else
double result;
std::istringstream s(str); std::istringstream s(str);
std::locale l("C"); std::locale l("C");
s.imbue(l); s.imbue(l);
s >> result; s >> *value;
return result; if (s.fail())
success = false;
#endif #endif
if (!success)
*value = std::numeric_limits<float>::max();
return success;
} }
bool atoi_clamp(const char *str, int *value)
{
long int lvalue = strtol(str, 0, 0);
if (errno == ERANGE || lvalue > std::numeric_limits<int>::max())
{
*value = std::numeric_limits<int>::max();
return false;
}
*value = static_cast<int>(lvalue);
return true;
}
...@@ -7,15 +7,14 @@ ...@@ -7,15 +7,14 @@
#ifndef COMPILER_UTIL_H #ifndef COMPILER_UTIL_H
#define COMPILER_UTIL_H #define COMPILER_UTIL_H
#ifdef __cplusplus // atof_clamp is like atof but
extern "C" { // 1. it forces C locale, i.e. forcing '.' as decimal point.
#endif // 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
// Return false if overflow happens.
extern bool atof_clamp(const char *str, float *value);
// atof_dot is like atof but forcing C locale, i.e. forcing '.' as decimal point. // If overflow happens, clamp the value to INT_MIN or INT_MAX.
double atof_dot(const char *str); // Return false if overflow happens.
extern bool atoi_clamp(const char *str, int *value);
#ifdef __cplusplus
} // end extern "C"
#endif
#endif // COMPILER_UTIL_H #endif // COMPILER_UTIL_H
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