elf: expand $ORIGIN in RUNPATH/RPATH entries
This commit is contained in:
parent
4bc1cc57f3
commit
6ee34832d1
@ -153,6 +153,7 @@ module ELFShim
|
||||
|
||||
# Search for dependencies in the runpath/rpath first
|
||||
local_paths&.each do |local_path|
|
||||
local_path = OS::Linux::Elf.expand_elf_dst(local_path, "ORIGIN", path.parent)
|
||||
candidate = Pathname(local_path)/basename
|
||||
return candidate if candidate.exist? && candidate.elf?
|
||||
end
|
||||
@ -225,3 +226,37 @@ module ELFShim
|
||||
metadata.dylibs
|
||||
end
|
||||
end
|
||||
|
||||
module OS
|
||||
module Linux
|
||||
# Helper functions for working with ELF objects.
|
||||
#
|
||||
# @api private
|
||||
module Elf
|
||||
sig { params(str: String, ref: String, repl: T.any(String, Pathname)).returns(String) }
|
||||
def self.expand_elf_dst(str, ref, repl)
|
||||
# ELF gABI rules for DSTs:
|
||||
# - Longest possible sequence using the rules (greedy).
|
||||
# - Must start with a $ (enforced by caller).
|
||||
# - Must follow $ with one underscore or ASCII [A-Za-z] (caller
|
||||
# follows these rules for REF) or '{' (start curly quoted name).
|
||||
# - Must follow first two characters with zero or more [A-Za-z0-9_]
|
||||
# (enforced by caller) or '}' (end curly quoted name).
|
||||
# (from https://github.com/bminor/glibc/blob/41903cb6f460d62ba6dd2f4883116e2a624ee6f8/elf/dl-load.c#L182-L228)
|
||||
|
||||
# In addition to capturing a token, also attempt to capture opening/closing braces and check that they are not
|
||||
# mismatched before expanding.
|
||||
str.gsub(/\$({?)([a-zA-Z_][a-zA-Z0-9_]*)(}?)/) do |orig_str|
|
||||
has_opening_brace = ::Regexp.last_match(1).present?
|
||||
matched_text = ::Regexp.last_match(2)
|
||||
has_closing_brace = ::Regexp.last_match(3).present?
|
||||
if (matched_text == ref) && (has_opening_brace == has_closing_brace)
|
||||
repl
|
||||
else
|
||||
orig_str
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
87
Library/Homebrew/test/os/linux/elf_spec.rb
Normal file
87
Library/Homebrew/test/os/linux/elf_spec.rb
Normal file
@ -0,0 +1,87 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe OS::Linux::Elf do
|
||||
describe "::expand_elf_dst" do
|
||||
it "expands tokens that are not wrapped in curly braces" do
|
||||
str = "$ORIGIN/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "/opt/homebrew/bin/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
end
|
||||
|
||||
it "expands tokens that are wrapped in curly braces" do
|
||||
str = "${ORIGIN}/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "/opt/homebrew/bin/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
|
||||
str = "${ORIGIN}new/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "/opt/homebrew/binnew/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
end
|
||||
|
||||
it "expands multiple occurrences of token" do
|
||||
str = "${ORIGIN}/../..$ORIGIN/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "/opt/homebrew/bin/../../opt/homebrew/bin/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
end
|
||||
|
||||
it "rejects and passes through tokens containing additional characters" do
|
||||
str = "$ORIGINAL/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "$ORIGINAL/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
|
||||
str = "$ORIGIN_/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "$ORIGIN_/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
|
||||
str = "$ORIGIN_STORY/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "$ORIGIN_STORY/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
|
||||
str = "${ORIGINAL}/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "${ORIGINAL}/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
|
||||
str = "${ORIGIN_}/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "${ORIGIN_}/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
|
||||
str = "${ORIGIN_STORY}/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "${ORIGIN_STORY}/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
end
|
||||
|
||||
it "rejects and passes through tokens with mismatched curly braces" do
|
||||
str = "${ORIGIN/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "${ORIGIN/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
|
||||
str = "$ORIGIN}/../lib"
|
||||
ref = "ORIGIN"
|
||||
repl = "/opt/homebrew/bin"
|
||||
expected = "$ORIGIN}/../lib"
|
||||
expect(described_class.expand_elf_dst(str, ref, repl)).to eq(expected)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user