Skip Menu |

This queue is for tickets about the Win32-TieRegistry CPAN distribution.

Report information
The Basics
Id: 99892
Status: resolved
Priority: 0/
Queue: Win32-TieRegistry

People
Owner: Nobody in particular
Requestors: Bruce.Reed [...] infor.com
Cc:
AdminCc:

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



CC: Jean McAllister <Jean.Mcallister [...] infor.com>, Mark Hewitt <Mark.Hewitt [...] infor.com>
Subject: Win32::TieRegistry::ValueNames error with Strawberry Perl 5.20
Date: Wed, 29 Oct 2014 18:40:16 +0000
To: "bug-Win32-TieRegistry [...] rt.cpan.org" <bug-Win32-TieRegistry [...] rt.cpan.org>
From: Bruce Reed <Bruce.Reed [...] infor.com>
This is in Version 0.26 of Win32::TieRegistry. There are actually two issues here. Issue #1 ValueNames calls _enumValues. If _enumValues does not set $self->{VALUES} for any reason, it remains an undefined value. Then ValueNames still tries to use as an Array reference it at line 682 without checking if it's set. Issue #2 - this is the real problem _enumValues is making this call to a Win32API::Registry function: my $nlen= 1+$self->Information("MaxValNameLen"); while( $self->RegEnumValue($pos++,$name,$nlen,[],[],[],[]) ) { According to the documentation for Win32API::Registry: $plValName initially specifies the [minimum] buffer size to be allocated for $sValName. Will be set to the length of the value name if the requested value exists even if $sValName isn't successfully set to the value name. See "Buffer sizes" for more information. "$plValName" is $nlen in this function call. $nlen is getting changed by the call to RegEnumValue, but is not getting reset to the MaxValNameLen value (plus 1) for the next call to RegEnumValue. This works OK with ActivePerl 5.18 and Strawberry Perl 5.18, and I assume earlier versions of both. However, it fails with Strawberry Perl 5.20 with this message: Can't use an undefined value as an ARRAY reference at c:/Strawberry64/perl/vendor/lib/Win32/TieRegistry.pm line 682. In my testing, if I reset $nlen to the value taken from MaxValNameLen, or just pass null (undef) instead of $nlen, it works OK even with Strawberry Perl 5.20. [cid:image001.png@01CFEC4C.24180FA0] Bruce Reed | Lead Software Engineer - Systems office/mobile: 989 430 2897 | urgent: 9894302897@vtext.com<mailto:9894302897@vtext.com> | bruce.reed@infor.com<mailto:bruce.reed@infor.com> | http://www.infor.com
Download image001.png
image/png 889b
image001.png
From: bruce.reed [...] infor.com
This problem occurs with Strawberry Perl 5.20.1, 32-bit and 64-bit. It does not occur with 5.20.0 or 5.18.4.
Note that this issue occurs with perl 5.20.1, but not 5.20.0 in both 32 and 64-bit builds. On Wed Oct 29 14:40:34 2014, Bruce.Reed@infor.com wrote: Show quoted text
> This is in Version 0.26 of Win32::TieRegistry. > > There are actually two issues here. > > Issue #1 > ValueNames calls _enumValues. > If _enumValues does not set $self->{VALUES} for any reason, it remains > an undefined value. > Then ValueNames still tries to use as an Array reference it at line > 682 without checking if it's set. > > Issue #2 - this is the real problem > _enumValues is making this call to a Win32API::Registry function: > my $nlen= 1+$self->Information("MaxValNameLen"); > while( $self->RegEnumValue($pos++,$name,$nlen,[],[],[],[]) ) { > According to the documentation for Win32API::Registry: > $plValName initially specifies the [minimum] buffer size to be > allocated for $sValName. Will be set to the length of the value name > if the requested value exists even if $sValName isn't successfully set > to the value name. See "Buffer sizes" for more information. > > "$plValName" is $nlen in this function call. > > $nlen is getting changed by the call to RegEnumValue, but is not > getting reset to the MaxValNameLen value (plus 1) for the next call to > RegEnumValue. > > This works OK with ActivePerl 5.18 and Strawberry Perl 5.18, and I > assume earlier versions of both. > > However, it fails with Strawberry Perl 5.20 with this message: > Can't use an undefined value as an ARRAY reference at > c:/Strawberry64/perl/vendor/lib/Win32/TieRegistry.pm line 682. > > In my testing, if I reset $nlen to the value taken from MaxValNameLen, > or just pass null (undef) instead of $nlen, it works OK even with > Strawberry Perl 5.20. > > > > > > > > > [cid:image001.png@01CFEC4C.24180FA0] > > Bruce Reed | Lead Software Engineer - Systems > office/mobile: 989 430 2897 | urgent: > 9894302897@vtext.com<mailto:9894302897@vtext.com> | > bruce.reed@infor.com<mailto:bruce.reed@infor.com> | > http://www.infor.com
This is also a problema with the method SubKeyNames which calls _enumSubKeys. In there, the same thing happens with the while() block calling $self->RegEnumKeyEx; if $namSiz and $clsSiz are reseted to $self->Information('MaxSubKeyLen', 'MaxSubClassLen'), then the error goes away and the function Works properly. Otherwise, it causes the error "Can't use an undefined value as an ARRAY reference at D:/usr/site/lib/Win32/TieRegistry.pm line 718." This is a very simple code case that causes the error: use Win32::TieRegistry (Delimiter => "/", ArrayValues => 0); for my $i ($Registry->{"LMachine/System"}->SubKeyNames) { print "$i\n"; }
On Sat Nov 08 08:57:48 2014, ZARABOZO wrote: Show quoted text
> This is also a problema with the method SubKeyNames which calls > _enumSubKeys. In there, the same thing happens with the while() block > calling $self->RegEnumKeyEx; if $namSiz and $clsSiz are reseted to > $self->Information('MaxSubKeyLen', 'MaxSubClassLen'), then the error > goes away and the function Works properly. Otherwise, it causes the > error "Can't use an undefined value as an ARRAY reference at > D:/usr/site/lib/Win32/TieRegistry.pm line 718." > > This is a very simple code case that causes the error: > > use Win32::TieRegistry (Delimiter => "/", ArrayValues => 0); > for my $i ($Registry->{"LMachine/System"}->SubKeyNames) { > print "$i\n"; > }
The problem is with Win32API::Registry. See some good analysis here: https://rt.perl.org/Public/Bug/Display.html?id=123207 The only solution is to patch Win32API::Registry. The author seems a little unresponsive (see https://rt.cpan.org/Ticket/Display.html?id=37750.) If someone who knows XS would like to offer to take it over I think that would be best.
From: Bruce Reed
The error in TieRegistry.pm is in two places, in _enumValues and _enumSubKeys. The error is caused by incorrect use of input/output length parameters when calling 2 Win32API::Registry functions. Those query functions use the length parameters to allocate a buffer, then return the actual size in those same length parameters. According to the Win32API::Registry description of buffers, those length parameters can be passed as NULL by sending [], then the buffer size will be determined automatically. Since TieRegistry does not use the returned lengthed, it can just pass [] for all the length variables. I have tested this *briefly* and it works in limited testing. I have attached a file with a code snippet showing the fixes. That file also shows other reported bugs that seem to be this same bug; it's been around a while, but seems to hide very well depending on internal details of Perl distributions.
Subject: TieRegistry-fix.txt
=pod Win32API::Registry Explanation of Buffers and buffer sizes http://search.cpan.org/~blm/Win32API-Registry-0.32/Registry.pm#Buffer_sizes Related bug reports: http://community.activestate.com/forum-topic/tieregistry-module-fails http://www.perlmonks.org/?node_id=663433 https://rt.cpan.org/Public/Bug/Display.html?id=25102 https://rt.cpan.org/Public/Bug/Display.html?id=32598 https://rt.cpan.org/Public/Bug/Display.html?id=97127 https://rt.cpan.org/Public/Bug/Display.html?id=99892 =cut sub _enumValues { my $self= shift(@_); $self= tied(%$self) if tied(%$self); my( @names )= (); my $pos= 0; my $name= ""; while( $self->RegEnumValue($pos++,$name,[],[],[],[],[]) ) { push( @names, $name ); } if( ! _NoMoreItems() ) { return (); } $self->{VALUES}= \@names; return 1; } sub ValueNames { my $self= shift(@_); $self= tied(%$self) if tied(%$self); @_ and croak "Usage: \@names= \$key->ValueNames;"; $self->_enumValues unless $self->{VALUES}; return @{$self->{VALUES}}; } sub _enumSubKeys { my $self= shift(@_); $self= tied(%$self) if tied(%$self); my( @subkeys, @classes, @times )= (); my $pos= 0; my( $subkey, $class, $time )= ("","",""); while( $self->RegEnumKeyEx( $pos++, $subkey, [], [], $class, [], $time ) ) { push( @subkeys, $subkey ); push( @classes, $class ); push( @times, $time ); } if( ! _NoMoreItems() ) { return (); } $self->{SUBKEYS}= \@subkeys; $self->{SUBCLASSES}= \@classes; $self->{SUBTIMES}= \@times; return 1; }
From: Bruce Reed
I see that CHORNY has provided version 0.27 which fixes the bug in one of the two places, by resetting the buffer size inputs on each call. (THANK YOU!) _enumSubKeys was fixed, used in SubKeyNames, SubKeyClasses, SubKeyTimes _enumValues remains unfixed, used in ValueNames The same fix could be used in _enumValues, or both functions could be changed to pass [] (NULL) for the length parameters.