Skip Menu |

This queue is for tickets about the Params-Validate CPAN distribution.

Report information
The Basics
Id: 61692
Status: stalled
Priority: 0/
Queue: Params-Validate

People
Owner: Nobody in particular
Requestors: DAMS [...] cpan.org
Cc:
AdminCc:

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



I'm using Params::ValidatePP in conjonction with Log4Perl in this situation : I use Params::Validate from my module Foo, with the option allow_extra => 0. when a parameter validation fails, I catch the DIE signal to log the error to file, using Log4Perl. Log4Perl, in some methods, uses Param::Validate to check parameters, with configuration allow_extra => 1. The clever mechanism to have the Params::Validate configuration per module is short-circuited with this line which appears in multiple places, e.g. in the sub validate (line 213) : local $options = _get_options( (caller(0))[0] ) unless defined $options; In my case, $options is already set, but that's the setting of the original module where the first error originated : Foo. These settings are however used when validating params for a call from Log4Perl. So, settings fro Foo are used instead of settings for Log4Perl. It then crashes, because allow_extra is 0, instead of 1. I think that not using 'local', and passing around the $options variable should fix the issue.
Subject: Re: [rt.cpan.org #61692]
Date: Mon, 27 Sep 2010 09:32:37 -0500 (CDT)
To: Damien Krotkine via RT <bug-Params-Validate [...] rt.cpan.org>
From: Dave Rolsky <autarch [...] urth.org>
On Mon, 27 Sep 2010, Damien Krotkine via RT wrote: Show quoted text
> In my case, $options is already set, but that's the setting of the > original module where the first error originated : Foo. These settings > are however used when validating params for a call from Log4Perl. > > So, settings fro Foo are used instead of settings for Log4Perl. It then > crashes, because allow_extra is 0, instead of 1. > > I think that not using 'local', and passing around the $options variable > should fix the issue.
Can you provide some code that demonstrates the bug? Thanks, -dave /*============================================================ http://VegGuide.org http://blog.urth.org Your guide to all that's veg House Absolute(ly Pointless) ============================================================*/
Sure, here is an example. When you run it, it prints "test foo" once, then dies with "The following parameter was passed in the call to Foo::test_foo but was not listed in the validation options: extra_arg" instead of printing "test foo" twice and printing on STDERR : "The following parameter was passed in the call to Bar::test_bar but was not listed in the validation options: wrong_arg" What the example does is that it calls validate in Bar that dies. The DIE signal is caught, and call validate again in Foo. But validate keeps using the options from Bar. Here is the code ------------------------ # force using ValidatePP.pm BEGIN { $ENV{PV_TEST_PERL}=1 } # this package allows extra parameter package Foo; use Params::Validate qw(validate SCALAR); Params::Validate::validation_options( allow_extra => 1 ); sub test_foo { my %p = validate( @_, { arg1 => { type => SCALAR } } ); print "test foo\n"; } package Bar; use Params::Validate qw(validate SCALAR); Params::Validate::validation_options( allow_extra => 0 ); sub test_bar { # catch die signal local $SIG{__DIE__} = sub { # we died from within Params::Validate (because of wrong_Arg) we call # Foo::test_foo with OK args, but it'll die, because # Params::ValidatePP::options is still set to the options of the Bar # package, and so it won't retreive the one from Foo. Foo::test_foo(arg1 => 1, extra_arg => 2); }; # this will die because the arg received is 'wrong_arg' my %p = validate( @_, { arg1 => { type => SCALAR } } ); } package main; # that works Foo::test_foo(arg1 => 1, extra_arg => 2); # call test_bar with wrong arg Bar::test_bar(wrong_arg => 1); ------------------------ I think the issue is in ValidatePP.pm : ------------------------ sub validate (\@$) { return if $NO_VALIDATION && !defined wantarray; my $p = $_[0]; my $specs = $_[1]; local $options = _get_options( ( caller(0) )[0] ) unless defined $options; ------------------------ This line 'local $options...' is the culprit : it won't retrieve the options again because $options is already set, because the die was issued from Params::Validate iteself. So it reuses the options of the Bar module (no extra params), instead of getting the options of the Foo module (extra params allowed) The bug hit me on a real usage : I have a complicated piece of software that uses Params::Validate(PP) and when it dies (for various reasons), I want to log the issue with Log4Perl then die. Log4Perl uses Params::Validate with extra args enabled, my code doesn't. You could argue that I'm doing too many things in my SIG{__DIE__}, and I guess that would be a valid answer... But I thought this bug should be fixed, and it can be fixed probably easily by not using a local variable. But it's your module :) On my side, I've used a bulk workaround : disable parameter validation in the SIG{__DIE__} closure. Sorry for the long message, dams
Show quoted text
> guess that would be a valid answer... But I thought this bug should be > fixed, and it can be fixed probably easily by not using a local > variable. But it's your module :)
I tried removing the local() and just passing $options around. It fixes your bug but seems to cause others. There's a branch in the Params- Validate repo called fix-recursive-pp-fail if you're interested in taking a look.
Wow, err, this is quite old, I don't remember the context around this, and I'm afraid I'm not using the code anymore. These days I'm more into Log::Dispatch and the XS version of Params::Validate. So feel free to close this bug if nobody else is complaining :)