Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
915d6dca16 | ||
|
|
a983c8c043 |
@@ -234,6 +234,12 @@ These additions offer greater transparency into the components and licenses of e
|
||||
|
||||
This work was performed by [Jonatan Männchen](https://maennchen.dev) and sponsored by the [Erlang Ecosystem Foundation](https://erlef.org).
|
||||
|
||||
## v1.19.6 (2026-08-28)
|
||||
|
||||
### 1. Security
|
||||
|
||||
* [List] Avoid recursion when invalid charlists are given to `List.to_string/1` or `List.to_charlist/1` (CVE-2026-75758, GHSA-jf5q-v438-665c)
|
||||
|
||||
## v1.19.5 (2026-01-09)
|
||||
|
||||
### 1. Enhancements
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
ELIXIR_VERSION=1.19.5
|
||||
ELIXIR_VERSION=1.19.6
|
||||
|
||||
if [ $# -eq 0 ] || { [ $# -eq 1 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; }; }; then
|
||||
cat <<USAGE >&2
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
:: SPDX-FileCopyrightText: 2021 The Elixir Team
|
||||
:: SPDX-FileCopyrightText: 2012 Plataformatec
|
||||
|
||||
set ELIXIR_VERSION=1.19.5
|
||||
set ELIXIR_VERSION=1.19.6
|
||||
|
||||
if ""%1""=="""" if ""%2""=="""" goto documentation
|
||||
if /I ""%1""==""--help"" if ""%2""=="""" goto documentation
|
||||
|
||||
@@ -389,13 +389,20 @@ defimpl Inspect, for: List do
|
||||
close = color_doc("]", :list, opts)
|
||||
|
||||
cond do
|
||||
lists == :as_charlists or (lists == :infer and List.ascii_printable?(term, printable_limit)) ->
|
||||
inspected =
|
||||
case Identifier.escape(IO.chardata_to_string(term), ?", printable_limit) do
|
||||
{escaped, ""} -> [?~, ?c, ?", escaped, ?"]
|
||||
{escaped, _} -> [?~, ?c, ?", escaped, ?", " ++ ..."]
|
||||
(lists == :as_charlists and unicode_list?(term, printable_limit)) or
|
||||
(lists == :infer and List.ascii_printable?(term, printable_limit)) ->
|
||||
{split, tail} =
|
||||
if is_integer(printable_limit) do
|
||||
case Enum.split(term, printable_limit) do
|
||||
{split, []} -> {split, []}
|
||||
{split, _} -> {split, " ++ ..."}
|
||||
end
|
||||
else
|
||||
{term, []}
|
||||
end
|
||||
|
||||
{escaped, _} = Identifier.escape(IO.chardata_to_string(split), ?")
|
||||
inspected = [?~, ?c, ?", escaped, ?" | tail]
|
||||
color_doc(IO.iodata_to_binary(inspected), :charlist, opts)
|
||||
|
||||
keyword?(term) ->
|
||||
@@ -409,6 +416,19 @@ defimpl Inspect, for: List do
|
||||
end
|
||||
end
|
||||
|
||||
defp unicode_list?(_, 0), do: true
|
||||
|
||||
defp unicode_list?([char | rest], counter)
|
||||
when char in 0..0xD7FF or char in 0xE000..0x10FFFF,
|
||||
do: unicode_list?(rest, decrement(counter))
|
||||
|
||||
defp unicode_list?([], _counter), do: true
|
||||
defp unicode_list?(_, _counter), do: false
|
||||
|
||||
@compile {:inline, decrement: 1}
|
||||
defp decrement(:infinity), do: :infinity
|
||||
defp decrement(counter), do: counter - 1
|
||||
|
||||
@doc false
|
||||
def keyword({key, value}, opts) do
|
||||
key = color_doc(Macro.inspect_atom(:key, key), :atom, opts)
|
||||
|
||||
@@ -21,8 +21,8 @@ defmodule Inspect.Opts do
|
||||
is `:decimal` and if it is printable, otherwise in bit syntax. See
|
||||
`String.printable?/1` to learn when a string is printable.
|
||||
|
||||
* `:charlists` - when `:as_charlists` all lists will be printed as charlists,
|
||||
non-printable elements will be escaped.
|
||||
* `:charlists` - when `:as_charlists` all charlists will be printed as charlists,
|
||||
non-printable code points will be escaped. Other lists will be printed as lists.
|
||||
|
||||
When `:as_lists` all lists will be printed as lists.
|
||||
|
||||
|
||||
@@ -1137,7 +1137,7 @@ defmodule List do
|
||||
|
||||
Please check the given list or call inspect/1 to get the list representation, got:
|
||||
|
||||
#{inspect(list)}
|
||||
#{inspect(list, charlists: :as_lists)}
|
||||
"""
|
||||
else
|
||||
result when is_binary(result) ->
|
||||
@@ -1189,7 +1189,7 @@ defmodule List do
|
||||
|
||||
Please check the given list or call inspect/1 to get the list representation, got:
|
||||
|
||||
#{inspect(list)}
|
||||
#{inspect(list, charlists: :as_lists)}
|
||||
"""
|
||||
else
|
||||
result when is_list(result) ->
|
||||
|
||||
@@ -282,10 +282,15 @@ defmodule Inspect.ListTest do
|
||||
|
||||
test "printable limit" do
|
||||
assert inspect(~c"hello world", printable_limit: 4) == ~s(~c"hell" ++ ...)
|
||||
assert inspect(~c"hello", printable_limit: :infinity) == ~s(~c"hello")
|
||||
# Non printable characters after the limit don't matter
|
||||
assert inspect(~c"hello world" ++ [0], printable_limit: 4) == ~s(~c"hell" ++ ...)
|
||||
# Non printable strings aren't affected by printable limit
|
||||
assert inspect([0, 1, 2, 3, 4], printable_limit: 3) == ~s([0, 1, 2, 3, 4])
|
||||
# Ensure a non-printable value after limit does not crash
|
||||
assert inspect(~c"hello world" ++ [nil], printable_limit: 4) == ~s(~c"hell" ++ ...)
|
||||
# Ensure a non-printable value after default limit does not hang
|
||||
assert String.ends_with?(inspect(List.duplicate(?a, 5000) ++ [nil]), "\" ++ ...")
|
||||
end
|
||||
|
||||
test "keyword" do
|
||||
@@ -310,10 +315,20 @@ defmodule Inspect.ListTest do
|
||||
assert inspect([0], charlists: :infer) == "[0]"
|
||||
end
|
||||
|
||||
test "opt as strings" do
|
||||
test "opt as charlists" do
|
||||
assert inspect(~c"john" ++ [0] ++ ~c"doe", charlists: :as_charlists) == ~s(~c"john\\0doe")
|
||||
assert inspect(~c"john", charlists: :as_charlists) == ~s(~c"john")
|
||||
assert inspect([0], charlists: :as_charlists) == ~s(~c"\\0")
|
||||
assert inspect([nil], charlists: :as_charlists) == "[nil]"
|
||||
assert inspect([0xD800], charlists: :as_charlists) == "[55296]"
|
||||
assert inspect([1_114_112], charlists: :as_charlists) == "[1114112]"
|
||||
assert inspect([[?a]], charlists: :as_charlists) == ~s([~c"a"])
|
||||
|
||||
assert inspect([?a, ?b, ?c | nil], charlists: :as_charlists, printable_limit: 4) ==
|
||||
"[97, 98, 99 | nil]"
|
||||
|
||||
assert inspect([?a, ?b, ?c | nil], charlists: :as_charlists, printable_limit: 3) ==
|
||||
~s(~c"abc" ++ ...)
|
||||
end
|
||||
|
||||
test "opt as lists" do
|
||||
|
||||
@@ -331,6 +331,12 @@ defmodule ListTest do
|
||||
assert_raise ArgumentError, ~r"cannot convert the given list to a string", fn ->
|
||||
List.to_string([:a, :b])
|
||||
end
|
||||
|
||||
invalid = List.duplicate(?a, 4096) ++ [nil]
|
||||
|
||||
assert_raise ArgumentError, ~r/got:\n\n\[97, 97, .*\.\.\.\]\n\z/s, fn ->
|
||||
List.to_string(invalid)
|
||||
end
|
||||
end
|
||||
|
||||
test "to_charlist/1" do
|
||||
@@ -349,6 +355,12 @@ defmodule ListTest do
|
||||
assert_raise ArgumentError, ~r"cannot convert the given list to a charlist", fn ->
|
||||
List.to_charlist([:a, :b])
|
||||
end
|
||||
|
||||
invalid = List.duplicate(?a, 4096) ++ [nil]
|
||||
|
||||
assert_raise ArgumentError, ~r/got:\n\n\[97, 97, .*\.\.\.\]\n\z/s, fn ->
|
||||
List.to_charlist(invalid)
|
||||
end
|
||||
end
|
||||
|
||||
describe "myers_difference/2" do
|
||||
|
||||
Reference in New Issue
Block a user