Add consistent path validation
This commit is contained in:
parent
894c335e32
commit
5aebde3ffd
@ -365,9 +365,9 @@ module Homebrew
|
||||
end || 0
|
||||
end
|
||||
|
||||
filename = Bottle::Filename.create(formula, bottle_tag.to_sym, rebuild)
|
||||
filename = Bottle::Filename.create(formula, bottle_tag, rebuild)
|
||||
local_filename = filename.to_s
|
||||
bottle_path = Pathname.pwd/filename
|
||||
bottle_path = Pathname.pwd/local_filename
|
||||
|
||||
tab = nil
|
||||
keg = nil
|
||||
@ -690,8 +690,8 @@ module Homebrew
|
||||
bottle_hash["bottle"]["tags"].each do |tag, tag_hash|
|
||||
filename = Bottle::Filename.new(
|
||||
formula_name,
|
||||
bottle_hash["formula"]["pkg_version"],
|
||||
tag,
|
||||
PkgVersion.parse(bottle_hash["formula"]["pkg_version"]),
|
||||
Utils::Bottles::Tag.from_symbol(tag.to_sym),
|
||||
bottle_hash["bottle"]["rebuild"],
|
||||
)
|
||||
|
||||
@ -700,8 +700,8 @@ module Homebrew
|
||||
|
||||
all_filename = Bottle::Filename.new(
|
||||
formula_name,
|
||||
bottle_hash["formula"]["pkg_version"],
|
||||
"all",
|
||||
PkgVersion.parse(bottle_hash["formula"]["pkg_version"]),
|
||||
Utils::Bottles::Tag.from_symbol(:all),
|
||||
bottle_hash["bottle"]["rebuild"],
|
||||
)
|
||||
|
||||
|
@ -197,7 +197,7 @@ class VCSDownloadStrategy < AbstractDownloadStrategy
|
||||
super
|
||||
@ref_type, @ref = extract_ref(meta)
|
||||
@revision = meta[:revision]
|
||||
@cached_location = @cache/"#{name}--#{cache_tag}"
|
||||
@cached_location = @cache/Utils.safe_filename("#{name}--#{cache_tag}")
|
||||
end
|
||||
|
||||
# Download and cache the repository at {#cached_location}.
|
||||
@ -296,7 +296,7 @@ class AbstractFileDownloadStrategy < AbstractDownloadStrategy
|
||||
return @symlink_location if defined?(@symlink_location)
|
||||
|
||||
ext = Pathname(parse_basename(url)).extname
|
||||
@symlink_location = @cache/"#{name}--#{version}#{ext}"
|
||||
@symlink_location = @cache/Utils.safe_filename("#{name}--#{version}#{ext}")
|
||||
end
|
||||
|
||||
# Path for storing the completed download.
|
||||
@ -312,7 +312,7 @@ class AbstractFileDownloadStrategy < AbstractDownloadStrategy
|
||||
@cached_location = if downloads.count == 1
|
||||
downloads.first
|
||||
else
|
||||
HOMEBREW_CACHE/"downloads/#{url_sha256}--#{resolved_basename}"
|
||||
HOMEBREW_CACHE/"downloads/#{url_sha256}--#{Utils.safe_filename(resolved_basename)}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -307,13 +307,15 @@ class Formula
|
||||
end
|
||||
|
||||
def validate_attributes!
|
||||
raise FormulaValidationError.new(full_name, :name, name) if name.blank? || name.match?(/\s/)
|
||||
if name.blank? || name.match?(/\s/) || !Utils.safe_filename?(name)
|
||||
raise FormulaValidationError.new(full_name, :name, name)
|
||||
end
|
||||
|
||||
url = active_spec.url
|
||||
raise FormulaValidationError.new(full_name, :url, url) if url.blank? || url.match?(/\s/)
|
||||
|
||||
val = version.respond_to?(:to_str) ? version.to_str : version
|
||||
return if val.present? && !val.match?(/\s/)
|
||||
return if val.present? && !val.match?(/\s/) && Utils.safe_filename?(val)
|
||||
|
||||
raise FormulaValidationError.new(full_name, :version, val)
|
||||
end
|
||||
|
@ -294,12 +294,18 @@ class Bottle
|
||||
class Filename
|
||||
attr_reader :name, :version, :tag, :rebuild
|
||||
|
||||
sig { params(formula: Formula, tag: Utils::Bottles::Tag, rebuild: Integer).returns(T.attached_class) }
|
||||
def self.create(formula, tag, rebuild)
|
||||
new(formula.name, formula.pkg_version, tag, rebuild)
|
||||
end
|
||||
|
||||
sig { params(name: String, version: PkgVersion, tag: Utils::Bottles::Tag, rebuild: Integer).void }
|
||||
def initialize(name, version, tag, rebuild)
|
||||
@name = File.basename name
|
||||
|
||||
raise ArgumentError, "Invalid bottle name" unless Utils.safe_filename?(@name)
|
||||
raise ArgumentError, "Invalid bottle version" unless Utils.safe_filename?(version.to_s)
|
||||
|
||||
@version = version
|
||||
@tag = tag.to_s
|
||||
@rebuild = rebuild
|
||||
|
@ -7,47 +7,47 @@ describe Bottle::Filename do
|
||||
subject { described_class.new(name, version, tag, rebuild) }
|
||||
|
||||
let(:name) { "user/repo/foo" }
|
||||
let(:version) { "1.0" }
|
||||
let(:tag) { :tag }
|
||||
let(:version) { PkgVersion.new(Version.new("1.0"), 0) }
|
||||
let(:tag) { Utils::Bottles::Tag.from_symbol(:x86_64_linux) }
|
||||
let(:rebuild) { 0 }
|
||||
|
||||
describe "#extname" do
|
||||
its(:extname) { is_expected.to eq ".tag.bottle.tar.gz" }
|
||||
its(:extname) { is_expected.to eq ".x86_64_linux.bottle.tar.gz" }
|
||||
|
||||
context "when rebuild is 0" do
|
||||
its(:extname) { is_expected.to eq ".tag.bottle.tar.gz" }
|
||||
its(:extname) { is_expected.to eq ".x86_64_linux.bottle.tar.gz" }
|
||||
end
|
||||
|
||||
context "when rebuild is 1" do
|
||||
let(:rebuild) { 1 }
|
||||
|
||||
its(:extname) { is_expected.to eq ".tag.bottle.1.tar.gz" }
|
||||
its(:extname) { is_expected.to eq ".x86_64_linux.bottle.1.tar.gz" }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#to_s and #to_str" do
|
||||
its(:to_s) { is_expected.to eq "foo--1.0.tag.bottle.tar.gz" }
|
||||
its(:to_str) { is_expected.to eq "foo--1.0.tag.bottle.tar.gz" }
|
||||
its(:to_s) { is_expected.to eq "foo--1.0.x86_64_linux.bottle.tar.gz" }
|
||||
its(:to_str) { is_expected.to eq "foo--1.0.x86_64_linux.bottle.tar.gz" }
|
||||
end
|
||||
|
||||
describe "#url_encode" do
|
||||
its(:url_encode) { is_expected.to eq "foo-1.0.tag.bottle.tar.gz" }
|
||||
its(:url_encode) { is_expected.to eq "foo-1.0.x86_64_linux.bottle.tar.gz" }
|
||||
end
|
||||
|
||||
describe "#github_packages" do
|
||||
its(:github_packages) { is_expected.to eq "foo--1.0.tag.bottle.tar.gz" }
|
||||
its(:github_packages) { is_expected.to eq "foo--1.0.x86_64_linux.bottle.tar.gz" }
|
||||
end
|
||||
|
||||
describe "#json" do
|
||||
its(:json) { is_expected.to eq "foo--1.0.tag.bottle.json" }
|
||||
its(:json) { is_expected.to eq "foo--1.0.x86_64_linux.bottle.json" }
|
||||
|
||||
context "when rebuild is 1" do
|
||||
its(:json) { is_expected.to eq "foo--1.0.tag.bottle.json" }
|
||||
its(:json) { is_expected.to eq "foo--1.0.x86_64_linux.bottle.json" }
|
||||
end
|
||||
end
|
||||
|
||||
describe "::create" do
|
||||
subject { described_class.create(f, :tag, 0) }
|
||||
subject { described_class.create(f, tag, rebuild) }
|
||||
|
||||
let(:f) do
|
||||
formula do
|
||||
@ -56,6 +56,6 @@ describe Bottle::Filename do
|
||||
end
|
||||
end
|
||||
|
||||
its(:to_s) { is_expected.to eq "formula_name--1.0.tag.bottle.tar.gz" }
|
||||
its(:to_s) { is_expected.to eq "formula_name--1.0.x86_64_linux.bottle.tar.gz" }
|
||||
end
|
||||
end
|
||||
|
@ -168,4 +168,17 @@ module Utils
|
||||
word.downcase!
|
||||
word
|
||||
end
|
||||
|
||||
SAFE_FILENAME_REGEX = /[[:cntrl:]#{Regexp.escape("#{File::SEPARATOR}#{File::ALT_SEPARATOR}")}]/o
|
||||
private_constant :SAFE_FILENAME_REGEX
|
||||
|
||||
sig { params(basename: String).returns(T::Boolean) }
|
||||
def self.safe_filename?(basename)
|
||||
!SAFE_FILENAME_REGEX.match?(basename)
|
||||
end
|
||||
|
||||
sig { params(basename: String).returns(String) }
|
||||
def self.safe_filename(basename)
|
||||
basename.gsub(SAFE_FILENAME_REGEX, "")
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user