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 MINOR_VERSION 2
#define BUILD_VERSION 0
#define BUILD_REVISION 2441
#define BUILD_REVISION 2442
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
......
......@@ -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 int check_type(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
......@@ -189,13 +191,13 @@ O [0-7]
return check_type(yyscanner);
}
0[xX]{H}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
0{O}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
{D}+ { yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
0[xX]{H}+ { return int_constant(yyscanner); }
0{O}+ { return int_constant(yyscanner); }
{D}+ { return int_constant(yyscanner); }
{D}+{E} { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
{D}+"."{D}*({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
"."{D}+({E})? { yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
{D}+{E} { return float_constant(yyscanner); }
{D}+"."{D}*({E})? { return float_constant(yyscanner); }
"."{D}+({E})? { return float_constant(yyscanner); }
"+=" { return ADD_ASSIGN; }
"-=" { return SUB_ASSIGN; }
......@@ -293,6 +295,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
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) {
yyscan_t scanner = NULL;
if (yylex_init_extra(context, &scanner))
......
......@@ -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 int check_type(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
......@@ -1500,27 +1502,27 @@ YY_RULE_SETUP
YY_BREAK
case 94:
YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
{ return int_constant(yyscanner); }
YY_BREAK
case 95:
YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
{ return int_constant(yyscanner); }
YY_BREAK
case 96:
YY_RULE_SETUP
{ yylval->lex.i = static_cast<int>(strtol(yytext, 0, 0)); return INTCONSTANT; }
{ return int_constant(yyscanner); }
YY_BREAK
case 97:
YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
{ return float_constant(yyscanner); }
YY_BREAK
case 98:
YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
{ return float_constant(yyscanner); }
YY_BREAK
case 99:
YY_RULE_SETUP
{ yylval->lex.f = static_cast<float>(atof_dot(yytext)); return FLOATCONSTANT; }
{ return float_constant(yyscanner); }
YY_BREAK
case 100:
YY_RULE_SETUP
......@@ -2902,6 +2904,22 @@ void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
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) {
yyscan_t scanner = NULL;
if (yylex_init_extra(context,&scanner))
......
......@@ -100,34 +100,6 @@ void Preprocessor::lex(Token* token)
case Token::PP_HASH:
assert(false);
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:
mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER,
token->location, token->text);
......
......@@ -7,6 +7,9 @@
#include <math.h>
#include <stdlib.h>
#include <cerrno>
#include <limits>
#include "util.h"
#ifdef _MSC_VER
......@@ -15,19 +18,39 @@
#include <sstream>
#endif
double atof_dot(const char *str)
bool atof_clamp(const char *str, float *value)
{
bool success = true;
#ifdef _MSC_VER
_locale_t l = _create_locale(LC_NUMERIC, "C");
double result = _atof_l(str, l);
double dvalue = _atof_l(str, l);
_free_locale(l);
return result;
if (errno == ERANGE || dvalue > std::numeric_limits<float>::max())
success = false;
else
*value = static_cast<float>(dvalue);
#else
double result;
std::istringstream s(str);
std::locale l("C");
s.imbue(l);
s >> result;
return result;
s >> *value;
if (s.fail())
success = false;
#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 @@
#ifndef COMPILER_UTIL_H
#define COMPILER_UTIL_H
#ifdef __cplusplus
extern "C" {
#endif
// atof_clamp is like atof but
// 1. it forces C locale, i.e. forcing '.' as decimal point.
// 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.
double atof_dot(const char *str);
#ifdef __cplusplus
} // end extern "C"
#endif
// If overflow happens, clamp the value to INT_MIN or INT_MAX.
// Return false if overflow happens.
extern bool atoi_clamp(const char *str, int *value);
#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