sv_dup(): avoid cloning empty arrays
kevin brintnall [Thu, 25 Dec 2008 02:59:15 +0000 (20:59 -0600)]
Testing the ARRAY pointer is insufficent.  Arrays emptied by 'shift' or
'pop' may still have non-NULL 'ARRAY' pointers.  Check more carefully to
determine whether the array has anything worth duplicating.  If not, reset
the FILL and MAX offsets to -1 just as 'undef @ARRAY' would.

This avoids potential corruption in the PL_ptr_table during perl_clone().

sv.c

diff --git a/sv.c b/sv.c
index 917c897..a9d9b21 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -10826,7 +10826,8 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                IoBOTTOM_NAME(dstr)     = SAVEPV(IoBOTTOM_NAME(dstr));
                break;
            case SVt_PVAV:
-               if (AvARRAY((const AV *)sstr)) {
+               /* avoid cloning an empty array */
+               if (AvARRAY((const AV *)sstr) && AvFILLp((const AV *)sstr) >= 0) {
                    SV **dst_ary, **src_ary;
                    SSize_t items = AvFILLp((const AV *)sstr) + 1;
 
@@ -10851,6 +10852,8 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                else {
                    AvARRAY(MUTABLE_AV(dstr))   = NULL;
                    AvALLOC((const AV *)dstr)   = (SV**)NULL;
+                   AvMAX(  (const AV *)dstr)   = -1;
+                   AvFILLp((const AV *)dstr)   = -1;
                }
                break;
            case SVt_PVHV: