Skip to content

fix: account for DST in XCCDF result timestamp offset#2367

Open
eran132 wants to merge 2 commits into
OpenSCAP:mainfrom
eran132:fix/timestamp-dst-offset
Open

fix: account for DST in XCCDF result timestamp offset#2367
eran132 wants to merge 2 commits into
OpenSCAP:mainfrom
eran132:fix/timestamp-dst-offset

Conversation

@eran132
Copy link
Copy Markdown

@eran132 eran132 commented Jun 6, 2026

Problem

oscap writes start-time / end-time attributes on XCCDF TestResult
elements via _get_timestamp() in src/XCCDF/result.c. On glibc the UTC
offset was derived from the global timezone variable, which holds the
standard-time offset and ignores daylight saving time. The wall-clock
fields (tm_hour, ...) come from localtime_r() and are DST-adjusted, so
during DST the offset and the time disagreed and the timestamp pointed to the
wrong instant — exactly the symptom in #1972 (an America/Los_Angeles scan in
summer emitted -08:00 instead of -07:00, an hour off).

Fix

Use struct tm.tm_gmtoff when the platform provides it. tm_gmtoff is the
offset east of UTC in seconds, already including DST, so it matches the actual
offset in effect at the represented local time.

  • New HAVE_STRUCT_TM_TM_GMTOFF CMake feature check (check_struct_has_member).
  • Platforms without tm_gmtoff (e.g. the MSVC runtime) keep the timezone
    global path, now corrected to add an hour when tm_isdst > 0.
  • Removes the old FreeBSD-only branch that re-added 3600s specifically to
    reproduce the glibc bug for consistency; FreeBSD now takes the correct
    tm_gmtoff path like glibc.

Verification

A full project build was not possible in my environment (no cmake / xmlsec1
and no sudo), but I verified the change directly:

  • Logic, executed: compiled the exact offset logic standalone and compared
    against libc's authoritative strftime("%z") for America/Los_Angeles,
    Europe/Berlin and UTC, in both summer and winter. Both the tm_gmtoff
    path and the fallback path produce the correct offset in every case
    (-07:00/-08:00, +02:00/+01:00, +00:00).
  • Compiles in context: gcc -fsyntax-only on the edited result.c against
    the real project headers passes cleanly with HAVE_STRUCT_TM_TM_GMTOFF
    defined and undefined (both #ifdef branches).

Fixes #1972

The start-time/end-time attributes on XCCDF TestResult elements are
produced by _get_timestamp(). On glibc the offset was taken from the
global `timezone` variable, which holds the standard-time offset and
does not account for daylight saving time. The wall-clock fields come
from localtime_r() and are DST-correct, so during DST the printed
offset was wrong by one hour, making the timestamp denote the wrong
instant (e.g. an America/Los_Angeles scan in summer reported -08:00
instead of -07:00).

Use struct tm.tm_gmtoff when available; it carries the actual UTC
offset in effect at the represented local time, DST included. A new
HAVE_STRUCT_TM_TM_GMTOFF CMake feature check guards it, falling back to
the timezone global (plus a DST hour) on platforms without tm_gmtoff
such as the MSVC runtime. This also drops the FreeBSD-specific branch
that previously re-added an hour to deliberately mirror the glibc bug.

Fixes OpenSCAP#1972

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 6, 2026 11:12
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.

This PR improves cross-platform timezone offset handling when generating timestamps by preferring struct tm.tm_gmtoff when available and adding a configure-time check for it.

Changes:

  • Use tm_gmtoff (when present) for UTC offset, including DST, instead of platform-specific conditionals.
  • Add a CMake compile-time probe and config macro (HAVE_STRUCT_TM_TM_GMTOFF) to detect tm_gmtoff.
  • Refine fallback offset logic using the global timezone value plus DST adjustment.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/XCCDF/result.c Switches to tm_gmtoff when available; adjusts fallback timezone logic and comments.
config.h.in Adds HAVE_STRUCT_TM_TM_GMTOFF config define.
CMakeLists.txt Adds check_struct_has_member probe for struct tm.tm_gmtoff.

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

Comment thread src/XCCDF/result.c
Comment on lines +1858 to +1863
/* Fallback for platforms without tm_gmtoff (e.g. the MSVC runtime).
* timezone is a global variable set by localtime(3) holding the offset
* of standard time; add an hour when daylight saving time is in effect. */
long std_diff = timezone;
if (lt->tm_isdst > 0)
std_diff -= 3600;
The fallback path subtracts 3600 seconds from `timezone`, but the
comment described this as "add an hour", which reads as contradicting
the code. Reword to explain that `timezone` is seconds west of UTC and
DST shifts local time one hour east (closer to UTC), so the westward
offset is reduced by 3600 seconds. No behavior change.
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 6, 2026

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.

start-time and end-time incorrect for non-UTC timezones

2 participants