Skip to content

Commit 9e10ffa

Browse files
authored
time: fix overflow in time.sys_mono_now() on windows (#26273)
1 parent 03d2675 commit 9e10ffa

1 file changed

Lines changed: 20 additions & 6 deletions

File tree

‎vlib/time/time_windows.c.v‎

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ fn C.localtime_s(t &C.time_t, tm &C.tm)
4444

4545
fn C.timespec_get(t &C.timespec, base int) int
4646

47-
// start_time is needed on Darwin and Windows because of potential overflows
47+
// start_time and time_coefficients are needed on Windows because of potential overflows
4848
const start_time = init_win_time_start()
49-
const freq_time = init_win_time_freq()
49+
const time_coefficients = init_win_time_coefficients()
5050
const start_local_time = local_as_unix_time()
5151

5252
// in most systems, these are __quad_t, which is an i64
@@ -64,10 +64,24 @@ fn make_unix_time(t C.tm) i64 {
6464
return portable_timegm(&t)
6565
}
6666

67-
fn init_win_time_freq() u64 {
68-
f := u64(0)
67+
struct WinTimeCoefficients {
68+
numer u64
69+
denom u64
70+
}
71+
72+
fn init_win_time_coefficients() WinTimeCoefficients {
73+
mut f := u64(0)
6974
C.QueryPerformanceFrequency(voidptr(&f))
70-
return f
75+
mut nom := u64(1000000000)
76+
for f % 10 == 0 {
77+
f = f / 10
78+
nom = nom / 10
79+
}
80+
res := WinTimeCoefficients{
81+
numer: nom
82+
denom: f
83+
}
84+
return res
7185
}
7286

7387
fn init_win_time_start() u64 {
@@ -80,7 +94,7 @@ fn init_win_time_start() u64 {
8094
pub fn sys_mono_now() u64 {
8195
tm := u64(0)
8296
C.QueryPerformanceCounter(voidptr(&tm)) // XP or later never fail
83-
return (tm - start_time) * 1000000000 / freq_time
97+
return (tm - start_time) * time_coefficients.numer / time_coefficients.denom
8498
}
8599

86100
// Note: vpc_now is used by `v -profile` .

0 commit comments

Comments
 (0)