Skip to content

Commit

Permalink
Merge pull request #15 from jordansissel/validate-payload-compressor
Browse files Browse the repository at this point in the history
Only attempt extraction if a known payload compressor is used.
  • Loading branch information
jordansissel committed Sep 17, 2022
2 parents c608f86 + 6ceb0a7 commit efddd45
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
2 changes: 2 additions & 0 deletions arr-pm.gemspec
Expand Up @@ -19,6 +19,8 @@ Gem::Specification.new do |spec|

spec.add_development_dependency "flores", ">0"
spec.add_development_dependency "rspec", ">3.0.0"
spec.add_development_dependency "stud", ">=0.0.23"
spec.add_development_dependency "insist", ">=1.0.0"
#spec.homepage = "..."
end

15 changes: 14 additions & 1 deletion lib/arr-pm/file.rb
Expand Up @@ -88,6 +88,14 @@ def payload
return @payload
end # def payload

def valid_compressor?(name)
# I scanned rpm's rpmio.c for payload implementation names and found the following.
# sed -rne '/struct FDIO_s \w+ *= *\{/{ n; s/^.*"(\w+)",$/\1/p }' rpmio/rpmio.c
# It's possible this misses some supported rpm payload compressors.

[ "gzip", "bzip2", "xz", "lzma", "zstd" ].include?(name)
end

# Extract this RPM to a target directory.
#
# This should have roughly the same effect as:
Expand All @@ -97,8 +105,13 @@ def extract(target)
if !File.directory?(target)
raise Errno::ENOENT.new(target)
end

compressor = tags[:payloadcompressor]
if !valid_compressor?(compressor)
raise "Cannot decompress. This RPM uses an invalid compressor '#{compressor}'"
end

extractor = IO.popen("#{tags[:payloadcompressor]} -d | (cd #{target}; cpio -i --quiet --make-directories)", "w")
extractor = IO.popen("#{compressor} -d | (cd #{target}; cpio -i --quiet --make-directories)", "w")
buffer = ""
begin
buffer.force_encoding("BINARY")
Expand Down
37 changes: 36 additions & 1 deletion spec/rpm/file_spec.rb
@@ -1,11 +1,14 @@
# encoding: utf-8

require "arr-pm/file"
require "stud/temporary"
require "insist"

describe ::RPM::File do
subject { described_class.new(path) }

context "with a known good rpm" do
let(:path) { File.join(File.dirname(__FILE__), "../fixtures/pagure-mirror-5.13.2-5.fc35.noarch.rpm") }
subject { described_class.new(path) }

context "#files" do
let(:files) { [
Expand All @@ -19,4 +22,36 @@
end
end
end

context "#extract" do
# This RPM should be correctly built, but we will modify the tags at runtime to force an error.
let(:path) { File.join(File.dirname(__FILE__), "../fixtures/example-1.0-1.x86_64.rpm") }
let(:dir) { dir = Stud::Temporary.directory }

after do
FileUtils.rm_rf(dir)
end

context "with an invalid payloadcompressor" do
before do
subject.tags[:payloadcompressor] = "some invalid | string"
end

it "should raise an error" do
insist { subject.extract(dir) }.raises(RuntimeError)
end
end

[ "gzip", "bzip2", "xz", "lzma", "zstd" ].each do |name|
context "with a '#{name}' payloadcompressor" do
before do
subject.tags[:payloadcompressor] = name
end

it "should succeed" do
reject { subject.extract(dir) }.raises(RuntimeError)
end
end
end
end
end

0 comments on commit efddd45

Please sign in to comment.