Skip to content

Commit e5ace9b

Browse files
committed
Rely on term_to_binary/1 format to protect from incomplete file writes
1 parent 1a2c0a2 commit e5ace9b

File tree

3 files changed

+5
-56
lines changed

3 files changed

+5
-56
lines changed

lib/mix/lib/mix/compilers/elixir.ex

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,7 @@ defmodule Mix.Compilers.Elixir do
311311
"""
312312
def read_manifest(manifest) do
313313
try do
314-
{:ok, contents} = Mix.Task.Compiler.read_checksumed_file(manifest)
315-
:erlang.binary_to_term(contents)
314+
manifest |> File.read!() |> :erlang.binary_to_term()
316315
rescue
317316
_ -> {[], []}
318317
else
@@ -889,8 +888,7 @@ defmodule Mix.Compilers.Elixir do
889888
# Similar to read_manifest, but for internal consumption and with data migration support.
890889
defp parse_manifest(manifest, compile_path) do
891890
try do
892-
{:ok, contents} = Mix.Task.Compiler.read_checksumed_file(manifest)
893-
:erlang.binary_to_term(contents)
891+
manifest |> File.read!() |> :erlang.binary_to_term()
894892
rescue
895893
_ ->
896894
@default_manifest
@@ -960,7 +958,7 @@ defmodule Mix.Compilers.Elixir do
960958
project_mtime, config_mtime, protocols_and_impls}
961959

962960
manifest_data = :erlang.term_to_binary(term, [:compressed])
963-
:ok = Mix.Task.Compiler.write_checksumed_file(manifest, manifest_data)
961+
File.write!(manifest, manifest_data)
964962
File.touch!(manifest, timestamp)
965963
delete_checkpoints(manifest)
966964

lib/mix/lib/mix/task.compiler.ex

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -370,51 +370,4 @@ defmodule Mix.Task.Compiler do
370370
Mix.Task.reenable("compile.all")
371371
Enum.each(compilers, &Mix.Task.reenable("compile.#{&1}"))
372372
end
373-
374-
@checksum_version 1
375-
376-
@doc """
377-
Reads a checksumed file.
378-
379-
This function is useful to read files with checksums
380-
and validate they won't get corrupted with time.
381-
"""
382-
def read_checksumed_file(path) do
383-
case File.read(path) do
384-
{:ok, <<@checksum_version, size::64, checksum::binary-size(size), contents::binary>>} ->
385-
if checksum(contents) == checksum do
386-
{:ok, contents}
387-
else
388-
{:error, :echecksum}
389-
end
390-
391-
{:error, reason} ->
392-
{:error, reason}
393-
end
394-
end
395-
396-
@doc """
397-
Writes a checksumed file.
398-
399-
This function is useful to write compilation manifests
400-
and validate they won't get corrupted with time.
401-
"""
402-
def write_checksumed_file(path, contents) do
403-
checksum = checksum(contents)
404-
405-
File.write(
406-
path,
407-
<<@checksum_version, byte_size(checksum)::64, checksum::binary, contents::binary>>
408-
)
409-
end
410-
411-
defp checksum(contents) do
412-
case :erlang.system_info(:wordsize) do
413-
8 -> :crypto.hash(:blake2b, contents)
414-
_ -> :crypto.hash(:blake2s, contents)
415-
end
416-
rescue
417-
# Blake may not be available on all OpenSSL distribution
418-
_ -> :erlang.md5(contents)
419-
end
420373
end

lib/mix/test/mix/tasks/compile.elixir_test.exs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -653,13 +653,11 @@ defmodule Mix.Tasks.Compile.ElixirTest do
653653

654654
manifest = "_build/dev/lib/sample/.mix/compile.elixir"
655655

656-
{:ok, contents} = Mix.Task.Compiler.read_checksumed_file(manifest)
657-
658-
contents
656+
File.read!(manifest)
659657
|> :erlang.binary_to_term()
660658
|> put_elem(0, 9)
661659
|> :erlang.term_to_binary()
662-
|> then(&Mix.Task.Compiler.write_checksumed_file(manifest, &1))
660+
|> then(&File.write!(manifest, &1))
663661

664662
Mix.Task.clear()
665663
assert Mix.Task.run("compile", ["--verbose"]) == {:ok, []}

0 commit comments

Comments
 (0)