Two DateTime Parser Bugs
in the AWS SDK for C++
After the
Base64 decoder,
we turned ESBMC on the timestamp parsers of the
AWS SDK for C++
and reported two more defects: unbounded digit accumulation that overflows the parsers'
int field accumulators, and an unchecked
conversion that reported out-of-range dates as successful parses. AWS confirmed both,
took the patch we supplied, and shipped the fix in
PR #3896,
released in SDK 1.11.877.
2
timestamp-parsing bugs we reported, confirmed and fixed by AWS in PR #3896
3
date parsers hardened: RFC822, ISO-8601 and ISO-8601 Basic
1.11.877
AWS SDK for C++ release carrying the fix, published 2026-08-24
12
regression tests added upstream alongside the fix
Context
Aws::Utils::DateTime
is the timestamp type of the AWS SDK for C++, and almost nothing an application does
with AWS avoids it. Credential expiry times, request-signing timestamps, S3
Last-Modified
headers, and every dated field in every service response are parsed through one of
its three parsers: RFC822, ISO-8601, and ISO-8601 Basic. All three run on bytes that
arrived over the network.
Each parser is a hand-written state machine that walks the string one character at a
time. Fields are accumulated digit by digit,
value = value * 10 + (c - '0'),
and the machine advances state when it sees a delimiter. That shape is compact and
fast, and it has a characteristic weakness: the loop is driven by where the
delimiter is, not by how wide the field is allowed to be.
Approach
We analysed the parsers with ESBMC, our software model checker, using the same technique that produced the Base64 findings: rather than feeding the parsers a list of timestamp strings, we drove them with symbolic input and asked the solver whether any string up to a given bound could reach an arithmetic overflow or a silently wrong result.
Timestamp parsing is a good fit for this. The inputs are short, the state space is small, and the properties of interest are exactly the ones a bounded model checker decides directly: does an accumulator leave the range of its type, and does a conversion produce a value the caller will read as valid when it is not.
Results
Unbounded digit accumulation, overflowing the int accumulators.
Nothing bounded how many digits a delimiter-driven field could absorb, so a
timestamp such as
Wed, 99999999999999999999 Oct 2002 08:00:00 GMT
drives the day accumulator past
INT_MAX.
Signed integer overflow is undefined behaviour in C++ ([expr.pre]/4), so what the
parser does from that point on is not defined by the language at all. The same
pattern held for the year, month, hour, minute, and second fields, across all
three parsers. We supplied the patch that bounds each accumulator by its field
width, two digits for day, month, hour, minute and second, four for the year.
Out-of-range dates reported as successful parses. Separately,
ConvertTimestampStringToTimePoint
handed the parsed value to
std::chrono::system_clock::from_time_t
with no range check. That conversion scales seconds up to the clock's tick period,
which on a nanosecond clock leaves the
int64_t
representation spanning only about 1677 to 2262. A date outside that window
overflowed, and the wrong value that came out was returned to the caller as a
successful parse. The fix rejects out-of-range timestamps before converting and
derives the window from the platform clock rather than hard-coding it.
The "never expires" sentinel is the case that bites. Fri, 31 Dec 9999 23:59:59 GMT
is a conventional never-expires marker in HTTP-adjacent code, and it is well
outside a nanosecond clock's range. Before the fix it parsed "successfully" into a
value with no relation to the year 9999, which is precisely the wrong failure mode
for a timestamp a caller is about to compare against the current time to decide
whether something has expired. After the fix,
WasParseSuccessful()
returns false and the caller can see that the value is not usable.
Confirmed and fixed upstream in PR #3896, merged 2026-08-24 and released in AWS SDK for C++ 1.11.877 the same day. The PR carries 12 new regression tests pinning the behaviour, including boundary round-trips at 2262-04-11 and 1677-09-22 and rejection of 9-, 11- and 20-digit day fields. AWS credits the report and the field-width patch in the commit message.
If you use the SDK
Upgrade to AWS SDK for C++ 1.11.877 or later. Note that the second fix changes an
observable behaviour rather than only hardening an internal path: a timestamp outside
the system clock's range now parses as invalid instead of yielding a wrong
value. If your code parses far-future sentinels and does not check
WasParseSuccessful(),
the upgrade will surface that, which is the point, but it is worth knowing before the
version bump rather than after.
What this means
The two defects are different in kind, and only one of them is the sort a memory-safety tool would flag. The digit accumulation is undefined behaviour and a sanitiser could catch it given the right input. The conversion bug produces no crash and no diagnostic: the function returns, the caller's success check passes, and the wrong number propagates. Bounded model checking treats both the same way, because both are just properties to decide over the input space, and neither depends on a test author having guessed the input.
It is also the second engagement with the same codebase, which is the part worth generalising. Once a decoder or a parser has been modelled once, the next one in the same library costs far less, and the findings compound. Small, self-contained routines that sit on untrusted bytes are where this technique pays for itself fastest.
References
- aws/aws-sdk-cpp PR #3896, "Validate DateTime range and bound parser field widths (defense in depth)" (merged 2026-08-24). github.com/aws/aws-sdk-cpp/pull/3896
- aws/aws-sdk-cpp release 1.11.877 (2026-08-24), the first release carrying the fix. github.com/aws/aws-sdk-cpp/releases/tag/1.11.877
- Our earlier work on the same SDK: two Base64 memory-safety CVEs, AWS security bulletin 2026-080. Read the case study
- ESBMC, the open-source bounded model checker used for the analysis. github.com/esbmc/esbmc
Note. The issues were reported by Lucas Carvalho Cordeiro and Rafael Sá Menezes (University of Manchester), acknowledged by name in the upstream commit message. CRC Ltd is not in a commercial partnership with AWS and the analysis was not commissioned by AWS; the findings went through AWS's coordinated vulnerability disclosure process. AWS classified the fix as defence in depth and did not assign a CVE to either issue.