aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Freeland <jfree@FreeBSD.org>2026-03-20 06:33:20 +0000
committerJake Freeland <jfree@FreeBSD.org>2026-03-20 07:15:08 +0000
commite3799530b3ba38567f8052b9e107884609fc71ea (patch)
tree6c54a6af45cba52fa89c9f188ee58fe81789928b
parent85c0f1a87da1fd1eb3e646e86f70e630c48da91a (diff)
sys/time: Add saturating sbt conversions
When converting from timespec to sbintime, the timespec's 64-bit tv_sec component is shifted to the left 32 bits, causing any information in the upper 32 bits to be lost. This data loss during conversion can turn timespecs with very large tv_sec counters into sbintimes that represent much smaller time durations. Add tstosbt_sat() and tvtosbt_sat(), which are saturating versions of tstosbt and tvtosbt. With these routines, any overflow resulting from the conversion is clamped to [-SBT_MAX - 1, SBT_MAX]. Reviewed by: imp, markj Differential Revision: https://reviews.freebsd.org/D55791 MFC after: 2 weeks
-rw-r--r--sys/sys/time.h21
1 files changed, 21 insertions, 0 deletions
diff --git a/sys/sys/time.h b/sys/sys/time.h
index d3a19ebfc811..707565b6a6f1 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -352,6 +352,16 @@ tstosbt(struct timespec _ts)
return (((sbintime_t)_ts.tv_sec << 32) + nstosbt(_ts.tv_nsec));
}
+static __inline sbintime_t
+tstosbt_sat(struct timespec _ts)
+{
+ if (_ts.tv_sec > SBT_MAX >> 32)
+ return (SBT_MAX);
+ if (_ts.tv_sec < -(SBT_MAX >> 32) - 1)
+ return (-SBT_MAX - 1);
+ return (tstosbt(_ts));
+}
+
static __inline struct timeval
sbttotv(sbintime_t _sbt)
{
@@ -368,6 +378,17 @@ tvtosbt(struct timeval _tv)
return (((sbintime_t)_tv.tv_sec << 32) + ustosbt(_tv.tv_usec));
}
+
+static __inline sbintime_t
+tvtosbt_sat(struct timeval _tv)
+{
+ if (_tv.tv_sec > SBT_MAX >> 32)
+ return (SBT_MAX);
+ if (_tv.tv_sec < -(SBT_MAX >> 32) - 1)
+ return (-SBT_MAX - 1);
+ return (tvtosbt(_tv));
+}
+
#endif /* __BSD_VISIBLE */
#ifdef _KERNEL