Skip to content

Commit 4008142

Browse files
authored
Fix infinite loop: Enum.take/2 with negative index on empty enum (#14747)
1 parent 56333d4 commit 4008142

File tree

3 files changed

+18
-6
lines changed

3 files changed

+18
-6
lines changed

lib/elixir/lib/calendar/date_range.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ defmodule Date.Range do
9595
[date_from_iso_days(current, calendar)]
9696
end
9797

98-
defp slice(current, step, remaining, calendar) do
98+
defp slice(current, step, remaining, calendar) when remaining > 1 do
9999
[
100100
date_from_iso_days(current, calendar)
101101
| slice(current + step, step, remaining - 1, calendar)

lib/elixir/lib/enum.ex

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3674,9 +3674,14 @@ defmodule Enum do
36743674
end
36753675

36763676
def take(enumerable, amount) when is_integer(amount) and amount < 0 do
3677-
{count, fun} = slice_count_and_fun(enumerable, 1)
3678-
first = Kernel.max(amount + count, 0)
3679-
fun.(first, count - first, 1)
3677+
case slice_count_and_fun(enumerable, 1) do
3678+
{0, _fun} ->
3679+
[]
3680+
3681+
{count, fun} ->
3682+
first = Kernel.max(amount + count, 0)
3683+
fun.(first, count - first, 1)
3684+
end
36803685
end
36813686

36823687
@doc """
@@ -5181,6 +5186,9 @@ defimpl Enumerable, for: Range do
51815186
slice(Map.put(range, :step, step))
51825187
end
51835188

5184-
defp slice(_current, _step, 0), do: []
5185-
defp slice(current, step, remaining), do: [current | slice(current + step, step, remaining - 1)]
5189+
defp slice(current, _step, 1), do: [current]
5190+
5191+
defp slice(current, step, remaining) when remaining > 1 do
5192+
[current | slice(current + step, step, remaining - 1)]
5193+
end
51865194
end

lib/elixir/test/elixir/calendar/date_range_test.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ defmodule Date.RangeTest do
101101
end
102102
end
103103

104+
test "Enum.take/1 for empty range with negative step" do
105+
assert Enum.take(@empty_range, -1) == []
106+
end
107+
104108
test "works with date-like structs" do
105109
range = Date.range(~N[2000-01-01 09:00:00], ~U[2000-01-02 09:00:00Z])
106110
assert range.first == ~D[2000-01-01]

0 commit comments

Comments
 (0)