Skip to content

fix: correct fractional seconds normalization in RFC3339 parser - #242

Merged
vlastahajek merged 1 commit into
tobiasschuerg:masterfrom
se-fLa:fix/rfc3339-fractional-seconds-xor
Jun 9, 2026
Merged

vlastahajek merged 1 commit into
tobiasschuerg:masterfrom
se-fLa:fix/rfc3339-fractional-seconds-xor

Conversation

@se-fLa

@se-fLa se-fLa commented May 24, 2026 •

Copy link
Copy Markdown
Contributor

In convertRfc3339(), the intent was to normalize a sub-6-digit fractional seconds value to microseconds by multiplying by a power of 10. The code used the ^ operator for this, which in C++ is bitwise XOR - not exponentiation. There is no exponentiation operator in C++.

This caused incorrect microsecond values for any RFC3339 timestamp with fewer than 6 fractional digits. The most common real-world case is 3-digit millisecond precision (e.g. '2020-02-18T10:34:08.135Z'), where the multiplier becomes 10 XOR 3 = 9 instead of 1000, producing a result roughly 111x too small.

Timestamps with 6 digits (microseconds) or 7-9 digits (nanoseconds, truncated to 6 before this branch) are not affected.

The struct tm fields (year, month, day, hour, minute, second) are parsed separately by sscanf and are always correct. Only the sub-second microseconds field is affected.

Proposed Changes

replace the single XOR expression with an explicit multiply loop, which avoids pulling in <math.h> for pow() and keeps the arithmetic integer throughout.

Checklist

  • CHANGELOG.md updated
  • Rebased/mergeable
  • A test has been added if appropriate
  • Tests pass
  • Commit messages are in semantic format

In convertRfc3339(), the intent was to normalize a sub-6-digit fractional
seconds value to microseconds by multiplying by a power of 10. The code
used the ^ operator for this, which in C++ is bitwise XOR - not
exponentiation. There is no exponentiation operator in C++.

This caused incorrect microsecond values for any RFC3339 timestamp with
fewer than 6 fractional digits. The most common real-world case is
3-digit millisecond precision (e.g. '2020-02-18T10:34:08.135Z'), where
the multiplier becomes 10 XOR 3 = 9 instead of 1000, producing a result
roughly 111x too small.

Timestamps with 6 digits (microseconds) or 7-9 digits (nanoseconds,
truncated to 6 before this branch) are not affected.

The struct tm fields (year, month, day, hour, minute, second) are parsed
separately by sscanf and are always correct. Only the sub-second
microseconds field is affected.

Fix: replace the single XOR expression with an explicit multiply loop,
which avoids pulling in <math.h> for pow() and keeps the arithmetic
integer throughout.
@se-fLa

se-fLa commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Have you seen this PR @tobiasschuerg ?

@vlastahajek vlastahajek left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for noticing this and for the PR!.

@vlastahajek
vlastahajek merged commit deaa777 into tobiasschuerg:master Jun 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants