Merge pull request #24349 from Homebrew/elf-utf8-relocation-paths

Preserve UTF-8 paths in ELF loader strings
This commit is contained in:
Mike McQuaid authored and GitHub committed 2026-10-24 16:31:14 +00:00
commit e92663d173
3 files changed
+39 -3

No files matched your search

+3 -2
View File
@@ -743,9 +743,10 @@ class Keg
end
strings.filter_map do |offset, match|
next unless match.ascii_only?
match.force_encoding(Encoding::UTF_8)
next unless match.valid_encoding?
[offset.to_s(16), match.force_encoding(Encoding::UTF_8)]
[offset.to_s(16), match]
end
ensure
stream.close
+9 -1
View File
@@ -111,6 +111,14 @@ RSpec.describe Homebrew::DevCmd::Bottle do
(formula.libexec/"raw-prefix").binwrite(
"\0#{Array.new(Homebrew::DevCmd::Bottle::MAXIMUM_STRING_MATCHES + 1, formula.libexec.to_s).join("\0")}\0",
)
require "patchelf"
library = formula.libexec/"José/libhello.so.0"
library.dirname.mkpath
FileUtils.cp TEST_FIXTURE_DIR/"elf/libhello.so.0", library
FileUtils.cp TEST_FIXTURE_DIR/"elf/hello", formula.libexec/"elf-prefix"
patcher = PatchELF::Patcher.new((formula.libexec/"elf-prefix").to_s, on_error: :silent)
patcher.add_needed(library.to_s.b)
patcher.save
stderr = if !Sandbox.available?
"Warning: Sandbox unavailable: processing downloaded files without sandboxing!\n"
elsif Sandbox.nested_sandbox?
@@ -140,7 +148,7 @@ RSpec.describe Homebrew::DevCmd::Bottle do
expect(tag.fetch("tab")).to include(
"changed_files" => be_an(Array),
"linkage_files" => be_an(Array),
"binary_relocation_files" => include("libexec/raw-prefix"),
"binary_relocation_files" => include("libexec/raw-prefix", "libexec/elf-prefix"),
"built_prefix" => HOMEBREW_PREFIX.to_s,
)
binary_relocation_diagnostics = tag.fetch("binary_relocation_diagnostics")
@@ -34,6 +34,24 @@ RSpec.describe Keg do
expect(described_class.text_matches_in_file(file, dir.to_s, [], [], nil).size).to eq 1
end
it "keeps referenced paths containing non-ASCII characters" do
rpath = dir/"José"
rpath.mkpath
patch_rpath rpath.to_s
expect(described_class.text_matches_in_file(file, dir.to_s, [], [], nil).map(&:first)).to eq [rpath.to_s]
end
it "drops referenced paths containing invalid UTF-8" do
rpath = "#{dir}/invalid-\xFF".b
patch_rpath rpath
candidates = []
described_class.each_candidate_string(file, dir.to_s) { |candidate| candidates << candidate.last.b }
expect(candidates).not_to include(rpath)
end
it "drops dead loader strings nothing references any more" do
# Shrinking the RPATH leaves an in-place `X` run inside `.dynstr`;
# writing a prefix string over it recreates the dead bytes a moved or
@@ -96,6 +114,15 @@ RSpec.describe Keg do
expect(described_class.text_matches_in_file(file, dir.to_s, [], [], nil).size).to eq 1
end
it "keeps an interpreter containing non-ASCII characters" do
interpreter = dir/"ld-José.so"
FileUtils.touch interpreter
patch_rpath "#{Keg::PREFIX_PLACEHOLDER}/lib"
patch_interpreter interpreter.to_s.b
expect(described_class.text_matches_in_file(file, dir.to_s, [], [], nil).map(&:first)).to eq [interpreter.to_s]
end
it "drops old interpreter bytes the loader no longer uses" do
patch_rpath "#{Keg::PREFIX_PLACEHOLDER}/lib"
# Growing the interpreter moves it; shrinking it back leaves an