chrono icon indicating copy to clipboard operation
chrono copied to clipboard

SystemTimeToTzSpecificLocalTime failed with: The parameter is incorrect. (os error 87)

Open andrewbanchich opened this issue 3 years ago • 6 comments

We're getting a panic from chrono here when run on a Windows 2012 server:

thread '<unnamed>' panicked at 'SystemTimeToTzSpecificLocalTime failed with: The parameter is incorrect. (os error 87)',
/cargo/registry/src/github.com-1ecc6299db9ec823/chrono-0.4.19/src/sys/windows.rs:97:9
stack backtrace:
   0: rust_begin_unwind
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b\/library\std\src/panicking.rs:498:5
   1: core::panicking::panic_fmt
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b\/library\core\src/panicking.rs:107:14
   2: chrono::sys::inner::time_to_local_tm
   3: <chrono::offset::local::Local as chrono::offset::TimeZone>::from_utc_datetime
   4: <chrono::datetime::DateTime<chrono::offset::local::Local> as core::convert::From<std::time::SystemTime>>::from
...

We debugged the SystemTime we were getting and it was:

SystemTime {
    intervals: 147221225472,
}

A normal intervals value (e.g. 132790361186042732) is much larger.

I'm assuming there's something about this unusually short SystemTime that's causing chrono to panic.

andrewbanchich avatar Feb 17 '22 23:02 andrewbanchich

use std::{io, mem};
use winapi::{shared::minwindef::*, um::timezoneapi::*};

fn main() {
    // works - 132790361186042732
    // fails - 147221225472

    let t = 147221225472 as u64;

    let ft = FILETIME {
        dwLowDateTime: t as DWORD,
        dwHighDateTime: (t >> 32) as DWORD,
    };

    unsafe {
        let mut utc = mem::zeroed();
        let mut local = mem::zeroed();

        FileTimeToSystemTime(&ft, &mut utc);

        dbg!(&utc.wYear); // 1601
        dbg!(&utc.wMonth); // 1
        dbg!(&utc.wDayOfWeek); // 1 (Monday)
        dbg!(&utc.wDay); // 1
        dbg!(&utc.wHour);
        dbg!(&utc.wMinute);
        dbg!(&utc.wSecond);
        dbg!(&utc.wMilliseconds);

        SystemTimeToTzSpecificLocalTime(0 as *const _, &mut utc, &mut local); // returns 0 (failure)
        dbg!(io::Error::last_os_error()); // InvalidInput
    }
}

Those debug statements tell you that the SystemTime is January 1, 1601. And while that seems totally ridiculous, it should be a valid date according to Microsoft documentation. Despite this, passing that value to SystemTimeToTzSpecificLocalTime triggers an InvalidInput error:

[src\main.rs:31] io::Error::last_os_error() = Os {
    code: 87,
    kind: InvalidInput,
    message: "The parameter is incorrect.",       
}

annmarie-switzer avatar Feb 18 '22 14:02 annmarie-switzer

This seems to be an issue with something lower level having to do with Windows, so I'm going to close this.

We opened an issue in the official windows crate repo.

andrewbanchich avatar Feb 18 '22 16:02 andrewbanchich

Actually, I'm reopening this since based on the feedback from that issue it looks like the problem might be more in chrono's domain.

andrewbanchich avatar Feb 18 '22 17:02 andrewbanchich

I'm unable to test on Windows myself. I'd be happy to review any code changes that are supported with documentation and/or explanation why they improve the current situation, but I probably won't be able to work on this proactively.

Let me know if you need any guidance on how to fix chrono to support this scenario better.

djc avatar Mar 23 '22 04:03 djc

@annmarie-switzer should have the fix for this. Unfortunately, I don't have the code and also am unable to test on Windows.

andrewbanchich avatar Apr 02 '22 19:04 andrewbanchich

Just adding some additional info:

We (Nushell) recently got a bug report where this panic was occurring when the user ran ls ~/Downloads (which uses chrono for file modified times).

The culprit ended up being a file named NUL (which should not exist, cannot be created manually, and was probably created by some buggy third-party software; NUL is a reserved name). To fix the issue the user just deleted the file.

rgwood avatar Jul 25 '22 05:07 rgwood

While https://github.com/chronotope/chrono/issues/1150 is a duplicate of this issue, it becomes a bit more specific on what to fix. Closing this issue as a duplicate.

pitdicker avatar Jul 05 '23 05:07 pitdicker