This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[PATCH] Fix the UB in regex caused by long decimal string
- From: "Tim Shen via libstdc++" <libstdc++ at gcc dot gnu dot org>
- To: "libstdc++" <libstdc++ at gcc dot gnu dot org>
- Date: Fri, 10 Feb 2017 17:19:44 -0800
- Subject: [PATCH] Fix the UB in regex caused by long decimal string
- Authentication-results: sourceware.org; auth=none
- Reply-to: Tim Shen <timshen at google dot com>
LibFuzzer found a signed integer overflow UB in the regex library!
Here is the fix. Bootstrapped and tested on x86_64-linux-gnu.
Thanks!
--
Regards,
Tim Shen
diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc
index a6d8016d87f..b0aed277cf3 100644
--- a/libstdc++-v3/include/bits/regex_compiler.tcc
+++ b/libstdc++-v3/include/bits/regex_compiler.tcc
@@ -601,9 +601,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_cur_int_value(int __radix)
{
long __v = 0;
+ __glibcxx_assert(__radix > 1);
for (typename _StringT::size_type __i = 0;
__i < _M_value.length(); ++__i)
- __v =__v * __radix + _M_traits.value(_M_value[__i], __radix);
+ {
+ if (__v > std::numeric_limits<long>::max() / __radix)
+ __throw_regex_error(
+ regex_constants::error_complexity,
+ "Brace expression contains a number that's too large");
+ __v = __v * __radix + _M_traits.value(_M_value[__i], __radix);
+ }
return __v;
}
diff --git a/libstdc++-v3/include/std/regex b/libstdc++-v3/include/std/regex
index 777edd96d73..df363d3dca4 100644
--- a/libstdc++-v3/include/std/regex
+++ b/libstdc++-v3/include/std/regex
@@ -41,6 +41,7 @@
# include <iosfwd>
#endif
#include <iterator>
+#include <limits>
#include <locale>
#include <memory>
#include <sstream>
diff --git a/libstdc++-v3/testsuite/28_regex/regression.cc b/libstdc++-v3/testsuite/28_regex/regression.cc
index ee4d3e1e6f8..8ab2d5c1cca 100644
--- a/libstdc++-v3/testsuite/28_regex/regression.cc
+++ b/libstdc++-v3/testsuite/28_regex/regression.cc
@@ -93,6 +93,22 @@ test06()
}
}
+// Huge brace expression number.
+void
+test07()
+{
+ bool thrown = false;
+ try
+ {
+ std::basic_regex<char> r("a{444444444444444444444444444}");
+ }
+ catch (const std::regex_error &e)
+ {
+ thrown = true;
+ }
+ VERIFY(thrown);
+}
+
int
main()
{
@@ -102,6 +118,7 @@ main()
test04();
test05();
test06();
+ test07();
return 0;
}