Commit a3d384ad by Olli Etuaho Committed by Commit Bot

Fix signed integer overflow in GLSL preprocessor left shift

Signed integer overflow is undefined in C++, whereas unsigned integer overflow is not. Always cast left shift operand to unsigned to avoid UB. On common compilers, the behavior was already the same before this patch, so this patch is done mostly for the benefit of automated fuzz testing. BUG=chromium:743136 TEST=angle_unittests Change-Id: I7aab939036bb19a37f258cef4297b560da3cd9d5 Reviewed-on: https://chromium-review.googlesource.com/704659Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent b433e872
...@@ -496,12 +496,9 @@ static const yytype_uint8 yytranslate[] = ...@@ -496,12 +496,9 @@ static const yytype_uint8 yytranslate[] =
#if YYDEBUG #if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] = static const yytype_uint16 yyrline[] = {0, 108, 108, 115, 116, 127, 127, 148, 148, 169,
{
0, 108, 108, 115, 116, 127, 127, 148, 148, 169,
172, 175, 178, 181, 184, 187, 190, 193, 196, 221, 172, 175, 178, 181, 184, 187, 190, 193, 196, 221,
246, 249, 252, 278, 305, 308, 311, 314, 326, 329 243, 246, 249, 275, 302, 305, 308, 311, 323, 326};
};
#endif #endif
#if YYDEBUG || YYERROR_VERBOSE || 0 #if YYDEBUG || YYERROR_VERBOSE || 0
...@@ -1537,14 +1534,11 @@ yyreduce: ...@@ -1537,14 +1534,11 @@ yyreduce:
} }
(yyval) = static_cast<YYSTYPE>(0); (yyval) = static_cast<YYSTYPE>(0);
} }
else if ((yyvsp[-2]) < 0)
{
// Logical shift left.
(yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) << (yyvsp[0]));
}
else else
{ {
(yyval) = (yyvsp[-2]) << (yyvsp[0]); // Logical shift left. Casting to unsigned is needed to ensure there's no signed integer
// overflow, which some tools treat as an error.
(yyval) = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>((yyvsp[-2])) << (yyvsp[0]));
} }
} }
......
...@@ -233,14 +233,11 @@ expression ...@@ -233,14 +233,11 @@ expression
} }
$$ = static_cast<YYSTYPE>(0); $$ = static_cast<YYSTYPE>(0);
} }
else if ($1 < 0)
{
// Logical shift left.
$$ = static_cast<YYSTYPE>(static_cast<UNSIGNED_TYPE>($1) << $3);
}
else else
{ {
$$ = $1 << $3; // 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 { | expression '-' expression {
......
...@@ -958,6 +958,41 @@ TEST_F(IfTest, BitShiftLeftOperatorNegativeLHS) ...@@ -958,6 +958,41 @@ TEST_F(IfTest, BitShiftLeftOperatorNegativeLHS)
preprocess(str, expected); preprocess(str, expected);
} }
// Left shift overflows. Note that the intended result is not explicitly specified, but we assume it
// to do the same operation on the 2's complement bit representation as unsigned shift in C++.
TEST_F(IfTest, BitShiftLeftOverflow)
{
const char *str =
"#if (0x10000 + 0x1) << 28 == 0x10000000\n"
"pass\n"
"#endif\n";
const char *expected =
"\n"
"pass\n"
"\n";
preprocess(str, expected);
}
// Left shift of a negative number overflows. Note that the intended result is not explicitly
// specified, but we assume it to do the same operation on the 2's complement bit representation as
// unsigned shift in C++.
TEST_F(IfTest, BitShiftLeftNegativeOverflow)
{
// The bit representation of -5 is 11111111 11111111 11111111 11111011.
// Shifting by 30 leaves: 11000000 00000000 00000000 00000000.
const char *str =
"#if (-5) << 30 == -1073741824\n"
"pass\n"
"#endif\n";
const char *expected =
"\n"
"pass\n"
"\n";
preprocess(str, expected);
}
// Undefined shift: shift offset is out of range. // Undefined shift: shift offset is out of range.
TEST_F(IfTest, BitShiftRightOperatorNegativeOffset) TEST_F(IfTest, BitShiftRightOperatorNegativeOffset)
{ {
......
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