dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.07k stars 1.56k forks source link

DateTime parse function is too generic #56476

Closed vasilich6107 closed 3 weeks ago

vasilich6107 commented 3 weeks ago

Hi.

I noticed that DateTime.parse function could literally parse anything into date time object. For example a random number of digits transforms to date time object telegram-cloud-photo-size-2-5321049968611546939-y

Consider adding parseIso and tryParseIso or any other naming which will be more strict to the input and oriented only on industry standard date time format(ISO 8601) without being tolerant to overflow

dart-github-bot commented 3 weeks ago

Summary: The DateTime.parse function is overly permissive, allowing invalid inputs like random numbers to be parsed into date-time objects. The user suggests adding a more strict parseIso or tryParseIso function that only accepts ISO 8601 formatted dates.

lrhn commented 3 weeks ago

The format that is accepted for year/month/date is Y-M-D where Y must have 4-6 digits and may have a prefix + or -, M and D must both have two digits and the -s can be omitted. The last part is what makes "any sequence of digits" be parsed as a Date. This is documented on DateTime.parse.

Those can then be followed by T or space and a time of the form H[:m[:S[.s]]][Z] where H, m and S must be two digits if they occur, and the :s can be omitted, and s can be 1-6 digits (fractional seconds to the milli-/microseconds), where the . cannot be omitted. Z can be z or ±H[:M]. All in all, it is fairly permissive. It accepts ISO8601 dates, partial Dates (no time, or time only to a second, minute or hour precision), but it also allows omitting -s and :s, basing the parsing on position. (Which is why the M/D/H/m/S must always be two digits.)

It is a problem that the parser is forgiving of overflow, so something like 1970-20-99 is accepted, and therefore so is 19702099, or any random string of 8-10 digits, with a leading + or -. The parser probably shouldn't be as permissive, and should reject the 20 month and 99 day. (There is an issue for that somewhere. It's obviously breaking to change, so it hasn't been a high priority. We defer to DateFormat.parseStrict instead, if you want more functionality.) Also, the VM fails to detect some overflows. The six-digit year is actually capped at ±100,000,000 days from 1970-01-01, so -271821-04-20 through +275760-09-13. The VM allows larger year numbers to overflow the underlying 64-bit value which is holding microseconds since epoch. (That would be easier to avoid if the month/day values couldn't overflow.)

In any case:

vasilich6107 commented 3 weeks ago

thanks will try parseStrict