diff options
author | Karl Williamson <khw@cpan.org> | 2015-09-07 10:03:27 -0600 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2015-09-08 10:05:56 -0600 |
commit | 308482c27259302fb2ca8c60b8383609a0e9f314 (patch) | |
tree | 5e15ba76b2ea0b5365c1d8b99a65cc0d6f64d923 /t | |
parent | d8f8a4817f5910267c45439ddb7764b371f06276 (diff) | |
download | perl-308482c27259302fb2ca8c60b8383609a0e9f314.tar.gz |
t/loc_tools.pl: Fix some bugs in locales_enabled()
This code assumed that all locale categories were represented by
non-negative whole numbers. However, it turns out that this assumption
is wrong, as on AIX, LC_ALL is -1. This commit changes our assumption to
take into account that reality; it now assumes that all categories are
larger than a much more negative number, and now the new assumption is
tested for, and if wrong, the code dies instead of silently doing the
wrong thing.
There was also a bug where if a locale category wasn't defined on the
machine, but the corresponding #ifdef for using that category was still
set, the category was improperly assumed to exist
Diffstat (limited to 't')
-rw-r--r-- | t/loc_tools.pl | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/t/loc_tools.pl b/t/loc_tools.pl index 541e08f1b4..86d8e483ea 100644 --- a/t/loc_tools.pl +++ b/t/loc_tools.pl @@ -80,20 +80,38 @@ sub _decode_encodings { # For use only by other functions in this file! return @enc; } +# LC_ALL can be -1 on some platforms. And, in fact the implementors could +# legally use any integer to represent any category. But it makes the most +# sense for them to have used small integers. Below, we create new locale +# numbers for ones missing from this machine. We make them very negative, +# hopefully more negative than anything likely to be a valid category on the +# platform, but also below is a check to be sure that our guess is valid. +my $max_bad_category_number = -1000000; + # Initialize this hash so that it looks like e.g., # 6 => 'CTYPE', # where 6 is the value of &POSIX::LC_CTYPE my %category_name; eval { require POSIX; import POSIX 'locale_h'; }; unless ($@) { - my $number_for_missing_category = 0; + my $number_for_missing_category = $max_bad_category_number; foreach my $name (qw(ALL COLLATE CTYPE MESSAGES MONETARY NUMERIC TIME)) { my $number = eval "&POSIX::LC_$name"; - # Use a negative number if the platform doesn't support this category, - # so we have an entry for all ones that might be specified in calls to - # us. - $number = --$number_for_missing_category if $@; + if ($@) { + # Use a negative number (smaller than any legitimate category + # number) if the platform doesn't support this category, so we + # have an entry for all the ones that might be specified in calls + # to us. + $number = $number_for_missing_category-- if $@; + } + elsif ( $number !~ / ^ -? \d+ $ /x + || $number <= $max_bad_category_number) + { + # We think this should be an int. And it has to be larger than + # any of our synthetic numbers. + die "Unexpected locale category number '$number' for LC_$name" + } $category_name{$number} = "$name"; } @@ -129,19 +147,30 @@ sub locales_enabled(;$) { if (defined $categories_ref) { $categories_ref = [ $categories_ref ] if ! ref $categories_ref; my @local_categories_copy = @$categories_ref; - for my $category (@local_categories_copy) { - if ($category =~ / ^ -? \d+ $ /x) { - die "Invalid locale category number '$category'" - unless grep { $category == $_ } keys %category_name; - $category = $category_name{$category}; + for my $category_name_or_number (@local_categories_copy) { + my $name; + my $number; + if ($category_name_or_number =~ / ^ -? \d+ $ /x) { + $number = $category_name_or_number; + die "Invalid locale category number '$number'" + unless grep { $number == $_ } keys %category_name; + $name = $category_name{$number}; } else { - $category =~ s/ ^ LC_ //x; - die "Invalid locale category name '$category'" - unless grep { $category eq $_ } values %category_name; + $name = $category_name_or_number; + $name =~ s/ ^ LC_ //x; + foreach my $trial (keys %category_name) { + if ($category_name{$trial} eq $name) { + $number = $trial; + last; + } + } + die "Invalid locale category name '$name'" + unless defined $number; } - return 0 if $Config{ccflags} =~ /\bD?NO_LOCALE_$category\b/; + return 0 if $number <= $max_bad_category_number + || $Config{ccflags} =~ /\bD?NO_LOCALE_$name\b/; } } |