Skip to content

Commit a20acc4

Browse files
author
José Valim
committed
Check for null bytes and invalid environment vars on System
1 parent e520842 commit a20acc4

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

lib/elixir/lib/system.ex

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ defmodule System do
339339
"""
340340
@spec find_executable(binary) :: binary | nil
341341
def find_executable(program) when is_binary(program) do
342+
assert_no_null_byte!(program, "System.find_executable/1")
343+
342344
case :os.find_executable(String.to_charlist(program)) do
343345
false -> nil
344346
other -> List.to_string(other)
@@ -393,8 +395,13 @@ defmodule System do
393395
"""
394396
@spec put_env(binary, binary) :: :ok
395397
def put_env(varname, value) when is_binary(varname) and is_binary(value) do
396-
:os.putenv String.to_charlist(varname), String.to_charlist(value)
397-
:ok
398+
case :binary.match(varname, "=") do
399+
{_, _} ->
400+
raise ArgumentError, "cannot execute System.put_env/2 for key with \"=\", got: #{inspect varname}"
401+
:nomatch ->
402+
:os.putenv String.to_charlist(varname), String.to_charlist(value)
403+
:ok
404+
end
398405
end
399406

400407
@doc """
@@ -588,6 +595,7 @@ defmodule System do
588595
@spec cmd(binary, [binary], keyword) ::
589596
{Collectable.t, exit_status :: non_neg_integer}
590597
def cmd(command, args, opts \\ []) when is_binary(command) and is_list(args) do
598+
assert_no_null_byte!(command, "System.cmd/3")
591599
cmd = String.to_charlist(command)
592600

593601
cmd =
@@ -833,6 +841,15 @@ defmodule System do
833841
:erlang.unique_integer(modifiers)
834842
end
835843

844+
defp assert_no_null_byte!(binary, operation) do
845+
case :binary.match(binary, "\0") do
846+
{_, _} ->
847+
raise ArgumentError, "cannot execute #{operation} for program with null byte, got: #{inspect binary}"
848+
:nomatch ->
849+
binary
850+
end
851+
end
852+
836853
defp normalize_time_unit(:native),
837854
do: :native
838855

lib/elixir/test/elixir/system_test.exs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ defmodule SystemTest do
7373

7474
System.put_env(%{@test_var => "OTHER_SAMPLE"})
7575
assert System.get_env(@test_var) == "OTHER_SAMPLE"
76+
77+
assert_raise ArgumentError, ~r[cannot execute System.put_env/2 for key with \"=\"], fn ->
78+
System.put_env("FOO=BAR", "BAZ")
79+
end
80+
end
81+
82+
test "cmd/2 raises for null bytes" do
83+
assert_raise ArgumentError, ~r"cannot execute System.cmd/3 for program with null byte", fn ->
84+
System.cmd("null\0byte", [])
85+
end
7686
end
7787

7888
if windows?() do
@@ -107,19 +117,19 @@ defmodule SystemTest do
107117
File.rm_rf! Path.dirname(tmp_path(@echo))
108118
end
109119
else
110-
test "cmd/2 Unix" do
120+
test "cmd/2 unix" do
111121
assert {"hello\n", 0} = System.cmd "echo", ["hello"]
112122
end
113123

114-
test "cmd/3 (with options) Unix" do
124+
test "cmd/3 (with options) unix" do
115125
assert {["hello\n"], 0} = System.cmd "echo", ["hello"],
116126
into: [], cd: System.cwd!, env: %{"foo" => "bar", "baz" => nil},
117127
arg0: "echo", stderr_to_stdout: true, parallelism: true
118128
end
119129

120130
@echo "echo-elixir-test"
121131

122-
test "cmd/2 with absolute and relative paths Unix" do
132+
test "cmd/2 with absolute and relative paths ynix" do
123133
echo = tmp_path(@echo)
124134
File.mkdir_p! Path.dirname(echo)
125135
File.cp! System.find_executable("echo"), echo
@@ -143,6 +153,9 @@ defmodule SystemTest do
143153
assert System.find_executable("erl")
144154
assert is_binary System.find_executable("erl")
145155
assert !System.find_executable("does-not-really-exist-from-elixir")
156+
assert_raise ArgumentError, ~r"cannot execute System.find_executable/1 for program with null byte", fn ->
157+
System.find_executable("null\0byte")
158+
end
146159
end
147160

148161
test "monotonic_time/0" do

0 commit comments

Comments
 (0)