From 5d5f168f25e3d826da5cae3add8aa10bd2ea4922 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Wed, 17 Apr 2013 13:35:32 -0700 Subject: [PATCH] Don't clone rule unconditionally in format_rule() Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Chains.pm | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 14a437f31..22a09db9d 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -620,6 +620,7 @@ our %opttype = ( rule => CONTROL, cmdlevel => CONTROL, simple => CONTROL, matches => CONTROL, + complex => CONTROL, i => UNIQUE, s => UNIQUE, @@ -813,6 +814,7 @@ sub set_rule_option( $$$ ) { push @{$ruleref->{$option}}, ( reftype $value ? @$value : $value ); push @{$ruleref->{matches}}, $option; + $ruleref->{complex} = 1; } else { assert( ! reftype $value ); $ruleref->{$option} = join(' ', $value1, $value ) unless $value1 eq $value; @@ -964,19 +966,21 @@ sub pop_match( $$ ) { my ( $ruleref, $option ) = @_; my $value = $ruleref->{$option}; - $value = shift @{$ruleref->{$option}} if reftype $value; - - $value; + reftype $value ? shift @{$ruleref->{$option}} : $value; } +sub clone_rule( $ ); + sub format_rule( $$;$ ) { my ( $chainref, $rulerefp, $suppresshdr ) = @_; return $rulerefp->{cmd} if exists $rulerefp->{cmd}; my $rule = $suppresshdr ? '' : "-A $chainref->{name}"; - - my $ruleref = clone_rule( $rulerefp ); + # + # The code the follows can be destructive of the rule so we clone it + # + my $ruleref = $rulerefp->{complex} ? clone_rule( $rulerefp ) : $rulerefp; for ( @unique_options ) { if ( exists $ruleref->{$_} ) { @@ -996,8 +1000,8 @@ sub format_rule( $$;$ ) { if ( defined ( my $state = $ruleref->{'conntrack --ctstate'} ) ) { $rule .= format_option( 'conntrack --ctstate' , $state ); - } elsif ( defined $ruleref->{state} ) { - $rule .= format_option( 'state', $ruleref->{state} ); + } elsif ( defined ( $state = $ruleref->{state} ) ) { + $rule .= format_option( 'state', $state ); } for ( grep ! $opttype{$_}, @{$ruleref->{matches}} ) { @@ -1331,6 +1335,7 @@ sub push_matches { $ruleref->{$option} = [ $curvalue ] unless reftype $curvalue; push @{$ruleref->{$option}}, reftype $value ? @$value : $value; push @{$ruleref->{matches}}, $option; + $ruleref->{complex} = 1; } else { $ruleref->{$option} = join( '', $curvalue, $value ); }