aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2023-08-03 08:45:43 +0100
committerJonathan Wakely <jwakely@redhat.com>2023-08-07 22:09:10 +0100
commit5d87f71bb462ccb78dd3d9d810ea08d96869cb4b (patch)
tree9f3d9355979598043fc0c298e91a3c9b38212e67
parenteff0e7a4ae31d1e4e64ae37bbc10d073d8579255 (diff)
downloadgcc-5d87f71bb462ccb78dd3d9d810ea08d96869cb4b.zip
gcc-5d87f71bb462ccb78dd3d9d810ea08d96869cb4b.tar.gz
gcc-5d87f71bb462ccb78dd3d9d810ea08d96869cb4b.tar.bz2
libstdc++: Fix past-the-end increment in std::format [PR110862]
At the end of a replacement field we should check that the closing brace is actually present before incrementing past it. libstdc++-v3/ChangeLog: PR libstdc++/110862 * include/std/format (_Scanner::_M_on_replacement_field): Check for expected '}' before incrementing iterator. * testsuite/std/format/string.cc: Check "{0:{0}" format string.
-rw-r--r--libstdc++-v3/include/std/format4
-rw-r--r--libstdc++-v3/testsuite/std/format/string.cc13
2 files changed, 16 insertions, 1 deletions
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 1e0ef61..0debbae 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -3534,7 +3534,9 @@ namespace __format
_M_pc.advance_to(__ptr);
}
_M_format_arg(__id);
- _M_pc.advance_to(_M_pc.begin() + 1); // Move past '}'
+ if (begin() == end() || *begin() != '}')
+ __format::__unmatched_left_brace_in_format_string();
+ _M_pc.advance_to(begin() + 1); // Move past '}'
}
constexpr virtual void _M_format_arg(size_t __id) = 0;
diff --git a/libstdc++-v3/testsuite/std/format/string.cc b/libstdc++-v3/testsuite/std/format/string.cc
index d28135e..6a45237 100644
--- a/libstdc++-v3/testsuite/std/format/string.cc
+++ b/libstdc++-v3/testsuite/std/format/string.cc
@@ -128,6 +128,19 @@ test_format_spec()
VERIFY( ! is_format_string_for("{:9999999}", 1) );
}
+void
+test_pr110862()
+{
+ try {
+ // PR libstdc++/110862 out-of-bounds read on invalid format string
+ (void) std::vformat("{0:{0}", std::make_format_args(1));
+ VERIFY( false );
+ } catch (const std::format_error& e) {
+ std::string_view what = e.what();
+ VERIFY( what.find("unmatched left brace") != what.npos );
+ }
+}
+
int main()
{
test_no_args();