Your message dated Sun, 31 May 2020 22:33:11 +0300 with message-id <[email protected]> and subject line Re: Bug#940922: perl: iterating hash with "each", no write to hash but references got messed up has caused the Debian Bug report #940922, regarding perl: iterating hash with "each", no write to hash but references got messed up to be marked as done.
This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact [email protected] immediately.) -- 940922: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=940922 Debian Bug Tracking System Contact [email protected] with problems
--- Begin Message ---Package: perl Version: 5.24.1-3+deb9u5 Severity: normal I was trying to make program below as simple as possible, but I don't understand where is the bug introduced. The task is to make a copy of hash such that keys in new hash are made only out of alphanumerics and underscores "_". Hashes are nested. Here is the program: #!/usr/bin/perl use Data::Dumper; sub hash_is_okey { ref $_[0] eq "HASH" or return 0; # for my $k (keys %{$_[0]}) { # my $v = ${$_[0]}{$k}; while (my ($k, $v) = each %{$_[0]}) { $k =~ /\A[_[:alnum:]]+\z/ or return 0; hash_ok_or_scalar($v) or return 0; } return 1; } sub hash_ok_or_scalar { return hash_is_okey($_[0]) || ! ref $_[0]; } sub make_hash_with_good_keys { my ($x) = $_[0]; hash_ok_or_scalar($x) and return $x; ref $x eq "HASH" or die; # copy hash "%{$x}" to new hash "%h" but make names good my %h; for my $k (keys %$x) { # copy "$k" to "$n", then make good name of "$n" my $n = $k =~ s/[^[:alnum:]]/_/gr; $h{$n} = make_hash_with_good_keys($$x{$k}); } return \%h; } my $original = { "top_level" => { "level down" => 123 } }; my $with_good_keys = make_hash_with_good_keys($original); print Dumper($original, $with_good_keys); and here is the result: $VAR1 = { 'top_level' => { 'level down' => 123 } }; $VAR2 = { 'top_level' => $VAR1->{'top_level'} }; In program hash "$with_good_keys" is made by: * initializing new hash "%h", and then asigning to that hash new value or * plugging reference if "subhash" has good keys. But the result is bad, because "VAR2" has bad key "level down" -- contains space. If I change this part of program: # for my $k (keys %{$_[0]}) { # my $v = ${$_[0]}{$k}; while (my ($k, $v) = each %{$_[0]}) { to look like this (uncomment "for...keys", comment "while...each"): for my $k (keys %{$_[0]}) { my $v = ${$_[0]}{$k}; # while (my ($k, $v) = each %{$_[0]}) { then result is: $VAR1 = { 'top_level' => { 'level down' => 123 } }; $VAR2 = { 'top_level' => { 'level_down' => 123 } }; Now "$VAR2" is a copy with names modified as expected. This is extremely strange, because I don't write to hash I am iterating over with "while...each". I tried to resolve this myself for many hours, but I failed. -- System Information: Debian Release: 9.11 APT prefers oldstable-updates APT policy: (500, 'oldstable-updates'), (500, 'oldstable') Architecture: amd64 (x86_64) Kernel: Linux 4.9.0-9-amd64 (SMP w/4 CPU cores) Locale: LANG=pl_PL.UTF-8, LC_CTYPE=pl_PL.UTF-8 (charmap=UTF-8), LANGUAGE=pl_PL.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) Versions of packages perl depends on: ii dpkg 1.18.25 ii libperl5.24 5.24.1-3+deb9u5 ii perl-base 5.24.1-3+deb9u5 ii perl-modules-5.24 5.24.1-3+deb9u5 Versions of packages perl recommends: ii netbase 5.4 pn rename <none> Versions of packages perl suggests: pn libterm-readline-gnu-perl | libterm-readline-perl-perl <none> pn make <none> pn perl-doc <none> -- no debconf information
--- End Message ---
--- Begin Message ---On Sun, Sep 22, 2019 at 01:39:30AM +0200, Leszek Dubiel wrote: > Package: perl > Version: 5.24.1-3+deb9u5 > Severity: normal > > I was trying to make program below as simple as possible, but I don't > understand where is the bug introduced. > > The task is to make a copy of hash such that keys in new hash are made only > out of alphanumerics and underscores "_". Hashes are nested. [...] > This is extremely strange, because I don't write to hash I am iterating over > with "while...each". I tried to > resolve this myself for many hours, but I failed. Hi, in the first hash_ok_or_scalar() check, the each() iterator in hash_is_okey() for the second level hash is left incomplete by the 'return 0' when the first (and only) item is deemed bad. When make_hash_with_good_keys() is then called recursively to make a copy of the second level hash, it calls hash_is_okey() again on the original second level hash, and each() continues where it left off, yielding nothing. So hash_is_okey() returns 1 as if there's nothing wrong with the hash, and make_hash_with_good_keys() happily returns it unchanged. Hope that helps, not sure if I explained it clearly enough. Anyway, this is not a bug in Perl so closing. -- Niko Tyni [email protected]
--- End Message ---

