Skip Menu |

This queue is for tickets about the Data-Diver CPAN distribution.

Report information
The Basics
Id: 108120
Status: new
Priority: 0/
Queue: Data-Diver

People
Owner: Nobody in particular
Requestors: kevin.broadey [...] ptti.co.uk
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Data-Diver-1.0101: Dive() does not do advertised scalar reference dereferencing
Date: Thu, 29 Oct 2015 20:42:13 +0000
To: "bug-Data-Diver [...] rt.cpan.org" <bug-Data-Diver [...] rt.cpan.org>
From: Kevin Broadey <kevin.broadey [...] ptti.co.uk>
The POD says: For both Dive() and DiveRef(), each $key in @ListOfKeys can have the following values: […snip…] a reference to a scalarThis means that you expect $ref to be a reference to a hash and you want to dereference it using $$key as the key. This is true for DiveRef (and therefore DiveVal) but it is NOT true for Dive itself. Looking at the code, the handling for ‘$$key’ around line 90 is flawed. Here’s a test case to show the bug:- ------------------------------------------------------------------------------- #!/usr/bin/perl use strict; use warnings; use Data::Diver qw(Dive DiveVal DiveError); use Data::Dumper; my %Collection; my @keys = qw(Location WNHO110 I 20151018); my @keyrefs = \((@keys)); sub value_or_dive_error { my $expr = shift; my $value = eval "[ $expr || DiveError() ]"; print "$expr: @$value\n"; } DiveVal(\%Collection, @keyrefs) = "Hello World!"; value_or_dive_error 'Dive(\%Collection, @keyrefs)'; value_or_dive_error 'Dive(\%Collection, \((@keys)) )'; value_or_dive_error 'Dive(\%Collection, @keys)'; value_or_dive_error 'DiveVal(\%Collection, @keyrefs)'; print Data::Dumper->Dump([\%Collection], [qw(Collection)]); ------------------------------------------------------------------------------- Here’s the output with the faulty code... ./Data-Dumper-bug.pl Dive(\%Collection, @keyrefs): Key not present in hash HASH(0x7fb1c20173c8) REF(0x7fb1c20226e0) Dive(\%Collection, \((@keys)) ): Key not present in hash HASH(0x7fb1c20173c8) REF(0x7fb1c287a5c8) Dive(\%Collection, @keys): Hello World! DiveVal(\%Collection, @keyrefs): Hello World! $Collection = { 'Location' => { 'WNHO110' => { 'I' => { '20151018' => 'Hello World!' } } } }; ------------------------------------------------------------------------------- Here’s a patch to fix it - though you may want to revisit the ‘$$key’ stuff immediately after in the original code... diff -u Diver.pm.orig Diver.pm --- Diver.pm.orig 2005-09-03 07:57:22.000000000 +0100 +++ Diver.pm 2015-10-29 20:40:24.000000000 +0000 @@ -4,7 +4,7 @@ require Exporter; use vars qw( $VERSION @EXPORT_OK ); BEGIN { - $VERSION= 1.01_01; + $VERSION= 1.01_02; @EXPORT_OK= qw( Dive DiveRef DiveVal DiveError DiveDie DiveClear ); *import= \&Exporter::import; *isa= \&UNIVERSAL::isa; @@ -87,6 +87,10 @@ if $key < -@$ref || $#$ref < $key; $ref= $ref->[$key]; + } elsif( ref($key) + && eval { exists $ref->{$$key} } + ) { + $ref= $ref->{$$key}; } elsif( eval { exists $ref->{$key} } ) { if( eval { my $x= $$key; 1 } ) { $ref= $ref->{$$key}; ------------------------------------------------------------------------------- and here’s the proof the fix works… ./Data-Dumper-bug.pl Dive(\%Collection, @keyrefs): Hello World! Dive(\%Collection, \((@keys)) ): Hello World! Dive(\%Collection, @keys): Hello World! DiveVal(\%Collection, @keyrefs): Hello World! $Collection = { 'Location' => { 'WNHO110' => { 'I' => { '20151018' => 'Hello World!' } } } }; ------------------------------------------------------------------------------- All the best Kevin