diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2005-10-10 07:23:03 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2005-10-10 07:23:03 +0000 |
commit | 1964522e91f6aaced069060a1dd8acad26e761ce (patch) | |
tree | a93117d330381c16a9d3359c835d85ffafc72edf /sys/kern/kern_time.c | |
parent | 047615e69f96fdfe217e854b3be08f91f348a29d (diff) |
Avoid arithmetic overflows in computation of adjtime(). Fixes adjusting in the
wrong direction for large offsets as nick@ saw. With tom@ and toby@;
ok tdeval@ krw@
Diffstat (limited to 'sys/kern/kern_time.c')
-rw-r--r-- | sys/kern/kern_time.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 8fa57ea24ed..2ed842aab04 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_time.c,v 1.48 2005/05/31 11:32:47 art Exp $ */ +/* $OpenBSD: kern_time.c,v 1.49 2005/10/10 07:23:02 otto Exp $ */ /* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */ /* @@ -419,8 +419,21 @@ sys_adjtime(p, v, retval) * hardclock(), tickdelta will become zero, lest the correction * overshoot and start taking us away from the desired final time. */ - ndelta = atv.tv_sec * 1000000 + atv.tv_usec; - if (ndelta > bigadj) + if (atv.tv_sec > LONG_MAX / 1000000L) + ndelta = LONG_MAX; + else if (atv.tv_sec < LONG_MIN / 1000000L) + ndelta = LONG_MIN; + else { + ndelta = atv.tv_sec * 1000000L; + odelta = ndelta; + ndelta += atv.tv_usec; + if (atv.tv_usec > 0 && ndelta <= odelta) + ndelta = LONG_MAX; + else if (atv.tv_usec < 0 && ndelta >= odelta) + ndelta = LONG_MIN; + } + + if (ndelta > bigadj || ndelta < -bigadj) ntickdelta = 10 * tickadj; else ntickdelta = tickadj; |