8d306c
From b5ad485cc167b3b6aa43f83aa92bbf8b8811cb42 Mon Sep 17 00:00:00 2001
8d306c
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
8d306c
Date: Fri, 20 Apr 2018 10:20:55 +0200
8d306c
Subject: [PATCH] Fix RT #52610: Carp: Do not crash when reading @DB::args
8d306c
MIME-Version: 1.0
8d306c
Content-Type: text/plain; charset=UTF-8
8d306c
Content-Transfer-Encoding: 8bit
8d306c
8d306c
Petr Pisar: Ported from perl after 5.27.8. The unreliable test was
8d306c
later deleted in a77eff3c and the comments rephrased in 02c84d7:
8d306c
8d306c
commit 4764858cb80e76fdba33cc1b3be8fcdef26df754
8d306c
Author: Pali <pali@cpan.org>
8d306c
Date:   Wed Jan 31 22:43:46 2018 +0100
8d306c
8d306c
    Fix RT #52610: Carp: Do not crash when reading @DB::args
8d306c
8d306c
    Trying to read values from array @DB::args can lead to perl fatal error
8d306c
    "Bizarre copy of ARRAY in scalar assignment". But missing, incomplete or
8d306c
    possible incorrect value in @DB::args is not a fatal error for Carp.
8d306c
8d306c
    Carp is primary used for reporting warnings and errors from other
8d306c
    modules, so it should not crash perl when trying to print error message.
8d306c
8d306c
    This patch safely iterates all elements of @DB::args array via eval { }
8d306c
    block and replace already freed scalars for Carp usage by string
8d306c
    "** argument not available anymore **".
8d306c
8d306c
    This prevent crashing perl and allows to use Carp module. It it not a
8d306c
    proper fix but rather workaround for Carp module. At least it allows to
8d306c
    safely use Carp.
8d306c
8d306c
    Patch amended by Yves Orton
8d306c
8d306c
Signed-off-by: Petr Písař <ppisar@redhat.com>
8d306c
---
8d306c
 lib/Carp.pm | 22 ++++++++++++++++------
8d306c
 1 file changed, 16 insertions(+), 6 deletions(-)
8d306c
8d306c
diff --git a/lib/Carp.pm b/lib/Carp.pm
8d306c
index 05052b9..60b2469 100644
8d306c
--- a/lib/Carp.pm
8d306c
+++ b/lib/Carp.pm
8d306c
@@ -203,11 +203,22 @@ sub caller_info {
8d306c
 
8d306c
     my $sub_name = Carp::get_subname( \%call_info );
8d306c
     if ( $call_info{has_args} ) {
8d306c
-        my @args;
8d306c
-        if (CALLER_OVERRIDE_CHECK_OK && @DB::args == 1
8d306c
-            && ref $DB::args[0] eq ref \$i
8d306c
-            && $DB::args[0] == \$i ) {
8d306c
-            @DB::args = ();    # Don't let anyone see the address of $i
8d306c
+        # guard our serialization of the stack from stack refcounting bugs
8d306c
+        my @args = map {
8d306c
+                my $arg;
8d306c
+                local $@= $@;
8d306c
+                eval {
8d306c
+                    $arg = $_;
8d306c
+                    1;
8d306c
+                } or do {
8d306c
+                    $arg = '** argument not available anymore **';
8d306c
+                };
8d306c
+                $arg;
8d306c
+            } @DB::args;
8d306c
+        if (CALLER_OVERRIDE_CHECK_OK && @args == 1
8d306c
+            && ref $args[0] eq ref \$i
8d306c
+            && $args[0] == \$i ) {
8d306c
+            @args = ();    # Don't let anyone see the address of $i
8d306c
             local $@;
8d306c
             my $where = eval {
8d306c
                 my $func    = $cgc or return '';
8d306c
@@ -226,7 +237,6 @@ sub caller_info {
8d306c
                 = "** Incomplete caller override detected$where; \@DB::args were not set **";
8d306c
         }
8d306c
         else {
8d306c
-            @args = @DB::args;
8d306c
             my $overflow;
8d306c
             if ( $MaxArgNums and @args > $MaxArgNums )
8d306c
             {    # More than we want to show?
8d306c
-- 
8d306c
2.14.3
8d306c