Skip Menu |

This queue is for tickets about the Config-Any CPAN distribution.

Report information
The Basics
Id: 104079
Status: resolved
Priority: 0/
Queue: Config-Any

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

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



Subject: File parse errors silently ignored in v0.25
Prior to the v0.25 release, attempting to load a file that had parse errors, such as invalid YAML or JSON used to die with the appropriate parse error. There has been a change in behaviour with the v0.25 release. Loading such files no longer dies, the parse error is no longer reported and load_files returns undef. Since this is typically used to load configuration files, knowing your configuration is broken due to a parse error is very important. Reporting this ASAP and as loudly as possible is my preferred approach :)
This looks like its a regression caused by localising $@. Attached is a patch (with amended tests) that restores the throwing of a fatal error if load() generates an error and extension matching was used. Cheers, Russell.
Subject: bugfix_invalid_parse_errors.patch
From cfacf1cec779e9edb0bd24e8f2374e3f4cae1ca5 Mon Sep 17 00:00:00 2001 From: Russell Jenkins <veryrusty@gmail.com> Date: Wed, 29 Apr 2015 10:48:45 +1000 Subject: [PATCH 1/2] Test load_files throws parse errors when use_ext=1 Piggyback off existing tests for invalid config files to verify a parse error is thrown when the config is invalid and use_ext => 1. --- t/50-general.t | 12 +++++++++++- t/51-ini.t | 12 +++++++++++- t/52-json.t | 12 +++++++++++- t/53-perl.t | 13 +++++++++++-- t/54-xml.t | 13 ++++++++++++- t/55-yaml.t | 12 +++++++++++- 6 files changed, 67 insertions(+), 7 deletions(-) diff --git a/t/50-general.t b/t/50-general.t index cc7d6f8..5361ca2 100644 --- a/t/50-general.t +++ b/t/50-general.t @@ -2,13 +2,14 @@ use strict; use warnings; use Test::More; +use Config::Any; use Config::Any::General; if ( !Config::Any::General->is_supported ) { plan skip_all => 'Config::General format not supported'; } else { - plan tests => 7; + plan tests => 9; } { @@ -38,3 +39,12 @@ else { ok( !$config, 'config load failed' ); ok( $@, "error thrown ($@)" ); } + +# parse error generated on invalid config +{ + my $file = 't/invalid/conf.conf'; + my $config = eval { Config::Any->load_files( { files => [$file], use_ext => 1} ) }; + + ok( !$config, 'config load failed' ); + ok( $@, "error thrown ($@)" ); +} diff --git a/t/51-ini.t b/t/51-ini.t index 1fea544..c85ab27 100644 --- a/t/51-ini.t +++ b/t/51-ini.t @@ -2,13 +2,14 @@ use strict; use warnings; use Test::More; +use Config::Any; use Config::Any::INI; if ( !Config::Any::INI->is_supported ) { plan skip_all => 'INI format not supported'; } else { - plan tests => 13; + plan tests => 15; } { @@ -55,3 +56,12 @@ else { ok( !$config, 'config load failed' ); ok( $@, "error thrown ($@)" ); } + +# parse error generated on invalid config +{ + my $file = 't/invalid/conf.ini'; + my $config = eval { Config::Any->load_files( { files => [$file], use_ext => 1} ) }; + + ok( !$config, 'config load failed' ); + ok( $@, "error thrown ($@)" ); +} diff --git a/t/52-json.t b/t/52-json.t index 65c6099..555e74e 100644 --- a/t/52-json.t +++ b/t/52-json.t @@ -2,13 +2,14 @@ use strict; use warnings; use Test::More; +use Config::Any; use Config::Any::JSON; if ( !Config::Any::JSON->is_supported ) { plan skip_all => 'JSON format not supported'; } else { - plan tests => 4; + plan tests => 6; } { @@ -25,3 +26,12 @@ else { ok( !$config, 'config load failed' ); ok( $@, "error thrown ($@)" ); } + +# parse error generated on invalid config +{ + my $file = 't/invalid/conf.json'; + my $config = eval { Config::Any->load_files( { files => [$file], use_ext => 1} ) }; + + ok( !$config, 'config load failed' ); + ok( $@, "error thrown ($@)" ); +} diff --git a/t/53-perl.t b/t/53-perl.t index 5ad0468..1a749a1 100644 --- a/t/53-perl.t +++ b/t/53-perl.t @@ -1,8 +1,8 @@ use strict; use warnings; -use Test::More tests => 5; - +use Test::More tests => 7; +use Config::Any; use Config::Any::Perl; { @@ -24,3 +24,12 @@ use Config::Any::Perl; ok( !$config, 'config load failed' ); ok( $@, "error thrown ($@)" ); } + +# parse error generated on invalid config +{ + my $file = 't/invalid/conf.pl'; + my $config = eval { Config::Any->load_files( { files => [$file], use_ext => 1} ) }; + + ok( !$config, 'config load failed' ); + ok( $@, "error thrown ($@)" ); +} diff --git a/t/54-xml.t b/t/54-xml.t index 45fd66e..0d546cb 100644 --- a/t/54-xml.t +++ b/t/54-xml.t @@ -2,13 +2,14 @@ use strict; use warnings; use Test::More; +use Config::Any; use Config::Any::XML; if ( !Config::Any::XML->is_supported ) { plan skip_all => 'XML format not supported'; } else { - plan tests => 6; + plan tests => 8; } { @@ -39,3 +40,13 @@ SKIP: { ok( $config, 'config loaded' ); ok( !$@, 'no error thrown' ); } + +# parse error generated on invalid config +{ + my $file = 't/invalid/conf.xml'; + my $config = eval { Config::Any->load_files( { files => [$file], use_ext => 1} ) }; + + ok( !$config, 'config load failed' ); + ok( $@, "error thrown ($@)" ); +} + diff --git a/t/55-yaml.t b/t/55-yaml.t index 7b7b5bc..b6d1f9e 100644 --- a/t/55-yaml.t +++ b/t/55-yaml.t @@ -3,13 +3,14 @@ use warnings; no warnings 'once'; use Test::More; +use Config::Any; use Config::Any::YAML; if ( !Config::Any::YAML->is_supported ) { plan skip_all => 'YAML format not supported'; } else { - plan tests => 4; + plan tests => 6; } { @@ -26,3 +27,12 @@ else { ok( !$config, 'config load failed' ); ok( $@, "error thrown ($@)" ); } + +# parse error generated on invalid config +{ + my $file = 't/invalid/conf.yml'; + my $config = eval { Config::Any->load_files( { files => [$file], use_ext => 1} ) }; + + ok( !$config, 'config load failed' ); + ok( $@, "error thrown ($@)" ); +} -- 2.2.1 From 38bd1c62c47857ac18a0b698442e84e2d68e222e Mon Sep 17 00:00:00 2001 From: Russell Jenkins <veryrusty@gmail.com> Date: Wed, 29 Apr 2015 10:49:14 +1000 Subject: [PATCH 2/2] Capture file load errors for later use. Localizing $@ also implies that any load error wasn't available outside of the do block. Instead of always returning 1, return $@ so any error is captured. The error is then rethrown if use_ext is enabled. --- lib/Config/Any.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Config/Any.pm b/lib/Config/Any.pm index 7bdf2a6..2c2bc41 100644 --- a/lib/Config/Any.pm +++ b/lib/Config/Any.pm @@ -195,15 +195,15 @@ sub _load { next unless $loader->is_supported; $supported = 1; my @configs; - my $ok = do { + my $err = do { local $@; @configs = eval { $loader->load( $filename, $loader_args{ $loader } ); }; - 1; + $@; }; # fatal error if we used extension matching - croak "Error parsing $filename: $@" if !$ok and $use_ext_lut; - next if !$ok or !@configs; + croak "Error parsing $filename: $err" if $err and $use_ext_lut; + next if $err or !@configs; # post-process config with a filter callback if ( $args->{ filter } ) { -- 2.2.1
Thanks so much for the patch! I've applied it and shipped version 0.26. Cheers, -Brian