diff options
author | Ralph Boehme <slow@samba.org> | 2019-12-06 16:45:04 +0000 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2019-12-09 16:10:38 +0000 |
commit | f0813cbf4f507462b5b9aa0e913483232e51bea5 (patch) | |
tree | c702a780df4a61c467d69c46d992c145fb251d46 /lib/util/time.c | |
parent | 99d153fad120e0a9335ec474296f55a2e258561a (diff) | |
download | samba-f0813cbf4f507462b5b9aa0e913483232e51bea5.tar.gz |
lib: harden full_timespec_to_nt_time()
This protects against overflows when tv_sec is less then
TIME_FIXUP_CONSTANT_INT.
It also correctly limits the range of returned values to be
[NTTIME_MIN, NTTIME_MAX].
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'lib/util/time.c')
-rw-r--r-- | lib/util/time.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/lib/util/time.c b/lib/util/time.c index 0875c9fbda9..d8f1daca901 100644 --- a/lib/util/time.c +++ b/lib/util/time.c @@ -1080,23 +1080,37 @@ struct timespec make_omit_timespec(void) * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0 * and -1. Also dealing with SAMBA_UTIME_OMIT. **/ -NTTIME full_timespec_to_nt_time(const struct timespec *ts) +NTTIME full_timespec_to_nt_time(const struct timespec *_ts) { + struct timespec ts = *_ts; uint64_t d; - if (ts->tv_sec == TIME_T_MAX) { - return 0x7fffffffffffffffLL; + if (is_omit_timespec(_ts)) { + return NTTIME_OMIT; } - if (is_omit_timespec(ts)) { - return 0; + /* Ensure tv_nsec is less than 1 sec. */ + while (ts.tv_nsec > 1000000000) { + if (ts.tv_sec > TIME_T_MAX) { + return NTTIME_MAX; + } + ts.tv_sec += 1; + ts.tv_nsec -= 1000000000; } - d = ts->tv_sec; - d += TIME_FIXUP_CONSTANT_INT; + if (ts.tv_sec >= TIME_T_MAX) { + return NTTIME_MAX; + } + if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) { + return NTTIME_MIN; + } + + d = TIME_FIXUP_CONSTANT_INT; + d += ts.tv_sec; + d *= 1000*1000*10; /* d is now in 100ns units. */ - d += (ts->tv_nsec / 100); + d += (ts.tv_nsec / 100); return d; } |