guard negative operands in MathLib::value shift operators#8639
guard negative operands in MathLib::value shift operators#8639metsw24-max wants to merge 2 commits into
Conversation
|
Thanks for your contribution. template <uint64_t u>
uint64_t f() { return u; }
int main() {
f<1 << 0x8000000000000000>();
}Please add such a test case in testsimplifytemplate.cpp (even better if you have a valid example). Regarding the CI failure, there might be missing |
Move the regression test to testsimplifytemplate.cpp so it exercises the reachable path through simplifyNumericCalculations instead of calling the MathLib::value operators directly, which are not exported and broke the Windows/test link.
|
Moved the regression test into testsimplifytemplate.cpp. On the example: the bare template <long long> struct S { };
S<(0x8000000000000000 << 1)> s1; // negative left operand
S<(1 << 0x8000000000000000)> s2; // negative count
S<(1 >> 0x8000000000000000)> s3; // negative count, shiftRightWithout the guard s1 folds to On the CI failure: moving the test off the |
the value shift operators only reject a count >= bigint_bits, so MathLib::value::shiftLeft still left-shifts a negative value and both shiftLeft and shiftRight still shift by a negative count, which is undefined behaviour. it is reachable when folding a template argument like 0x8000000000000000 << 1 in simplifyNumericCalculations, since MathLib::isNegative only checks for a leading minus while a large hex literal parses to a negative bigint and the guard there lets it through. mirror the negative-operand check calculate.h already uses and return the operand unchanged, as is already done for oversized counts. ubsan flags the left shift at mathlib.cpp:272 on that input.