diff --git a/lib/bundler/audit/cli.rb b/lib/bundler/audit/cli.rb index 97979ecc..466160d2 100644 --- a/lib/bundler/audit/cli.rb +++ b/lib/bundler/audit/cli.rb @@ -71,6 +71,9 @@ def check(dir=Dir.pwd) rescue Bundler::GemfileLockNotFound => exception say exception.message, :red exit 1 + rescue Scanner::InvalidGemfileLock => exception + say_error exception.message, :red + exit 1 end report = scanner.report(ignore: options.ignore) diff --git a/lib/bundler/audit/scanner.rb b/lib/bundler/audit/scanner.rb index f0e79a30..1613931c 100644 --- a/lib/bundler/audit/scanner.rb +++ b/lib/bundler/audit/scanner.rb @@ -36,6 +36,12 @@ module Audit # class Scanner + # Raised when the given file is not a valid Bundler lockfile. + class InvalidGemfileLock < StandardError; end + + # Regexp matching the first line of every valid Bundler lockfile. + LOCKFILE_HEADER_RE = /\A(GEM|GIT|PATH|PLUGIN SOURCE|PLATFORMS|DEPENDENCIES|BUNDLED WITH)\b/ + # The advisory database. # # @return [Database] @@ -84,7 +90,13 @@ def initialize(root=Dir.pwd,gemfile_lock='Gemfile.lock',database=Database.new,co raise(Bundler::GemfileLockNotFound,"Could not find #{gemfile_lock.inspect} in #{@root.inspect}") end - @lockfile = LockfileParser.new(File.read(gemfile_lock_path)) + lock_file_content = File.read(gemfile_lock_path) + + unless lock_file_content =~ LOCKFILE_HEADER_RE + raise(InvalidGemfileLock,"#{gemfile_lock.inspect} is not a valid Gemfile.lock") + end + + @lockfile = LockfileParser.new(lock_file_content) config_dot_file_full_path = File.absolute_path(config_dot_file, @root) diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 11e4f256..0d1de922 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -161,4 +161,35 @@ end end end + + describe "#check" do + context "when --gemfile-lock is not a valid lock file" do + let(:bundle_dir) { File.expand_path(File.join('spec','bundle','unpatched_gems')) } + let(:database_path) { Fixtures::Database::PATH } + + it "must print an error message to stderr" do + expect { + begin + described_class.start ['check', bundle_dir, + '--gemfile-lock', 'Gemfile', + '--database', database_path, + '--no-update'] + rescue SystemExit + end + }.to output(/is not a valid Gemfile\.lock/).to_stderr + end + + it "must exit with status 1" do + expect { + described_class.start ['check', bundle_dir, + '--gemfile-lock', 'Gemfile', + '--database', database_path, + '--no-update'] + }.to raise_error(SystemExit) do |error| + expect(error.success?).to eq(false) + expect(error.status).to eq(1) + end + end + end + end end diff --git a/spec/scanner_spec.rb b/spec/scanner_spec.rb index afde727c..4cbfb600 100644 --- a/spec/scanner_spec.rb +++ b/spec/scanner_spec.rb @@ -7,6 +7,16 @@ subject { described_class.new(directory) } + describe "#initialize" do + context "when given a non-lock file as gemfile_lock" do + it "should raise InvalidGemfileLock" do + expect { + described_class.new(directory, 'Gemfile') + }.to raise_error(Scanner::InvalidGemfileLock,/is not a valid Gemfile\.lock/) + end + end + end + describe "#scan" do it "should yield results" do results = []