Fix a NULL pointer dereference when looking for a DESTROY method
Niko Tyni [Tue, 19 Jan 2010 10:03:08 +0000 (11:03 +0100)]
The empty DESTROY method optimization introduced by commit
fbb3ee5af3d would crash the interpreter if a DESTROY method
was declared but not actually defined.

This is seen in the real world with AutoLoader / AutoSplit,
where the crash defeats autoloading a DESTROY method.

sv.c
t/op/method.t

diff --git a/sv.c b/sv.c
index 4e80e18..a3eb187 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -5664,7 +5664,8 @@ Perl_sv_clear(pTHX_ register SV *const sv)
                        && !CvCONST(destructor)
                        /* Don't bother calling an empty destructor */
                        && (CvISXSUB(destructor)
-                       || CvSTART(destructor)->op_next->op_type != OP_LEAVESUB))
+                       || (CvSTART(destructor)
+                           && (CvSTART(destructor)->op_next->op_type != OP_LEAVESUB))))
                {
                    SV* const tmpref = newRV(sv);
                    SvREADONLY_on(tmpref);   /* DESTROY() could be naughty */
index afa8cfb..b602ca2 100644 (file)
@@ -10,7 +10,7 @@ BEGIN {
     require "test.pl";
 }
 
-print "1..78\n";
+print "1..79\n";
 
 @A::ISA = 'B';
 @B::ISA = 'C';
@@ -292,3 +292,16 @@ EOT
        "check if UNIVERSAL::AUTOLOAD works",
     );
 }
+
+# Test for #71952: crash when looking for a nonexistent destructor
+# Regression introduced by fbb3ee5af3d4
+{
+    fresh_perl_is(<<'EOT',
+sub M::DESTROY; bless {}, "M" ; print "survived\n";
+EOT
+    "survived",
+    {},
+       "no crash with a declared but missing DESTROY method"
+    );
+}
+