Skip to content

Commit

Permalink
Sort hash keys before iterating over them, for deterministic behaviou…
Browse files Browse the repository at this point in the history
…r. (#246)

* Sort hash keys before iterating over them, for deterministic behaviour.

* _set_values_and_labels: here too sort keys for deterministic behaviour.

Co-authored-by: Ed Avis <ed.avis@qmaw.com>
  • Loading branch information
Ed Avis and Ed Avis authored May 4, 2021
1 parent 40e0c3f commit 6b89d87
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 14 deletions.
4 changes: 4 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
(upcoming) 2021-03-18
[ FIX ]
- sort hash keys for deterministic behaviour (GH #245)

4.51 2020-10-01

[ DOCUMENTATION ]
Expand Down
28 changes: 14 additions & 14 deletions lib/CGI.pm
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ sub import {
# To allow overriding, search through the packages
# Till we find one in which the correct subroutine is defined.
my @packages = ($self,@{"$self\:\:ISA"});
for $sym (keys %EXPORT) {
for $sym (sort keys %EXPORT) {
my $pck;
my $def = $DefaultClass;
for $pck (@packages) {
Expand Down Expand Up @@ -609,7 +609,7 @@ sub init {
last METHOD;
}
if (ref($initializer) && ref($initializer) eq 'HASH') {
for (keys %$initializer) {
for (sort keys %$initializer) {
$self->param('-name'=>$_,'-value'=>$initializer->{$_});
}
last METHOD;
Expand Down Expand Up @@ -1155,7 +1155,7 @@ sub import_names {
die "Can't import names into \"main\"\n" if \%{"${namespace}::"} == \%::;
if ($delete || $MOD_PERL || exists $ENV{'FCGI_ROLE'}) {
# can anyone find an easier way to do this?
for (keys %{"${namespace}::"}) {
for (sort keys %{"${namespace}::"}) {
local *symbol = "${namespace}::${_}";
undef $symbol;
undef @symbol;
Expand Down Expand Up @@ -1428,7 +1428,7 @@ sub save {
if length($escaped_param) or length($value);
}
}
for (keys %{$self->{'.fieldnames'}}) {
for (sort keys %{$self->{'.fieldnames'}}) {
print $filehandle ".cgifields=",escape("$_"),"\n";
}
print $filehandle "=\n"; # end of record
Expand Down Expand Up @@ -2456,7 +2456,7 @@ sub popup_menu {
if (/<optgroup/) {
for my $v (split(/\n/)) {
my $selectit = $XHTML ? 'selected="selected"' : 'selected';
for my $selected (keys %selected) {
for my $selected (sort keys %selected) {
$v =~ s/(value="\Q$selected\E")/$selectit $1/;
}
$result .= "$v\n";
Expand Down Expand Up @@ -2578,7 +2578,7 @@ sub scrolling_list {
if (/<optgroup/) {
for my $v (split(/\n/)) {
my $selectit = $XHTML ? 'selected="selected"' : 'selected';
for my $selected (keys %selected) {
for my $selected (sort keys %selected) {
$v =~ s/(value="$selected")/$selectit $1/;
}
$result .= "$v\n";
Expand Down Expand Up @@ -2943,7 +2943,7 @@ sub query_string {
push(@pairs,"$eparam=$value");
}
}
for (keys %{$self->{'.fieldnames'}}) {
for (sort keys %{$self->{'.fieldnames'}}) {
push(@pairs,".cgifields=".escape("$_"));
}
return join($USE_PARAM_SEMICOLONS ? ';' : '&',@pairs);
Expand Down Expand Up @@ -2991,7 +2991,7 @@ sub Accept {
return $prefs{$search} if $prefs{$search};

# Didn't get it, so try pattern matching.
for (keys %prefs) {
for (sort keys %prefs) {
next unless /\*/; # not a pattern match
($pat = $_) =~ s/([^\w*])/\\$1/g; # escape meta characters
$pat =~ s/\*/.*/g; # turn it into a pattern
Expand Down Expand Up @@ -3144,7 +3144,7 @@ sub http {
}
return $ENV{"HTTP_$parameter"};
}
return grep { /^HTTP(?:_|$)/ } keys %ENV;
return grep { /^HTTP(?:_|$)/ } sort keys %ENV;
}

#### Method: https
Expand All @@ -3162,7 +3162,7 @@ sub https {
return $ENV{"HTTPS_$parameter"};
}
return wantarray
? grep { /^HTTPS(?:_|$)/ } keys %ENV
? grep { /^HTTPS(?:_|$)/ } sort keys %ENV
: $ENV{'HTTPS'};
}

Expand Down Expand Up @@ -3293,7 +3293,7 @@ sub register_parameter {
sub get_fields {
my($self) = @_;
return $self->CGI::hidden('-name'=>'.cgifields',
'-values'=>[keys %{$self->{'.parametersToAdd'}}],
'-values'=>[sort keys %{$self->{'.parametersToAdd'}}],
'-override'=>1);
}

Expand Down Expand Up @@ -3415,7 +3415,7 @@ sub read_multipart {
# together with the body for later parsing with an external
# MIME parser module
if ( $multipart ) {
for ( keys %header ) {
for ( sort keys %header ) {
print $filehandle "$_: $header{$_}${CRLF}";
}
print $filehandle "${CRLF}";
Expand Down Expand Up @@ -3624,7 +3624,7 @@ sub _set_values_and_labels {
$$l = $v if ref($v) eq 'HASH' && !ref($$l);
return $self->param($n) if !defined($v);
return $v if !ref($v);
return ref($v) eq 'HASH' ? keys %$v : @$v;
return ref($v) eq 'HASH' ? sort keys %$v : @$v;
}

# internal routine, don't use
Expand All @@ -3633,7 +3633,7 @@ sub _set_attributes {
my($element, $attributes) = @_;
return '' unless defined($attributes->{$element});
$attribs = ' ';
for my $attrib (keys %{$attributes->{$element}}) {
for my $attrib (sort keys %{$attributes->{$element}}) {
(my $clean_attrib = $attrib) =~ s/^-//;
$attribs .= "@{[lc($clean_attrib)]}=\"$attributes->{$element}{$attrib}\" ";
}
Expand Down

0 comments on commit 6b89d87

Please sign in to comment.