summaryrefslogtreecommitdiff
path: root/lib/util/time.c
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2019-12-06 16:45:04 +0000
committerRalph Boehme <slow@samba.org>2019-12-09 16:10:38 +0000
commitf0813cbf4f507462b5b9aa0e913483232e51bea5 (patch)
treec702a780df4a61c467d69c46d992c145fb251d46 /lib/util/time.c
parent99d153fad120e0a9335ec474296f55a2e258561a (diff)
downloadsamba-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.c30
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;
}