diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y')
-rw-r--r-- | src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y | 85 |
1 files changed, 73 insertions, 12 deletions
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y index 7b5d9e9cee..68d7cc3958 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y @@ -41,17 +41,15 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser. #include <cassert> #include <sstream> +#include <stdint.h> #include "DiagnosticsBase.h" #include "Lexer.h" #include "Token.h" +#include "common/mathutil.h" -#if defined(_MSC_VER) -typedef __int64 YYSTYPE; -#else -#include <stdint.h> -typedef intmax_t YYSTYPE; -#endif // _MSC_VER +typedef int32_t YYSTYPE; +typedef uint32_t UNSIGNED_TYPE; #define YYENABLE_NLS 0 #define YYLTYPE_IS_TRIVIAL 1 @@ -196,16 +194,57 @@ expression $$ = $1 < $3; } | expression TOK_OP_RIGHT expression { - $$ = $1 >> $3; + if ($3 < 0 || $3 > 31) + { + if (!context->isIgnoringErrors()) + { + std::ostringstream stream; + stream << $1 << " >> " << $3; + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT, + context->token->location, + text.c_str()); + *(context->valid) = false; + } + $$ = static_cast<YYSTYPE>(0); + } + else if ($1 < 0) + { + // Logical shift right. + $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) >> $3); + } + else + { + $$ = $1 >> $3; + } } | expression TOK_OP_LEFT expression { - $$ = $1 << $3; + if ($3 < 0 || $3 > 31) + { + if (!context->isIgnoringErrors()) + { + std::ostringstream stream; + stream << $1 << " << " << $3; + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::PP_UNDEFINED_SHIFT, + context->token->location, + text.c_str()); + *(context->valid) = false; + } + $$ = static_cast<YYSTYPE>(0); + } + else + { + // Logical shift left. Casting to unsigned is needed to ensure there's no signed integer + // overflow, which some tools treat as an error. + $$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) << $3); + } } | expression '-' expression { - $$ = $1 - $3; + $$ = gl::WrappingDiff<YYSTYPE>($1, $3); } | expression '+' expression { - $$ = $1 + $3; + $$ = gl::WrappingSum<YYSTYPE>($1, $3); } | expression '%' expression { if ($3 == 0) @@ -222,6 +261,12 @@ expression } $$ = static_cast<YYSTYPE>(0); } + else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1)) + { + // Check for the special case where the minimum representable number is + // divided by -1. If left alone this has undefined results. + $$ = 0; + } else { $$ = $1 % $3; @@ -242,13 +287,20 @@ expression } $$ = static_cast<YYSTYPE>(0); } + else if (($1 == std::numeric_limits<YYSTYPE>::min()) && ($3 == -1)) + { + // Check for the special case where the minimum representable number is + // divided by -1. If left alone this leads to integer overflow in C++, which + // has undefined results. + $$ = std::numeric_limits<YYSTYPE>::max(); + } else { $$ = $1 / $3; } } | expression '*' expression { - $$ = $1 * $3; + $$ = gl::WrappingMul($1, $3); } | '!' expression %prec TOK_UNARY { $$ = ! $2; @@ -257,7 +309,16 @@ expression $$ = ~ $2; } | '-' expression %prec TOK_UNARY { - $$ = - $2; + // Check for negation of minimum representable integer to prevent undefined signed int + // overflow. + if ($2 == std::numeric_limits<YYSTYPE>::min()) + { + $$ = std::numeric_limits<YYSTYPE>::min(); + } + else + { + $$ = -$2; + } } | '+' expression %prec TOK_UNARY { $$ = + $2; |