chrono icon indicating copy to clipboard operation
chrono copied to clipboard

utc_tm_to_time isn't memory-safe on nacl/solaris/illumos targets because it uses `std::env::set_var`

Open briansmith opened this issue 3 years ago • 3 comments

As discussed in #499, std::env::set_var isn't memory-safe, and should not be used.

The code in question is https://github.com/chronotope/chrono/blob/3467172c31188006147585f6ed3727629d642fed/src/sys/unix.rs#L55-L75

I don't know of a good solution but we should have a separate issue to track specifically set_var being problematic, to clarify the discussion in #499, which is about reading the environment.

briansmith avatar Feb 11 '22 19:02 briansmith

    let current_tz = var_os("TZ"); 
    set_var("TZ", "UTC");

Also, even if var_os and set_var were memory-safe, this would still be racy because another thread could be reading or writing TZ concurrently. In particular, current_tz may no longer be the "right" timezome to restore TZ to later, if another thread (permanently) changed it to another value. Similarly, if another thread is calling a function that reads TZ (including ones that implicitly or explicitly calls tzset()) then that other thread will get wrong results during the time we've temporarily set TZ to "UTC".

In other words, it isn't enough to find a way to make set_var memory-safe(r) because there would still be races even if set_var/get_var were memory-safe.

briansmith avatar Feb 11 '22 19:02 briansmith

Yes, I noticed this when trying to understand what chrono does. Interestingly, there's nothing that says you have to use system-implemented localtime functions! Both the inputs and outputs are well-defined, so there's no problem with writing our own - in Rust, or exactly as I did, by just patching an existing implementation. Maybe it'll need some more tweaks to work on solaris but should be doable.

Kixunil avatar Feb 11 '22 20:02 Kixunil

this would still be racy because another thread could be reading or writing TZ concurrently. In particular, current_tz may no longer be the "right" timezome to restore TZ to later

In particular, calling these threads concurrently in different threads over and over again will likely result in TZ getting fixed to the value "UTC" regardless of what it was originally set to be, as eventually we'll have:

Thread A: current_tz = get_var("TZ"); // value X Thread A: set_var("TZ", "UTC"); Thread B: current_tz = get_var("TZ"); // "UTC" Thread A: set_var("TZ", current_tz); // correctly restored to X Thread B: set_var("TZ", "UTC"); Thread B: set_var("TZ", current_tz); // "UTC", but it should be X.

briansmith avatar Feb 12 '22 17:02 briansmith

This should be fixed by releases >= 0.4.20

Interestingly, there's nothing that says you have to use system-implemented localtime functions! Both the inputs and outputs are well-defined, so there's no problem with writing our own

We are now directly parsing the tzinfo files and calculating the offsets where relevant, and avoiding mktime on all cfg(unix) platforms

esheppa avatar Aug 21 '22 12:08 esheppa