From 279a306fcb1789ef63fb04f83687b4ad24cec8f3 Mon Sep 17 00:00:00 2001 From: Postmodern Date: Fri, 13 Dec 2024 23:30:18 -0800 Subject: [PATCH] Improved `Text::Patterns::VERSION_NUMBER` (closes #557,#559,#560). * Match versions containing alpha-numeric parts. * When matching version numbers within file names, prevent accidentally matching the file extension as well (ex: `foo-1.2.3.zip` -> `1.2.3`). --- lib/ronin/support/text/patterns/numeric.rb | 2 +- spec/text/patterns/numeric_spec.rb | 67 ++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/lib/ronin/support/text/patterns/numeric.rb b/lib/ronin/support/text/patterns/numeric.rb index 3f19a491..5246b113 100644 --- a/lib/ronin/support/text/patterns/numeric.rb +++ b/lib/ronin/support/text/patterns/numeric.rb @@ -45,7 +45,7 @@ module Patterns # Regular expression for finding version numbers in text. # # @since 1.0.0 - VERSION_NUMBER = /\d+(?:\.\d+){1,3}(?:[-.]?[A-Za-z]+(?:[-.]?\d+)?)?/ + VERSION_NUMBER = /\d+\.\d+(?:(?!\.(?:tar|tgz|tbz|zip|rar|txt|htm|xml))[._-][A-Za-z0-9]+)*/ end end end diff --git a/spec/text/patterns/numeric_spec.rb b/spec/text/patterns/numeric_spec.rb index 80b41467..29b20058 100644 --- a/spec/text/patterns/numeric_spec.rb +++ b/spec/text/patterns/numeric_spec.rb @@ -84,12 +84,36 @@ expect(version).to fully_match(subject) end + it "must match 'X.Y-Z' versions" do + version = '1.2-3' + + expect(version).to fully_match(subject) + end + + it "must match 'X.Y_Z' versions" do + version = '1.2_3' + + expect(version).to fully_match(subject) + end + it "must match 'X.Y.Y.Z' versions" do version = '1.2.3.4' expect(version).to fully_match(subject) end + it "must match 'X.Y.Y-Z' versions" do + version = '1.2.3-4' + + expect(version).to fully_match(subject) + end + + it "must match 'X.Y.Y_Z' versions" do + version = '1.2.3_4' + + expect(version).to fully_match(subject) + end + it "must match 'X.Y.Ypre' versions" do version = '1.2.3pre' @@ -929,5 +953,48 @@ expect(version).to fully_match(subject) end + + context "when the version ends with a '+XXX' suffix" do + it "must not match the '+XXX' suffix" do + version = '1.2.3+a1b2c3' + + expect(version[subject]).to eq('1.2.3') + end + end + + it "must not accidentally match a phone number" do + expect('1-800-111-2222').to_not match(subject) + end + + it "must not accidentally match 'MM-DD-YY'" do + expect('01-02-24').to_not match(subject) + end + + it "must not accidentally match 'MM-DD-YYYY'" do + expect('01-02-2024').to_not match(subject) + end + + it "must not accidentally match 'YYYY-MM-DD'" do + expect('2024-01-02').to_not match(subject) + end + + it "must not accidentally match 'CVE-YYYY-XXXX'" do + expect('CVE-2024-1234').to_not match(subject) + end + + context "when the version is within a filename" do + let(:version) { '1.2.3' } + + %w[.tar.gz .tar.bz2 .tar.xz .tgz .tbz2 .zip .rar .htm .html .xml .txt].each do |extname| + context "and when the filename ends with '#{extname}'" do + let(:extname) { extname } + let(:filename) { "foo-#{version}#{extname}" } + + it "must not accidentally match '#{extname}' as part of the version" do + expect(filename[subject]).to eq(version) + end + end + end + end end end