develooper Front page | perl.perl5.porters | Postings from March 2006

Re: [perl #36267] hash assignment to a tied hash erroneously stores data in the real hash too

Thread Previous | Thread Next
From:
Nicholas Clark
Date:
March 30, 2006 10:20
Subject:
Re: [perl #36267] hash assignment to a tied hash erroneously stores data in the real hash too
Message ID:
20060330182002.GK32132@plum.flirble.org
On Mon, Jun 13, 2005 at 10:49:59AM -0000, Nicholas Clark wrote:
> # New Ticket Created by  Nicholas Clark 
> # Please include the string:  [perl #36267]
> # in the subject line of all future correspondence about this issue. 
> # <URL: https://rt.perl.org/rt3/Ticket/Display.html?id=36267 >
> 
> 
> Hash assignment (%foo = %bar) is one of the few parts of the perl core that
> uses hv_store, instead of hv_fetch.
> 
> If you assign to a tied hash, then the current implementation of hv_store
> erroneously also stores the new contents into the real hash hidden behind
> the tie interface, if that hash had ever had storage allocated. If you
> subsequently untie the hash, the original storage is exposed, and the
> erroneously assigned elements become visible.

I fixed this with change 27636

The hash API's reaction to tied hashes still feels crazy, but I'm not sure
if it's salvageable.

Nicholas Clark


Change 27636 by nicholas@nicholas-saigo on 2006/03/30 18:18:27

        Fix bug 36267 - assigning to a tied hash shouldn't change the
        underlying hash. (It used to, if the underlying hash had had storage
        allocated). This has the side effect of changing the return value from
        hv_store and hv_store_ent for some tied hash scenarios. But *to*
        something consistent (ly crazy)

Affected files ...

... //depot/perl/ext/XS/APItest/t/hash.t#9 edit
... //depot/perl/hv.c#295 edit
... //depot/perl/t/op/tie.t#44 edit

Differences ...

==== //depot/perl/ext/XS/APItest/t/hash.t#9 (text) ====

@@ -49,7 +49,7 @@
 {
   my %h = (a=>'cheat');
   tie %h, 'Tie::StdHash';
-  is (XS::APItest::Hash::store(\%h, chr 258,  1), 1);
+  is (XS::APItest::Hash::store(\%h, chr 258,  1), undef);
     
   ok (!exists $h{$utf8_for_258},
       "hv_store doesn't insert a key with the raw utf8 on a tied hash");
@@ -222,9 +222,9 @@
   if (defined $class) {
     tie %h1, ref $class;
     tie %h2, ref $class;
-    $HV_STORE_IS_CRAZY = undef unless @$defaults;
+    $HV_STORE_IS_CRAZY = undef;
   }
-  is (XS::APItest::Hash::store_ent(\%h1, $key, 1), 1,
+  is (XS::APItest::Hash::store_ent(\%h1, $key, 1), $HV_STORE_IS_CRAZY,
       "hv_store_ent$message $printable"); 
   ok (brute_force_exists (\%h1, $key), "hv_store_ent$message $printable");
   is (XS::APItest::Hash::store(\%h2, $key,  1), $HV_STORE_IS_CRAZY,

==== //depot/perl/hv.c#295 (text) ====

@@ -582,7 +582,7 @@
                }
 
                TAINT_IF(save_taint);
-               if (!HvARRAY(hv) && !needs_store) {
+               if (!needs_store) {
                    if (flags & HVhek_FREEKEY)
                        Safefree(key);
                    return NULL;

==== //depot/perl/t/op/tie.t#44 (xtext) ====

@@ -593,3 +593,22 @@
 print $x | $y;
 EXPECT
 10
+########
+# Bug 36267
+sub TIEHASH  { bless {}, $_[0] }
+sub STORE    { $_[0]->{$_[1]} = $_[2] }
+sub FIRSTKEY { my $a = scalar keys %{$_[0]}; each %{$_[0]} }
+sub NEXTKEY  { each %{$_[0]} }
+sub DELETE   { delete $_[0]->{$_[1]} }
+sub CLEAR    { %{$_[0]} = () }
+$h{b}=1;
+delete $h{b};
+print scalar keys %h, "\n";
+tie %h, 'main';
+$i{a}=1;
+%h = %i;
+untie %h;
+print scalar keys %h, "\n";
+EXPECT
+0
+0

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About