Skip to main content
All case studies
Cloud SDK · C++ · 2026

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

  1. 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
  2. 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
  3. Our earlier work on the same SDK: two Base64 memory-safety CVEs, AWS security bulletin 2026-080. Read the case study
  4. 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.