Skip to content

Commit d0634c9

Browse files
committed
Fix infinite loop: Enum.take/2 with negative index on empty enum (#14747)
1 parent cc797de commit d0634c9

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
@@ -3611,9 +3611,14 @@ defmodule Enum do
36113611
end
36123612

36133613
def take(enumerable, amount) when is_integer(amount) and amount < 0 do
3614-
{count, fun} = slice_count_and_fun(enumerable, 1)
3615-
first = Kernel.max(amount + count, 0)
3616-
fun.(first, count - first, 1)
3614+
case slice_count_and_fun(enumerable, 1) do
3615+
{0, _fun} ->
3616+
[]
3617+
3618+
{count, fun} ->
3619+
first = Kernel.max(amount + count, 0)
3620+
fun.(first, count - first, 1)
3621+
end
36173622
end
36183623

36193624
@doc """
@@ -5118,6 +5123,9 @@ defimpl Enumerable, for: Range do
51185123
slice(Map.put(range, :step, step))
51195124
end
51205125

5121-
defp slice(_current, _step, 0), do: []
5122-
defp slice(current, step, remaining), do: [current | slice(current + step, step, remaining - 1)]
5126+
defp slice(current, _step, 1), do: [current]
5127+
5128+
defp slice(current, step, remaining) when remaining > 1 do
5129+
[current | slice(current + step, step, remaining - 1)]
5130+
end
51235131
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)