Skip to content

Commit f80b2b9

Browse files
committed
Discard long durations
1 parent 37a6b02 commit f80b2b9

3 files changed

Lines changed: 18 additions & 3 deletions

File tree

‎lib/elixir/lib/calendar/duration.ex‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,9 @@ defmodule Duration do
367367
368368
Only seconds may be specified with a decimal fraction, using either a comma or a full stop: `P1DT4,5S`.
369369
370+
Inputs longer than 192 bytes are rejected, which is enough to parse each unit as a maximum signed
371+
64-bit integer (although it also allows parsing a single unit with 190 digits).
372+
370373
## Examples
371374
372375
iex> Duration.from_iso8601("P1Y2M3DT4H5M6S")

‎lib/elixir/lib/calendar/iso.ex‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -706,15 +706,15 @@ defmodule Calendar.ISO do
706706
"""
707707
@doc since: "1.17.0"
708708
@spec parse_duration(String.t()) :: {:ok, [Duration.unit_pair()]} | {:error, atom}
709-
def parse_duration("P" <> string) when byte_size(string) > 0 do
709+
def parse_duration("P" <> string) when byte_size(string) in 1..191 do
710710
parse_duration_date(string, 1, [], 0)
711711
end
712712

713-
def parse_duration("+P" <> string) when byte_size(string) > 0 do
713+
def parse_duration("+P" <> string) when byte_size(string) in 1..190 do
714714
parse_duration_date(string, 1, [], 0)
715715
end
716716

717-
def parse_duration("-P" <> string) when byte_size(string) > 0 do
717+
def parse_duration("-P" <> string) when byte_size(string) in 1..190 do
718718
parse_duration_date(string, -1, [], 0)
719719
end
720720

‎lib/elixir/test/elixir/calendar/duration_test.exs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,18 @@ defmodule DurationTest do
246246
assert Duration.from_iso8601("PT.6S") == {:error, :invalid_time_component}
247247
assert Duration.from_iso8601("PT0.5H") == {:error, :invalid_time_component}
248248
assert Duration.from_iso8601("invalid") == {:error, :invalid_duration}
249+
250+
# Inputs are capped at 192 bytes
251+
digits = String.duplicate("9", 189)
252+
assert {:ok, %Duration{}} = Duration.from_iso8601("P9#{digits}D")
253+
assert {:ok, %Duration{}} = Duration.from_iso8601("-P#{digits}D")
254+
assert {:ok, %Duration{}} = Duration.from_iso8601("+P#{digits}D")
255+
assert Duration.from_iso8601("P99#{digits}D") == {:error, :invalid_duration}
256+
assert Duration.from_iso8601("-P9#{digits}D") == {:error, :invalid_duration}
257+
assert Duration.from_iso8601("+P9#{digits}D") == {:error, :invalid_duration}
258+
259+
assert Duration.from_iso8601("P#{String.duplicate("9", 4_000_000)}D") ==
260+
{:error, :invalid_duration}
249261
end
250262

251263
test "from_iso8601!/1" do

0 commit comments

Comments
 (0)