From 1d3b54c784da260f71d885f5f560d69c211a645e Mon Sep 17 00:00:00 2001 From: Flavio Toffalini Date: Mon, 26 Oct 2026 09:03:57 +0000 Subject: plist: fix the (sec, usec) date API round trip plist_set_date_val stores val = sec + usec / 1000000, but plist_get_date_val splits it with a truncating cast and fabs(): *sec = (int32_t)val; val = fabs((val - (int64_t)val) * 1000000); *usec = (int32_t)val; Two results are wrong. The product is truncated, so set(5, 6) reads back as (5, 5) - 29.3% of round trips over sec in [0, 3] come back a microsecond short. And for a negative value, truncation toward zero plus fabs() give a pair that does not denote the same instant: set(-3, 250000) stores -2.75 and reads back as (-2, 750000), which the setter would store as -1.25. Every round trip with sec < 0 and usec != 0 is wrong. (int32_t)val is also undefined when the stored value is outside the int32_t range. Round the seconds down, round the fraction to microseconds carrying 1000000 into the seconds, and clamp the seconds before converting, so sec + usec / 1000000 == val to the microsecond with 0 <= usec < 1000000 - the convention the setter uses. Add test/date_val.c covering fixed cases and a sweep over sec in [-2, 2]. It fails on an unmodified tree - set(5, 6), set(-3, 250000) and set(-1, 1) all come back as different instants - and passes with this change, with make check at 44/44. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Arn4YaWtcQBDsQuJtyBmFP --- test/Makefile.am | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'test/Makefile.am') diff --git a/test/Makefile.am b/test/Makefile.am index 1d98349..2e2b04e 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -11,6 +11,7 @@ noinst_PROGRAMS = \ plist_test \ plist_test++ \ integer_set_test \ + date_val_test \ plist_btest \ plist_jtest \ plist_otest \ @@ -31,6 +32,9 @@ plist_test_LDADD = $(top_builddir)/src/libplist-2.0.la integer_set_test_SOURCES = integer_set.c integer_set_test_LDADD = $(top_builddir)/src/libplist-2.0.la +date_val_test_SOURCES = date_val.c +date_val_test_LDADD = $(top_builddir)/src/libplist-2.0.la + plist_btest_SOURCES = plist_btest.c plist_btest_LDADD = $(top_builddir)/src/libplist-2.0.la @@ -47,6 +51,7 @@ bplist_behavior_test_SOURCES = bplist_behavior_test.c bplist_behavior_test_LDADD = $(top_builddir)/src/libplist-2.0.la TESTS = \ + date_val.test \ empty.test \ small.test \ medium.test \ -- cgit v1.1-32-gdbae