Fix CVE-2026-48962 in perl-IO-Compress File::GlobMapper
Backport fix for CVE-2026-48962 which removes the use of eval in File::GlobMapper to prevent arbitrary code execution. The patch combines two upstream commits: f2db247 (primary fix removing eval usage) and 3651e9e (regression fix for wildcard replacement after ordinary letters). CVE: CVE-2026-48962 Upstream patches: -f2db247bf9.patch -3651e9eb3f.patch Resolves: RHEL-180419 This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent. Assisted-by: Ymir
This commit is contained in:
parent
0517de8b0a
commit
37fd0fc79f
266
perl-IO-Compress-2.212-CVE-2026-48962.patch
Normal file
266
perl-IO-Compress-2.212-CVE-2026-48962.patch
Normal file
@ -0,0 +1,266 @@
|
||||
From 4fc8f378815526073e84a62d1c4984b175c2a261 Mon Sep 17 00:00:00 2001
|
||||
From: pmqs <pmqs@cpan.org>
|
||||
Date: Sat, 16 May 2026 17:48:34 +0100
|
||||
Subject: [PATCH 1/2] remove use of eval in globmapper. #73
|
||||
|
||||
---
|
||||
lib/File/GlobMapper.pm | 52 ++++++++++++++++++++++++++++++++++--------
|
||||
t/globmapper.t | 52 +++++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 94 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/lib/File/GlobMapper.pm b/lib/File/GlobMapper.pm
|
||||
index 53f957a..6454bc4 100644
|
||||
--- a/lib/File/GlobMapper.pm
|
||||
+++ b/lib/File/GlobMapper.pm
|
||||
@@ -29,6 +29,11 @@ our ($VERSION, @EXPORT_OK);
|
||||
$VERSION = '1.001';
|
||||
@EXPORT_OK = qw( globmap );
|
||||
|
||||
+our $BEGIN_DELIM = "\xFF";
|
||||
+our $END_DELIM = "\xFE";
|
||||
+our $BACKSLASH_ESC = "\xFD";
|
||||
+our $HASH_ESC = "\xFC";
|
||||
+our $STAR_ESC = "\xFB";
|
||||
|
||||
our ($noPreBS, $metachars, $matchMetaRE, %mapping, %wildCount);
|
||||
$noPreBS = '(?<!\\\)' ; # no preceding backslash
|
||||
@@ -310,14 +315,23 @@ sub _parseOutputGlob
|
||||
}
|
||||
|
||||
my $noPreBS = '(?<!\\\)' ; # no preceding backslash
|
||||
- #warn "noPreBS = '$noPreBS'\n";
|
||||
+ my $noPreESC = '(?<![${BEGIN_DELIM}])' ; # no preceding backslash
|
||||
|
||||
- #$string =~ s/${noPreBS}\$(\d)/\${$1}/g;
|
||||
- $string =~ s/${noPreBS}#(\d)/\${$1}/g;
|
||||
- $string =~ s#${noPreBS}\*#\${inFile}#g;
|
||||
- $string = '"' . $string . '"';
|
||||
+ # escape any use of the delimiter symbols
|
||||
+ # $string =~ s/(${BEGIN_DELIM}|${END_DELIM}|${BACKSLASH_ESC})/$1$1/g;
|
||||
+
|
||||
+ # escape \# and \*
|
||||
+ $string =~ s/\\#/${HASH_ESC}/g;
|
||||
+ $string =~ s/\\\*/${STAR_ESC}/g;
|
||||
+
|
||||
+ # Transform "#3" to BEGIN_DELIM 3 END_DELIM
|
||||
+ $string =~ s/${noPreESC}#(\d)/${BEGIN_DELIM}${1}${END_DELIM}/g;
|
||||
+
|
||||
+ $string =~ s#\*#${BEGIN_DELIM}${END_DELIM}#g;
|
||||
+
|
||||
+ # print "INPUT '$self->{InputPattern}'\n";
|
||||
+ # print "OUTPUT '$self->{OutputGlob}' => '$string'\n";
|
||||
|
||||
- #print "OUTPUT '$self->{OutputGlob}' => '$string'\n";
|
||||
$self->{OutputPattern} = $string ;
|
||||
|
||||
return 1 ;
|
||||
@@ -335,11 +349,31 @@ sub _getFiles
|
||||
next if $inFiles{$inFile} ++ ;
|
||||
|
||||
my $outFile = $inFile ;
|
||||
+ my @matches ;
|
||||
+
|
||||
+ my $noPreESC = '(?<![${BEGIN_DELIM}])' ; # no preceding backslash
|
||||
|
||||
- if ( $inFile =~ m/$self->{InputPattern}/ )
|
||||
+ if (@matches = ($inFile =~ m/$self->{InputPattern}/ ))
|
||||
{
|
||||
- no warnings 'uninitialized';
|
||||
- eval "\$outFile = $self->{OutputPattern};" ;
|
||||
+ $outFile = $self->{OutputPattern};
|
||||
+ my $ix = 1;
|
||||
+
|
||||
+ # get the filename glob
|
||||
+ $outFile =~ s/${noPreESC}${BEGIN_DELIM}${END_DELIM}/$inFile/g;
|
||||
+
|
||||
+ # now each of the #1, #2,...
|
||||
+ for my $pattern (@matches)
|
||||
+ {
|
||||
+ $outFile =~ s/${noPreESC}${BEGIN_DELIM}${ix}${END_DELIM}/$pattern/g;
|
||||
+
|
||||
+ ++ $ix;
|
||||
+ }
|
||||
+
|
||||
+ # unescape
|
||||
+ $outFile =~ s/${BEGIN_DELIM}${BEGIN_DELIM}/${BEGIN_DELIM}/g;
|
||||
+ $outFile =~ s/${END_DELIM}${END_DELIM}/${END_DELIM}/g;
|
||||
+ $outFile =~ s/${HASH_ESC}/#/g;
|
||||
+ $outFile =~ s/${STAR_ESC}/*/g;
|
||||
|
||||
if (defined $outInMapping{$outFile})
|
||||
{
|
||||
diff --git a/t/globmapper.t b/t/globmapper.t
|
||||
index 75fa768..842562f 100644
|
||||
--- a/t/globmapper.t
|
||||
+++ b/t/globmapper.t
|
||||
@@ -24,7 +24,7 @@ Perl $]" )
|
||||
$extra = 1
|
||||
if eval { require Test::NoWarnings ; Test::NoWarnings->import; 1 };
|
||||
|
||||
- plan tests => 68 + $extra ;
|
||||
+ plan tests => 76 + $extra ;
|
||||
|
||||
use_ok('File::GlobMapper') ;
|
||||
}
|
||||
@@ -290,6 +290,56 @@ Perl $]" )
|
||||
], " got mapping";
|
||||
}
|
||||
|
||||
+{
|
||||
+ title "check escaping";
|
||||
+
|
||||
+ my $tmpDir ;#= 'td';
|
||||
+ my $lex = LexDir->new( $tmpDir );
|
||||
+
|
||||
+ my $BEGIN_DELIM = "\xFF";
|
||||
+ my $END_DELIM = "\xFE";
|
||||
+
|
||||
+ #mkdir $tmpDir, 0777 ;
|
||||
+
|
||||
+ touch map { "$tmpDir/$_.tmp" } qw( abc1 abc2 abc3 ) ;
|
||||
+
|
||||
+ my $map = File::GlobMapper::globmap("$tmpDir/*b*.tmp", "$tmpDir/X-${BEGIN_DELIM}#2-#1${END_DELIM}-X");
|
||||
+ ok $map, " got map"
|
||||
+ or diag $File::GlobMapper::Error ;
|
||||
+
|
||||
+ is @{ $map }, 3, " returned 3 maps";
|
||||
+ is_deeply $map,
|
||||
+ [ [map { "$tmpDir/$_" } ("abc1.tmp", "X-${BEGIN_DELIM}c1-a${END_DELIM}-X")],
|
||||
+ [map { "$tmpDir/$_" } ("abc2.tmp", "X-${BEGIN_DELIM}c2-a${END_DELIM}-X")],
|
||||
+ [map { "$tmpDir/$_" } ("abc3.tmp", "X-${BEGIN_DELIM}c3-a${END_DELIM}-X")],
|
||||
+ ], " got mapping";
|
||||
+}
|
||||
+
|
||||
+{
|
||||
+ title "check backslash escaping";
|
||||
+
|
||||
+ my $tmpDir ;#= 'td';
|
||||
+ my $lex = LexDir->new( $tmpDir );
|
||||
+
|
||||
+ my $BEGIN_DELIM = "\xFF";
|
||||
+ my $END_DELIM = "\xFE";
|
||||
+
|
||||
+ #mkdir $tmpDir, 0777 ;
|
||||
+
|
||||
+ touch map { "$tmpDir/$_.tmp" } qw( abc1 abc2 abc3 ) ;
|
||||
+
|
||||
+ my $map = File::GlobMapper::globmap("$tmpDir/*b*.tmp", $tmpDir . '/X-#2-\\#1\\*-X');
|
||||
+ ok $map, " got map"
|
||||
+ or diag $File::GlobMapper::Error ;
|
||||
+
|
||||
+ is @{ $map }, 3, " returned 3 maps";
|
||||
+ is_deeply $map,
|
||||
+ [ [map { "$tmpDir/$_" } ("abc1.tmp", "X-c1-#1*-X")],
|
||||
+ [map { "$tmpDir/$_" } ("abc2.tmp", "X-c2-#1*-X")],
|
||||
+ [map { "$tmpDir/$_" } ("abc3.tmp", "X-c3-#1*-X")],
|
||||
+ ], " got mapping";
|
||||
+}
|
||||
+
|
||||
# TODO
|
||||
# test each of the wildcard metacharacters can be mapped to the output filename
|
||||
#
|
||||
|
||||
From eef728b3fbf5c0e7dbcfbf7a02c289a74ffb2ad4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Vladim=C3=ADr=20Marek?= <vlmarek13@gmail.com>
|
||||
Date: Thu, 11 Jun 2026 15:55:22 +0200
|
||||
Subject: [PATCH 2/2] Fix File::GlobMapper wildcard replacement after ordinary
|
||||
letters
|
||||
|
||||
The eval-removal change used a single-quoted negative lookbehind
|
||||
containing ${BEGIN_DELIM}. That made the regex treat the characters in the
|
||||
literal string "${BEGIN_DELIM}" as excluded preceding characters, so output
|
||||
patterns such as B#1.out or IMG#1.out did not expand #1.
|
||||
|
||||
Escaped literal # and * are already protected with HASH_ESC and STAR_ESC
|
||||
before wildcard references are converted to internal markers, so the
|
||||
lookbehind is not needed. Replace exact internal marker sequences directly
|
||||
when generating output filenames.
|
||||
|
||||
Add a regression test for expanding #1 after an ordinary letter.
|
||||
---
|
||||
lib/File/GlobMapper.pm | 9 +++------
|
||||
t/globmapper.t | 20 +++++++++++++++++++-
|
||||
2 files changed, 22 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/lib/File/GlobMapper.pm b/lib/File/GlobMapper.pm
|
||||
index 6454bc4..2332336 100644
|
||||
--- a/lib/File/GlobMapper.pm
|
||||
+++ b/lib/File/GlobMapper.pm
|
||||
@@ -315,7 +315,6 @@ sub _parseOutputGlob
|
||||
}
|
||||
|
||||
my $noPreBS = '(?<!\\\)' ; # no preceding backslash
|
||||
- my $noPreESC = '(?<![${BEGIN_DELIM}])' ; # no preceding backslash
|
||||
|
||||
# escape any use of the delimiter symbols
|
||||
# $string =~ s/(${BEGIN_DELIM}|${END_DELIM}|${BACKSLASH_ESC})/$1$1/g;
|
||||
@@ -325,7 +324,7 @@ sub _parseOutputGlob
|
||||
$string =~ s/\\\*/${STAR_ESC}/g;
|
||||
|
||||
# Transform "#3" to BEGIN_DELIM 3 END_DELIM
|
||||
- $string =~ s/${noPreESC}#(\d)/${BEGIN_DELIM}${1}${END_DELIM}/g;
|
||||
+ $string =~ s/#(\d)/${BEGIN_DELIM}${1}${END_DELIM}/g;
|
||||
|
||||
$string =~ s#\*#${BEGIN_DELIM}${END_DELIM}#g;
|
||||
|
||||
@@ -351,20 +350,18 @@ sub _getFiles
|
||||
my $outFile = $inFile ;
|
||||
my @matches ;
|
||||
|
||||
- my $noPreESC = '(?<![${BEGIN_DELIM}])' ; # no preceding backslash
|
||||
-
|
||||
if (@matches = ($inFile =~ m/$self->{InputPattern}/ ))
|
||||
{
|
||||
$outFile = $self->{OutputPattern};
|
||||
my $ix = 1;
|
||||
|
||||
# get the filename glob
|
||||
- $outFile =~ s/${noPreESC}${BEGIN_DELIM}${END_DELIM}/$inFile/g;
|
||||
+ $outFile =~ s/${BEGIN_DELIM}${END_DELIM}/$inFile/g;
|
||||
|
||||
# now each of the #1, #2,...
|
||||
for my $pattern (@matches)
|
||||
{
|
||||
- $outFile =~ s/${noPreESC}${BEGIN_DELIM}${ix}${END_DELIM}/$pattern/g;
|
||||
+ $outFile =~ s/${BEGIN_DELIM}${ix}${END_DELIM}/$pattern/g;
|
||||
|
||||
++ $ix;
|
||||
}
|
||||
diff --git a/t/globmapper.t b/t/globmapper.t
|
||||
index 842562f..824466b 100644
|
||||
--- a/t/globmapper.t
|
||||
+++ b/t/globmapper.t
|
||||
@@ -24,7 +24,7 @@ Perl $]" )
|
||||
$extra = 1
|
||||
if eval { require Test::NoWarnings ; Test::NoWarnings->import; 1 };
|
||||
|
||||
- plan tests => 76 + $extra ;
|
||||
+ plan tests => 80 + $extra ;
|
||||
|
||||
use_ok('File::GlobMapper') ;
|
||||
}
|
||||
@@ -340,6 +340,24 @@ Perl $]" )
|
||||
], " got mapping";
|
||||
}
|
||||
|
||||
+{
|
||||
+ title "check wildcard references after ordinary letters";
|
||||
+
|
||||
+ my $tmpDir ;#= 'td';
|
||||
+ my $lex = LexDir->new( $tmpDir );
|
||||
+
|
||||
+ touch map { "$tmpDir/$_.tmp" } qw( abc ) ;
|
||||
+
|
||||
+ my $map = File::GlobMapper::globmap("$tmpDir/a*.tmp", "$tmpDir/B#1.out");
|
||||
+ ok $map, " got map"
|
||||
+ or diag $File::GlobMapper::Error ;
|
||||
+
|
||||
+ is @{ $map }, 1, " returned 1 map";
|
||||
+ is_deeply $map,
|
||||
+ [ [map { "$tmpDir/$_" } ("abc.tmp", "Bbc.out")],
|
||||
+ ], " got mapping";
|
||||
+}
|
||||
+
|
||||
# TODO
|
||||
# test each of the wildcard metacharacters can be mapped to the output filename
|
||||
#
|
||||
@ -14,11 +14,14 @@
|
||||
|
||||
Name: perl-IO-Compress
|
||||
Version: 2.212
|
||||
Release: 512%{?dist}
|
||||
Release: 513%{?dist}
|
||||
Summary: Read and write compressed data
|
||||
License: GPL-1.0-or-later OR Artistic-1.0-Perl
|
||||
URL: https://metacpan.org/release/IO-Compress
|
||||
Source0: https://cpan.metacpan.org/modules/by-module/IO/IO-Compress-%{version}.tar.gz
|
||||
# https://github.com/pmqs/IO-Compress/commit/f2db247bf90d4cc7ee2710be384946081f3b4610
|
||||
# https://github.com/pmqs/IO-Compress/commit/3651e9eb3fca0bd3718d1d8b12e96b9e80096144
|
||||
Patch0: perl-IO-Compress-2.212-CVE-2026-48962.patch
|
||||
BuildArch: noarch
|
||||
# Module Build
|
||||
BuildRequires: coreutils
|
||||
@ -116,6 +119,7 @@ with "%{_libexecdir}/%{name}/test".
|
||||
|
||||
%prep
|
||||
%setup -q -n IO-Compress-%{version}
|
||||
%patch -P0 -p1
|
||||
|
||||
# Remove spurious exec permissions
|
||||
chmod -c -x lib/IO/Uncompress/{Adapter/Identity,RawInflate}.pm
|
||||
@ -209,6 +213,10 @@ make test COMPRESS_ZLIB_RUN_%{?with_long_tests:ALL}%{!?with_long_tests:MOST}=1
|
||||
%{_libexecdir}/%{name}
|
||||
|
||||
%changelog
|
||||
* Tue Jul 28 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.212-513
|
||||
- Fix CVE-2026-48962: Remove use of eval in File::GlobMapper
|
||||
Resolves: RHEL-180419
|
||||
|
||||
* Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 2.212-512
|
||||
- Bump release for October 2024 mass rebuild:
|
||||
Resolves: RHEL-64018
|
||||
|
||||
Loading…
Reference in New Issue
Block a user