Fix: DateTimeParser trailing timezone designators & Timezone UTC offset cache invalidation#5318
Fix: DateTimeParser trailing timezone designators & Timezone UTC offset cache invalidation#5318kozemcak wants to merge 2 commits intopocoproject:mainfrom
Conversation
Commit 8410eb1 ("fix(Foundation): Reject trailing garbage in DateTimeParser (pocoproject#5030) (pocoproject#5117)") added a strict check that throws SyntaxException when any characters remain unconsumed after parsing. This breaks date strings that carry a trailing timezone indicator that is not captured by the format string -- a common, valid pattern in many date-time representations: - ISO 8601 / RFC 3339: "2013-10-07 08:23:19.120-04:00" - UTC indicator: "230101120000Z" (ASN.1 UTCTime) - Named zones: "Mon, 07 Oct 2013 08:23:19 GMT" Affected users include: - Poco::Crypto::X509Certificate::validFrom() and expiresOn(), which parse ASN.1 time strings (e.g. "YYMMDDHHMMSSZ") using DateTimeParser::parse() with format "%y%m%d%H%M%S". The trailing 'Z' was left unconsumed, triggering the exception and causing certificate loading to fail. - Application code that stores and validates ISO 8601 date strings with numeric UTC offsets (e.g. "2013-10-07 08:23:19.120-04:00") using DateTimeParser::parse() with ISO8601_FORMAT ("%Y-%m-%dT%H:%M:%S%z"). The %z specifier calls parseTZD() but parseTZD() returns without consuming anything when it sees '.' (fractional seconds); the remaining ".120-04:00" then triggers the trailing-garbage check. Fix: after skipping trailing whitespace: 1. Skip optional fractional seconds ('.' or ',' followed by digits) that were left unconsumed because the format used %S (integer seconds) instead of %s (fractional seconds). 2. Attempt to consume an optional trailing timezone designator using the existing parseTZD() helper (handles 'Z', named zones, and +/-HH:MM numeric offsets). The iterator is restored if parseTZD() throws, so that truly invalid trailing characters are still caught by the downstream check. Signed-off-by: Andrej Kozemcak <andrej.kozemcak@siemens.com>
…time changes Poco commit 1850dc1 introduced a TZInfo cache for the UTC offset to avoid repeated tzset() syscalls. The cache is invalidated only when the TZ environment variable changes. However, the TZ variable is process-local: if a different process (e.g. a timezone configuration daemon or an init script) changes the system timezone by updating /etc/localtime, the running process is not notified and its TZ environment variable remains unchanged. On systems that switch timezone by updating /etc/localtime (a symlink) without touching the TZ env var, the cache is therefore never invalidated and Timezone::utcOffset() returns the stale value computed at startup. Fix by extending cacheTZ()/tzChanged() to also track the inode and mtime of /etc/localtime via stat(2). When either changes the cache is considered stale and reloaded, preserving the performance benefit for the common case where neither TZ nor /etc/localtime changes between calls. Signed-off-by: Andrej Kozemcak <andrej.kozemcak@siemens.com>
|
The ASN.1 UTCTime issue ( The other example The real issue is that case 'S':
it = skipNonDigits(it, end);
second = parseNumberN(dtStr, it, end, 2);
if (it != end && (*it == '.' || *it == ','))
{
++it;
it = skipDigits(it, end);
}
break;This way |
|
Hi matejk, Thank you for the answer. Next week I will look at that and I will try your suggestion. |
Hi all,
After we update poco to new version our applications tests start failing. We identified these issues and fix it. Some of the issues are little specific, so we are interesting what you say about that. Here are quick summary of our changes.
Thanks.
Summary
This MR contains two bug fixes for the
Foundationlibrary addressing datetime parsing and timezone handling regressions.Changes
1.
fix(Foundation): DateTimeParser: allow trailing timezone designatorsA strict trailing-garbage check introduced in commit
8410eb1a6broke parsing of valid date strings with trailing timezone indicators not captured by the format string.Affected scenarios:
"230101120000Z") used byPoco::Crypto::X509Certificate::validFrom()andexpiresOn()— caused certificate loading to fail"2013-10-07 08:23:19.120-04:00") — triggered falseSyntaxExceptionFix: After skipping trailing whitespace, optionally consume fractional seconds and/or a trailing timezone designator before the trailing-garbage check.
2.
fix(Foundation): Timezone: invalidate utcOffset cache when /etc/localtime changesThe
TZInfoUTC offset cache introduced in Poco commit1850dc16is only invalidated when theTZenvironment variable changes. SinceTZis process-local, system timezone changes via/etc/localtime(symlink update) go undetected, causingTimezone::utcOffset()to return a stale value.Fix: Extend
cacheTZ()/tzChanged()to track the inode andmtimeof/etc/localtimeviastat(2). Cache is invalidated when either changes.Testing
utcOffset()reflects timezone changes after/etc/localtimeis updated without modifyingTZ