Subject: | Config lines with key but no value cause problems with undefined values (see 42721) |
(something of a continuation of bug report 42721)
Bug report 42721 asked that config lines with no value should be handled
so that that input situation could be 'seen' by the calling program.
Previously, undefined values were replaced with empty strings.
At least one part of the fix for 42721 confused things in routine
Config::General::_parse_value(), in that undefined values could now hit
code that would try to use these values if various options were turned
on e.g. InterPolateVars, AutoTrue, FlagBits . This is what Yves was
concerned about in his comments to that bug.
It would seem that trying to use an undefined value with any of those
options should not be done. Rather, if the routine sees an undefined
input value _parse_value() should just return it unmodified. This
avoids various "uninitialized value" warnings within that routine.
Separately, trying to save a config that contains undefined values can
also cause "uninitialized value" warnings within one of the output
routines, _write_scalar(). Again, rather than trying to use the
undefined value in various formatting tests, this situation should just
cause the immediate output of a config line with key and no value.
Attached is a test file that demonstrates both "uninitialized value"
warning situations. Also attached is a patch file for General.pm that
fixes both the _parse_value() and _write_scalar() routines.
Before I looked at _parse_value() I had noticed "uninitialized value"
warnings generated within _interpolate() and had put in a "return if !
defined $value;" at the start of that routine. But it seems that if
_parse_value() is patched as suggested then this check in _interpolate()
is unneeded. I've attached the Interpolated.pm patch for reference.
Finally, note that because Config::General::Interpolated does not have a
"use warnings;" statement, these "uninitialized value" warnings are not
seen unless the calling program has turned on warnings using "perl -w".
But I think almost everyone does so it would be good to apply this patch.
Subject: | General.pm.undef_values.patch |
--- General.pm.original 2009-09-07 14:49:55.000000000 -0500
+++ General.pm 2010-02-12 23:17:17.896237100 -0600
@@ -1039,9 +1039,9 @@
#
my($this, $config, $option, $value) =@_;
- # avoid "Use of uninitialized value"
if (! defined $value) {
- $value = undef; # bigfix rt.cpan.org#42721 q();
+ # Return an input undefined value without trying transformations
+ return $value;
}
if ($this->{InterPolateVars}) {
@@ -1253,7 +1253,10 @@
my $config_string;
- if ($line =~ /\n/ || $line =~ /\\$/) {
+ if ( ! defined $line ) {
+ $config_string .= $indent . $entry . "\n";
+ }
+ elsif ($line =~ /\n/ || $line =~ /\\$/) {
# it is a here doc
my $delimiter;
my $tmplimiter = 'EOF';
Subject: | 90_RTxxxxx_undef_values.t |
# This test relates to the following bug report
# CPAN RT bug report #42721
# https://rt.cpan.org/Public/Bug/Display.html?id=42721
# Fri Jan 23 09:49:06 2009 Frank Bicknell - Ticket created
# Subject: Config items with no values should return undef
use warnings;
use strict;
#use Test::More tests => 2;
use Test::More qw(no_plan);
use Data::Dumper;
# Our helpers for testing
sub diagf { diag sprintf $_[0], @_[1..$#_] }
sub VoU { defined $_[0] ? $_[0] : '<undef>'; }
my $debug_here = 0;
BEGIN { use_ok 'Config::General' };
#------------------------------------------------------------------
# A test config that contains a line with no value
my $config_source_text = <<'END_OF_CONFIG';
FOO
END_OF_CONFIG
# - - - - - - - - - - - - - -
# We need to demonstrate the uninitialized warnings as would be
# seen when a program is executed with "perl -w". The way
# to simulate that is to set a special variable.
$^W = 1;
# - - - - - - - - - - - - - -
# Process config containing line with no value - should be undef
my( $cfgo, %config, $config_value );
$cfgo = Config::General->new(
-String => $config_source_text,
);
%config = $cfgo->getall;
ok( exists $config{FOO},
q{config value found for input source key} );
$config_value = $config{FOO};
diagf " ( we see config_value as '%s' )\n", VoU($config_value) if $debug_here;
#ok( ! defined $config_value,
# q{config value returned as expected} );
is( $config_value, undef,
q{config value returned as expected} );
# - - - - - - - - - - - - - -
# Process config containing line with no value - should be undef
# Add the -InterPolateVars option
$cfgo = Config::General->new(
-String => $config_source_text,
-InterPolateVars => 1,
);
%config = $cfgo->getall;
ok( exists $config{FOO},
q{config value found for input source key} );
$config_value = $config{FOO};
diagf " ( we see config_value as '%s' )\n", VoU($config_value) if $debug_here;
#ok( ! defined $config_value,
# q{config value returned as expected} );
is( $config_value, undef,
q{config value returned as expected} );
# Use of uninitialized value $value in substitution (s///) at C:/strawberry/perl/site/lib/Config/General/Interpolated.pm line 74.
# Use of uninitialized value $value in substitution (s///) at C:/strawberry/perl/site/lib/Config/General/Interpolated.pm line 80.
# - - - - - - - - - - - - - -
my $sorted_save_string = $cfgo->save_string();
ok( defined $sorted_save_string, 'save_string() sorted' );
diag( Data::Dumper->Dump([ \$sorted_save_string ], [qw{ *sorted_save }]) )
if $debug_here;
# Use of uninitialized value $line in pattern match (m//) at C:/strawberry/perl/site/lib/Config/General.pm line 1256.
# Use of uninitialized value $line in pattern match (m//) at C:/strawberry/perl/site/lib/Config/General.pm line 1256.
# Use of uninitialized value $line in substitution (s///) at C:/strawberry/perl/site/lib/Config/General.pm line 1278.
# Use of uninitialized value $line in pattern match (m//) at C:/strawberry/perl/site/lib/Config/General.pm line 1280.
# Use of uninitialized value $line in pattern match (m//) at C:/strawberry/perl/site/lib/Config/General.pm line 1280.
# Use of uninitialized value $line in concatenation (.) or string at C:/strawberry/perl/site/lib/Config/General.pm line 1284.
# - - - - - - - - - - - - - -
__END__
# vim:ft=perl:ts=4:sw=4:et:is:hls:ss=10:
Subject: | Interpolated.pm.undef_values.patch |
--- Interpolated.pm.original 2009-07-19 15:04:51.000000000 -0500
+++ Interpolated.pm 2010-02-12 22:40:35.233134200 -0600
@@ -66,6 +66,8 @@
#
my ($this, $config, $key, $value) = @_;
+ return if ! defined $value;
+
# some dirty trick to circumvent single quoted vars to be interpolated
# we remove all quotes and replace them with unique random literals,
# which will be replaced after interpolation with the original quotes