Rework format string protection to be non-throwing.

Remove old test case, fix up tests to disable testing the new issues on the recursive implementation which will be going soon anyway.
This commit is contained in:
jzmaddock
2024-03-17 16:12:14 +00:00
parent b99ec17c8e
commit ae34d3cfc5
6 changed files with 10 additions and 40 deletions

View File

@ -201,11 +201,6 @@ OutputIterator basic_regex_formatter<OutputIterator, Results, traits, ForwardIte
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_all(unsigned recursion_count)
{
if (recursion_count > BOOST_REGEX_MAX_RECURSION_DEPTH)
{
// We need to protect ourselves from bad format strings used as DOS attacks:
throw std::runtime_error("Excessive recursion in format string, this looks like a deliberately malformed expression.");
}
// over and over:
while(m_position != m_end)
{
@ -224,7 +219,7 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
format_escape();
break;
case '(':
if(m_flags & boost::regex_constants::format_all)
if((m_flags & boost::regex_constants::format_all) && (recursion_count < BOOST_REGEX_MAX_RECURSION_DEPTH))
{
++m_position;
bool have_conditional = m_have_conditional;
@ -257,7 +252,7 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
++m_position;
break;
case '?':
if(m_flags & boost::regex_constants::format_all)
if((m_flags & boost::regex_constants::format_all) && (recursion_count < BOOST_REGEX_MAX_RECURSION_DEPTH))
{
++m_position;
format_conditional(recursion_count);

View File

@ -151,4 +151,3 @@ compile test_windows_defs_3.cpp ;
compile test_windows_defs_4.cpp ;
run issue153.cpp : : : <toolset>msvc:<linkflags>-STACK:2097152 ;
run bad_format_string.cpp ;

View File

@ -1,32 +0,0 @@
/*
*
* Copyright (c) 2024
* John Maddock
*
* Use, modification and distribution are subject to the
* Boost Software License, Version 1.0. (See accompanying file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
*/
#include <iostream>
#include <boost/regex.hpp>
#include <boost/core/lightweight_test.hpp>
int main()
{
try{
std::string format_string("(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((");
boost::regex e("foo");
std::string in("foobar");
std::string out;
boost::regex_replace(std::back_inserter(out), in.begin(), in.end(),
e, format_string, boost::match_default | boost::format_all);
BOOST_TEST(false);
}
catch (const std::runtime_error&)
{
std::cout << "OK" << std::endl;
}
return boost::report_errors();
}

View File

@ -52,6 +52,8 @@ void test_alt()
TEST_REGEX_SEARCH("a\nb", egrep, "b", match_default, make_array(0, 1, -2, -2));
TEST_REGEX_SEARCH("a\nb", egrep, "a", match_default, make_array(0, 1, -2, -2));
// DOS protection:
#ifndef BOOST_REGEX_RECURSIVE
TEST_INVALID_REGEX("(|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||(?0))", perl);
#endif
}

View File

@ -64,6 +64,8 @@ void test_anchors()
TEST_REGEX_SEARCH_W(L".$", boost::regex::extended, L" \x2028 \x2028", match_default, make_array(0, 1, -2, 2, 3, -2, 3, 4, -2, -2));
#endif
// DOS attack prevention:
#ifndef BOOST_REGEX_RECURSIVE
TEST_INVALID_REGEX("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", perl);
#endif
}

View File

@ -194,5 +194,9 @@ void test_replace()
TEST_REGEX_REPLACE("(a*)", perl, "aabb", match_default, "{$1}", "{aa}{}b{}b{}");
TEST_REGEX_REPLACE("(a*)", boost::regex::extended, "aabb", match_default, "{$1}", "{aa}{}b{}b{}");
TEST_REGEX_REPLACE("(a*)", boost::regex::extended, "aabb", match_default|match_posix, "{$1}", "{aa}b{}b{}");
#ifndef BOOST_REGEX_RECURSIVE
// DOS protection:
TEST_REGEX_REPLACE("foo", boost::regex::perl, "foobar", match_default|format_all, "(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((", "(((((((((((((((((((((bar");
#endif
}