chrono icon indicating copy to clipboard operation
chrono copied to clipboard

fix format panic problem

Open retrhelo opened this issue 4 years ago • 10 comments

Add some modification to format::inner_format(), which will prevent the program from panic when an inproper format string is provided. This is the problem mentioned in issue #575 .

The new strategy I'm using is to skip those inproper format substrings. You can find some of the examples in the test I add. I think this strategy is better than directly panic, especially when handling user input strings. Skipping the wrong parts will also indicate an invalid format string, and giving the programmer an opportunity to fix the problem while running, instead of panic and terminating the program.

retrhelo avatar Oct 31 '21 10:10 retrhelo

This unfortunately causes errors to become silent.

A better solution would be to introduce a format_opt method that correctly returns a Result<DelayedFormat, FormatError>.

quodlibetor avatar Nov 01 '21 14:11 quodlibetor

If invalid, I would imagine this would simply produce "%{whatever}", not "whatever}"

That sounds reasonable. I'll work on it.

By the way, I think the idea to introduce a new method that returns Result<DelayedFormat, FormatError>, which is mentioned before, is also an attractive solution to this problem. I can also give a try on it.

retrhelo avatar Nov 02 '21 01:11 retrhelo

Maybe create another function that returns a Result?

Milo123459 avatar Nov 02 '21 07:11 Milo123459

Maybe create another function that returns a Result?

I roughly created a try_format function for this purpose. However, I find that there's many format functions for each structure like DateTime, Date, etc. Adding such a function will get a lot of files involved, since we're adding it to every structure that implements format function. I think create a new PR for this task is better choice.

retrhelo avatar Nov 19 '21 07:11 retrhelo

Any update on this PR?

hustcer avatar May 06 '22 11:05 hustcer

What's the path here? Is there some outer API here that's not propagating the error from the inner API, but panicking instead?

djc avatar May 06 '22 16:05 djc

Is there some outer API here that's not propagating the error from the inner API, but panicking instead?

Yes, it's the panic problem. The original format function panics when passed in an inproper format string, making it hard to "format" a user-input string that's possibly inproper.

retrhelo avatar May 07 '22 02:05 retrhelo

Yeah, I don't think this is an improvement. If we're going to stop panicking, we should explicitly signal an error some other way.

djc avatar Jun 09 '22 09:06 djc

Just to add another option here, and I recognize this isn't super user friendly or discoverable, (we can potentially fix that with a few helper functions or more docs) but the potentially invalid user input problem can be solved in the currently released chrono, using StrftimeItems::new() and the write! macro depending on the task.

If you want to just check whether the format string is valid or not, using StrftimeItems suffices, however if you want to format without panicking, using write! instead of to_string or format! allows catching this (playground link).

use chrono::{Utc, format::{Item, strftime::StrftimeItems}}; // 0.4.19
use std::fmt::Write;
const BAD_FMT_STR: &str = "%Y-%m-%";
const GOOD_FMT_STR: &str = "%Y-%m-%d";

fn main() {
    assert!(StrftimeItems::new(BAD_FMT_STR).any(|i| matches!(i, Item::Error)));
    assert!(StrftimeItems::new(GOOD_FMT_STR).all(|i| !matches!(i, Item::Error)));
    
    let mut out = String::new();
    assert!(write!(&mut out, "{}", Utc::now().date().naive_local().format(GOOD_FMT_STR)).is_ok());
    assert!(write!(&mut out, "{}", Utc::now().date().naive_local().format(BAD_FMT_STR)).is_err());
}

esheppa avatar Jul 03 '22 12:07 esheppa

I've added a draft PR which shows some options here: https://github.com/chronotope/chrono/pull/735

esheppa avatar Jul 24 '22 11:07 esheppa

@retrhelo Thank you for your work here! We are going in a different direction to fix this panic, see https://github.com/chronotope/chrono/issues/1127.

pitdicker avatar Jul 11 '23 16:07 pitdicker