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