Skip to content

<chrono>: Fix stack buffer overflow in chrono::parse() with modified widths#6270

Open
StephanTLavavej wants to merge 8 commits into
microsoft:mainfrom
StephanTLavavej:stack-of-pancakes
Open

<chrono>: Fix stack buffer overflow in chrono::parse() with modified widths#6270
StephanTLavavej wants to merge 8 commits into
microsoft:mainfrom
StephanTLavavej:stack-of-pancakes

Conversation

@StephanTLavavej
Copy link
Copy Markdown
Member

Fixes #6269. (This bug was found by Copilot CLI with Opus 4.7, but this writeup, fix, and tests are all mine.)

  • Fix stack buffer write overrun in chrono::_Time_parse_fields::_Get_int().
    • Testing against cend(_Ac) - 1 is the fix. Add a comment explaining why. Moving *_Ptr = _Ch; inside the bounds test isn't necessary for the fix, but avoids potentially wacky behavior. If we continue to consume digits, we should exhibit the commented behavior of "drop trailing digits if already too large". Previously, we would keep updating the last digit, which makes no sense.
  • <xloctime>: Improve _Getint_v2().
    • Add the same comment to the _Ptr < _Pe test. Similarly, move *_Ptr = _Ch; inside the bounds test, in accordance with the "drop trailing digits if already too large" comment. AFAICT, this has no behavioral impact since we're additionally limited by _Digits_read < _Hi_digits and _Hi_digits is at most 4.
  • Avoid unnecessarily confusing overloading: test_parse() => test_all_parse()
  • Reorder test_lwg_3536(), test_lwg_3956(), no other changes.
    • We try to call test functions in definition order, and we usually test LWG resolutions last.
  • Enhance test_parse(), fail_parse() to take basic_string and use source_location.
  • Fix pre-existing inconsistency: Use 29d when testing year_month_day.
  • Pre-existing: Use basic_istringstream, basic_ostringstream instead of basic_stringstream.
    • We try to use the most specific types possible.
  • Add tests: parse_modified_maximum_characters()

…nt()`.

Testing against `cend(_Ac) - 1` is the fix. Add a comment explaining why.

Moving `*_Ptr = _Ch;` inside the bounds test isn't necessary for the fix, but avoids potentially wacky behavior.
If we continue to consume digits, we should exhibit the commented behavior of "drop trailing digits if already too large".
Previously, we would keep updating the last digit, which makes no sense.
Add the same comment to the `_Ptr < _Pe` test.

Similarly, move `*_Ptr = _Ch;` inside the bounds test, in accordance with the "drop trailing digits if already too large" comment.
AFAICT, this has no behavioral impact since we're additionally limited by `_Digits_read < _Hi_digits` and `_Hi_digits` is at most 4.
We try to call test functions in definition order, and we usually test LWG resolutions last.
@StephanTLavavej StephanTLavavej requested a review from a team as a code owner May 4, 2026 18:43
Copilot AI review requested due to automatic review settings May 4, 2026 18:43
@StephanTLavavej StephanTLavavej added bug Something isn't working chrono C++20 chrono labels May 4, 2026
@github-project-automation github-project-automation Bot moved this to Initial Review in STL Code Reviews May 4, 2026
@StephanTLavavej StephanTLavavej moved this from Initial Review to Final Review in STL Code Reviews May 4, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Fixes a stack buffer overflow in chrono::parse() when parsing fields with modified widths, and extends the test suite to cover the corrected behavior.

Changes:

  • Fix off-by-one buffer bounds checks in chrono::_Time_parse_fields::_Get_int() and <xloctime>’s _Getint_v2() to preserve space for the null terminator.
  • Improve parsing tests by adding coverage for modified maximum character widths and enhancing diagnostics via source_location.
  • Minor test refactors: rename test_parse() runner, reorder LWG tests, and tighten stream types (istringstream/ostringstream).
Show a summary per file
File Description
tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp Adds diagnostics and new regression tests for modified-width parsing; minor test refactors.
stl/inc/xloctime Adjusts digit-copy loop to avoid writing past the buffer when leaving room for a null terminator.
stl/inc/chrono Fixes off-by-one bounds check to prevent stack buffer overwrite during integer field parsing.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 4

Comment thread tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp
Comment thread tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp
Comment thread tests/std/tests/P0355R7_calendars_and_time_zones_io/test.cpp
Comment thread stl/inc/chrono
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working chrono C++20 chrono

Projects

Status: Final Review

Development

Successfully merging this pull request may close these issues.

<chrono>: Stack buffer overflow in chrono::parse() with modified widths

2 participants