libstdc++: Check for overflow in regex back-reference [PR106607]

Currently we fail to notice integer overflow when parsing a
back-reference expression, or when converting the parsed result from
long to int. This changes the result to be int, so no conversion is
needed, and uses the overflow-checking built-ins to detect an
out-of-range back-reference.

libstdc++-v3/ChangeLog:

	PR libstdc++/106607
	* include/bits/regex_compiler.tcc (_Compiler::_M_cur_int_value):
	Use built-ins to check for integer overflow in back-reference
	number.
	* testsuite/28_regex/basic_regex/106607.cc: New test.
This commit is contained in:
Jonathan Wakely
2022-08-22 15:16:16 +01:00
parent 990124c35c
commit 1b09eea33f
2 changed files with 31 additions and 4 deletions

View File

@@ -583,10 +583,12 @@ namespace __detail
_Compiler<_TraitsT>::
_M_cur_int_value(int __radix)
{
long __v = 0;
for (typename _StringT::size_type __i = 0;
__i < _M_value.length(); ++__i)
__v =__v * __radix + _M_traits.value(_M_value[__i], __radix);
int __v = 0;
for (_CharT __c : _M_value)
if (__builtin_mul_overflow(__v, __radix, &__v)
|| __builtin_add_overflow(__v, _M_traits.value(__c, __radix), &__v))
std::__throw_regex_error(regex_constants::error_backref,
"invalid back reference");
return __v;
}

View File

@@ -0,0 +1,25 @@
// { dg-do run { target c++11 } }
#include <regex>
#include <string>
#include <climits>
#include <testsuite_hooks.h>
// PR libstdc++/106607 - Regex integer overflow on large backreference value
int main()
{
std::regex r("(.)\\1"); // OK
try
{
long long n = (unsigned)-1 + 2LL; // 4294967297 for 32-bit int
VERIFY( (int)n == 1 ); // 4294967297 % 2^32 == 1
std::regex r("(.)\\" + std::to_string(n)); // Invalid back reference.
VERIFY(false);
}
catch (const std::regex_error& e)
{
VERIFY( e.code() == std::regex_constants::error_backref );
}
}