← Index
NYTProf Performance Profile   « line view »
For /usr/local/bin/sa-learn
  Run on Tue Nov 7 05:38:10 2017
Reported on Tue Nov 7 06:16:01 2017

Filename/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf/Parser.pm
StatementsExecuted 1032660 statements in 8.40s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
13832214.04s5.51sMail::SpamAssassin::Conf::Parser::::_meta_deps_recurseMail::SpamAssassin::Conf::Parser::_meta_deps_recurse (recurses: max depth 7, inclusive time 11.1s)
1111.51s4.55sMail::SpamAssassin::Conf::Parser::::parseMail::SpamAssassin::Conf::Parser::parse
3226112811.23s1.23sMail::SpamAssassin::Conf::Parser::::CORE:matchMail::SpamAssassin::Conf::Parser::CORE:match (opcode)
92819211277ms277msMail::SpamAssassin::Conf::Parser::::CORE:substMail::SpamAssassin::Conf::Parser::CORE:subst (opcode)
2074153191ms703msMail::SpamAssassin::Conf::Parser::::add_testMail::SpamAssassin::Conf::Parser::add_test
46511181ms240msMail::SpamAssassin::Conf::Parser::::is_meta_validMail::SpamAssassin::Conf::Parser::is_meta_valid
50821148ms215msMail::SpamAssassin::Conf::Parser::::handle_conditionalMail::SpamAssassin::Conf::Parser::handle_conditional
1504661137ms137msMail::SpamAssassin::Conf::Parser::::CORE:regcompMail::SpamAssassin::Conf::Parser::CORE:regcomp (opcode)
111116ms121msMail::SpamAssassin::Conf::Parser::::set_default_scoresMail::SpamAssassin::Conf::Parser::set_default_scores
122811108ms214msMail::SpamAssassin::Conf::Parser::::is_regexp_validMail::SpamAssassin::Conf::Parser::is_regexp_valid
111105ms125msMail::SpamAssassin::Conf::Parser::::fix_prioritiesMail::SpamAssassin::Conf::Parser::fix_priorities
11195.7ms6.05sMail::SpamAssassin::Conf::Parser::::finish_parsingMail::SpamAssassin::Conf::Parser::finish_parsing
11194.5ms98.0msMail::SpamAssassin::Conf::Parser::::find_dup_rulesMail::SpamAssassin::Conf::Parser::find_dup_rules
11159.5ms139msMail::SpamAssassin::Conf::Parser::::check_for_missing_descriptionsMail::SpamAssassin::Conf::Parser::check_for_missing_descriptions
12761148.8ms262msMail::SpamAssassin::Conf::Parser::::set_hash_key_valueMail::SpamAssassin::Conf::Parser::set_hash_key_value
12284337.0ms258msMail::SpamAssassin::Conf::Parser::::is_delimited_regexp_validMail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid
3791135.5ms42.2msMail::SpamAssassin::Conf::Parser::::pack_eval_methodMail::SpamAssassin::Conf::Parser::pack_eval_method
11130.7ms5.54sMail::SpamAssassin::Conf::Parser::::trace_meta_dependenciesMail::SpamAssassin::Conf::Parser::trace_meta_dependencies
112120.1ms20.1msMail::SpamAssassin::Conf::Parser::::CORE:sortMail::SpamAssassin::Conf::Parser::CORE:sort (opcode)
34119.29ms10.1msMail::SpamAssassin::Conf::Parser::::add_to_addrlistMail::SpamAssassin::Conf::Parser::add_to_addrlist
102227.89ms10.3msMail::SpamAssassin::Conf::Parser::::add_to_addrlist_rcvdMail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd
58114.63ms30.0msMail::SpamAssassin::Conf::Parser::::fix_path_relative_to_current_fileMail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file
43443433.93ms3.93msMail::SpamAssassin::Conf::Parser::::cond_clause_plugin_loadedMail::SpamAssassin::Conf::Parser::cond_clause_plugin_loaded
16113.89ms3.89msMail::SpamAssassin::Conf::Parser::::build_command_lutsMail::SpamAssassin::Conf::Parser::build_command_luts
55112.61ms4.18msMail::SpamAssassin::Conf::Parser::::cond_clause_can_or_hasMail::SpamAssassin::Conf::Parser::cond_clause_can_or_has
16112.08ms2.08msMail::SpamAssassin::Conf::Parser::::set_defaults_from_command_listMail::SpamAssassin::Conf::Parser::set_defaults_from_command_list
479211.67ms1.67msMail::SpamAssassin::Conf::Parser::::CORE:substcontMail::SpamAssassin::Conf::Parser::CORE:substcont (opcode)
8311968µs9.28msMail::SpamAssassin::Conf::Parser::::add_to_addrlist_dkimMail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim
3411912µs11.1msMail::SpamAssassin::Conf::Parser::::set_addrlist_valueMail::SpamAssassin::Conf::Parser::set_addrlist_value
161616889µs6.86msMail::SpamAssassin::Conf::Parser::::register_commandsMail::SpamAssassin::Conf::Parser::register_commands
551414829µs5.01msMail::SpamAssassin::Conf::Parser::::cond_clause_canMail::SpamAssassin::Conf::Parser::cond_clause_can
1711512µs559µsMail::SpamAssassin::Conf::Parser::::set_template_appendMail::SpamAssassin::Conf::Parser::set_template_append
2111492µs492µsMail::SpamAssassin::Conf::Parser::::setup_default_code_cbMail::SpamAssassin::Conf::Parser::setup_default_code_cb
511217µs231µsMail::SpamAssassin::Conf::Parser::::set_bool_valueMail::SpamAssassin::Conf::Parser::set_bool_value
411202µs425µsMail::SpamAssassin::Conf::Parser::::set_numeric_valueMail::SpamAssassin::Conf::Parser::set_numeric_value
31180µs89µsMail::SpamAssassin::Conf::Parser::::set_string_valueMail::SpamAssassin::Conf::Parser::set_string_value
11150µs50µsMail::SpamAssassin::Conf::Parser::::BEGIN@137Mail::SpamAssassin::Conf::Parser::BEGIN@137
21145µs45µsMail::SpamAssassin::Conf::Parser::::set_template_clearMail::SpamAssassin::Conf::Parser::set_template_clear
11142µs98µsMail::SpamAssassin::Conf::Parser::::BEGIN@592Mail::SpamAssassin::Conf::Parser::BEGIN@592
11141µs374µsMail::SpamAssassin::Conf::Parser::::BEGIN@140Mail::SpamAssassin::Conf::Parser::BEGIN@140
11130µs30µsMail::SpamAssassin::Conf::Parser::::newMail::SpamAssassin::Conf::Parser::new
11126µs243µsMail::SpamAssassin::Conf::Parser::::BEGIN@139Mail::SpamAssassin::Conf::Parser::BEGIN@139
11126µs88µsMail::SpamAssassin::Conf::Parser::::BEGIN@146Mail::SpamAssassin::Conf::Parser::BEGIN@146
11121µs21µsMail::SpamAssassin::Conf::Parser::::lint_trusted_networksMail::SpamAssassin::Conf::Parser::lint_trusted_networks
11120µs30µsMail::SpamAssassin::Conf::Parser::::BEGIN@143Mail::SpamAssassin::Conf::Parser::BEGIN@143
11120µs53µsMail::SpamAssassin::Conf::Parser::::BEGIN@144Mail::SpamAssassin::Conf::Parser::BEGIN@144
11119µs26µsMail::SpamAssassin::Conf::Parser::::BEGIN@145Mail::SpamAssassin::Conf::Parser::BEGIN@145
11119µs700µsMail::SpamAssassin::Conf::Parser::::BEGIN@138Mail::SpamAssassin::Conf::Parser::BEGIN@138
11117µs111µsMail::SpamAssassin::Conf::Parser::::BEGIN@148Mail::SpamAssassin::Conf::Parser::BEGIN@148
11114µs14µsMail::SpamAssassin::Conf::Parser::::BEGIN@141Mail::SpamAssassin::Conf::Parser::BEGIN@141
11112µs12µsMail::SpamAssassin::Conf::Parser::::lint_checkMail::SpamAssassin::Conf::Parser::lint_check
0000s0sMail::SpamAssassin::Conf::Parser::::add_regression_testMail::SpamAssassin::Conf::Parser::add_regression_test
0000s0sMail::SpamAssassin::Conf::Parser::::cond_clause_hasMail::SpamAssassin::Conf::Parser::cond_clause_has
0000s0sMail::SpamAssassin::Conf::Parser::::get_if_stack_as_stringMail::SpamAssassin::Conf::Parser::get_if_stack_as_string
0000s0sMail::SpamAssassin::Conf::Parser::::is_always_matching_regexpMail::SpamAssassin::Conf::Parser::is_always_matching_regexp
0000s0sMail::SpamAssassin::Conf::Parser::::lint_warnMail::SpamAssassin::Conf::Parser::lint_warn
0000s0sMail::SpamAssassin::Conf::Parser::::remove_addrlist_valueMail::SpamAssassin::Conf::Parser::remove_addrlist_value
0000s0sMail::SpamAssassin::Conf::Parser::::remove_from_addrlistMail::SpamAssassin::Conf::Parser::remove_from_addrlist
0000s0sMail::SpamAssassin::Conf::Parser::::remove_from_addrlist_dkimMail::SpamAssassin::Conf::Parser::remove_from_addrlist_dkim
0000s0sMail::SpamAssassin::Conf::Parser::::remove_from_addrlist_rcvdMail::SpamAssassin::Conf::Parser::remove_from_addrlist_rcvd
0000s0sMail::SpamAssassin::Conf::Parser::::set_duration_valueMail::SpamAssassin::Conf::Parser::set_duration_value
0000s0sMail::SpamAssassin::Conf::Parser::::set_ipaddr_listMail::SpamAssassin::Conf::Parser::set_ipaddr_list
0000s0sMail::SpamAssassin::Conf::Parser::::set_no_valueMail::SpamAssassin::Conf::Parser::set_no_value
0000s0sMail::SpamAssassin::Conf::Parser::::set_string_listMail::SpamAssassin::Conf::Parser::set_string_list
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# <@LICENSE>
2# Licensed to the Apache Software Foundation (ASF) under one or more
3# contributor license agreements. See the NOTICE file distributed with
4# this work for additional information regarding copyright ownership.
5# The ASF licenses this file to you under the Apache License, Version 2.0
6# (the "License"); you may not use this file except in compliance with
7# the License. You may obtain a copy of the License at:
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16# </@LICENSE>
17
18=head1 NAME
19
20Mail::SpamAssassin::Conf::Parser - parse SpamAssassin configuration
21
22=head1 SYNOPSIS
23
24 (see Mail::SpamAssassin)
25
26=head1 DESCRIPTION
27
28Mail::SpamAssassin is a module to identify spam using text analysis and
29several internet-based realtime blacklists.
30
31This class is used internally by SpamAssassin to parse its configuration files.
32Please refer to the C<Mail::SpamAssassin> documentation for public interfaces.
33
34=head1 STRUCTURE OF A CONFIG BLOCK
35
36This is the structure of a config-setting block. Each is a hashref which may
37contain these keys:
38
39=over 4
40
41=item setting
42
43the name of the setting it modifies, e.g. "required_score". this also doubles
44as the default for 'command' (below). THIS IS REQUIRED.
45
46=item command
47
48The command string used in the config file for this setting. Optional;
49'setting' will be used for the command if this is omitted.
50
51=item aliases
52
53An [aryref] of other aliases for the same command. optional.
54
55=item type
56
57The type of this setting:
58
59 - $CONF_TYPE_NOARGS: must not have any argument, like "clear_headers"
60 - $CONF_TYPE_STRING: string
61 - $CONF_TYPE_NUMERIC: numeric value (float or int)
62 - $CONF_TYPE_BOOL: boolean (0/no or 1/yes)
63 - $CONF_TYPE_TEMPLATE: template, like "report"
64 - $CONF_TYPE_ADDRLIST: list of mail addresses, like "whitelist_from"
65 - $CONF_TYPE_HASH_KEY_VALUE: hash key/value pair, like "describe" or tflags
66 - $CONF_TYPE_STRINGLIST list of strings, stored as an array
67 - $CONF_TYPE_IPADDRLIST list of IP addresses, stored as an array of SA::NetSet
68 - $CONF_TYPE_DURATION a nonnegative time interval in seconds - a numeric value
69 (float or int), optionally suffixed by a time unit (s, m,
70 h, d, w), seconds are implied if unit is missing
71
72If this is set, and a 'code' block does not already exist, a 'code' block is
73assigned based on the type.
74
75In addition, the SpamAssassin test suite will validate that the settings
76do not 'leak' between users.
77
78Note that C<$CONF_TYPE_HASH_KEY_VALUE>-type settings require that the
79value be non-empty, otherwise they'll produce a warning message.
80
81=item code
82
83A subroutine to deal with the setting. ONE OF B<code> OR B<type> IS REQUIRED.
84The arguments passed to the function are C<($self, $key, $value, $line)>,
85where $key is the setting (*not* the command), $value is the value string,
86and $line is the entire line.
87
88There are two special return values that the B<code> subroutine may return
89to signal that there is an error in the configuration:
90
91C<$Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE> -- this setting requires
92that a value be set, but one was not provided.
93
94C<$Mail::SpamAssassin::Conf::INVALID_VALUE> -- this setting requires a value
95from a set of 'valid' values, but the user provided an invalid one.
96
97C<$Mail::SpamAssassin::Conf::INVALID_HEADER_FIELD_NAME> -- this setting
98requires a syntactically valid header field name, but the user provided
99an invalid one.
100
101Any other values -- including C<undef> -- returned from the subroutine are
102considered to mean 'success'.
103
104It is good practice to set a 'type', if possible, describing how your settings
105are stored on the Conf object; this allows the SpamAssassin test suite to
106validate that the settings do not 'leak' between users.
107
108=item default
109
110The default value for the setting. may be omitted if the default value is a
111non-scalar type, which should be set in the Conf ctor. note for path types:
112using "__userstate__" is recommended for defaults, as it allows
113Mail::SpamAssassin module users who set that configuration setting, to receive
114the correct values.
115
116=item is_priv
117
118Set to 1 if this setting requires 'allow_user_rules' when run from spamd.
119
120=item is_admin
121
122Set to 1 if this setting can only be set in the system-wide config when run
123from spamd. (All settings can be used by local programs run directly by the
124user.)
125
126=item is_frequent
127
128Set to 1 if this value occurs frequently in the config. this means it's looked
129up first for speed.
130
131=back
132
133=cut
134
135package Mail::SpamAssassin::Conf::Parser;
136
137268µs150µs
# spent 50µs within Mail::SpamAssassin::Conf::Parser::BEGIN@137 which was called: # once (50µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 137
use Mail::SpamAssassin::Conf;
# spent 50µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@137
138271µs21.38ms
# spent 700µs (19+680) within Mail::SpamAssassin::Conf::Parser::BEGIN@138 which was called: # once (19µs+680µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 138
use Mail::SpamAssassin::Constants qw(:sa);
# spent 700µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@138 # spent 680µs making 1 call to Exporter::import
139271µs2460µs
# spent 243µs (26+217) within Mail::SpamAssassin::Conf::Parser::BEGIN@139 which was called: # once (26µs+217µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 139
use Mail::SpamAssassin::Logger;
# spent 243µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@139 # spent 217µs making 1 call to Exporter::import
140288µs2707µs
# spent 374µs (41+333) within Mail::SpamAssassin::Conf::Parser::BEGIN@140 which was called: # once (41µs+333µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 140
use Mail::SpamAssassin::Util qw(untaint_var);
# spent 374µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@140 # spent 333µs making 1 call to Exporter::import
141252µs114µs
# spent 14µs within Mail::SpamAssassin::Conf::Parser::BEGIN@141 which was called: # once (14µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 141
use Mail::SpamAssassin::NetSet;
# spent 14µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@141
142
143263µs240µs
# spent 30µs (20+10) within Mail::SpamAssassin::Conf::Parser::BEGIN@143 which was called: # once (20µs+10µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 143
use strict;
# spent 30µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@143 # spent 10µs making 1 call to strict::import
144263µs286µs
# spent 53µs (20+33) within Mail::SpamAssassin::Conf::Parser::BEGIN@144 which was called: # once (20µs+33µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 144
use warnings;
# spent 53µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@144 # spent 33µs making 1 call to warnings::import
145268µs232µs
# spent 26µs (19+6) within Mail::SpamAssassin::Conf::Parser::BEGIN@145 which was called: # once (19µs+6µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 145
use bytes;
# spent 26µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@145 # spent 6µs making 1 call to bytes::import
146277µs2149µs
# spent 88µs (26+62) within Mail::SpamAssassin::Conf::Parser::BEGIN@146 which was called: # once (26µs+62µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 146
use re 'taint';
# spent 88µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@146 # spent 62µs making 1 call to re::import
147
14812µs
# spent 111µs (17+94) within Mail::SpamAssassin::Conf::Parser::BEGIN@148 which was called: # once (17µs+94µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 150
use vars qw{
149 @ISA
15014.35ms2205µs};
# spent 111µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@148 # spent 94µs making 1 call to vars::import
151
152114µs@ISA = qw();
153
154###########################################################################
155
156
# spent 30µs within Mail::SpamAssassin::Conf::Parser::new which was called: # once (30µs+0s) by Mail::SpamAssassin::Conf::new at line 4515 of Mail/SpamAssassin/Conf.pm
sub new {
15712µs my $class = shift;
15812µs $class = ref($class) || $class;
15912µs my ($conf) = @_;
160
16113µs my $self = {
162 'conf' => $conf
163 };
164
16514µs $self->{command_luts} = { };
16614µs $self->{command_luts}->{frequent} = { };
16713µs $self->{command_luts}->{remaining} = { };
168
16912µs bless ($self, $class);
17019µs $self;
171}
172
173###########################################################################
174
175
# spent 6.86ms (889µs+5.97) within Mail::SpamAssassin::Conf::Parser::register_commands which was called 16 times, avg 429µs/call: # once (87µs+3.02ms) by Mail::SpamAssassin::Conf::new at line 4516 of Mail/SpamAssassin/Conf.pm # once (48µs+778µs) by Mail::SpamAssassin::Plugin::TxRep::set_config at line 1067 of Mail/SpamAssassin/Plugin/TxRep.pm # once (50µs+360µs) by Mail::SpamAssassin::Plugin::URIDNSBL::set_config at line 813 of Mail/SpamAssassin/Plugin/URIDNSBL.pm # once (72µs+205µs) by Mail::SpamAssassin::Plugin::ReplaceTags::set_config at line 292 of Mail/SpamAssassin/Plugin/ReplaceTags.pm # once (56µs+211µs) by Mail::SpamAssassin::Plugin::SPF::set_config at line 228 of Mail/SpamAssassin/Plugin/SPF.pm # once (48µs+212µs) by Mail::SpamAssassin::Plugin::DKIM::set_config at line 502 of Mail/SpamAssassin/Plugin/DKIM.pm # once (55µs+202µs) by Mail::SpamAssassin::Plugin::FreeMail::set_config at line 213 of Mail/SpamAssassin/Plugin/FreeMail.pm # once (45µs+187µs) by Mail::SpamAssassin::Plugin::Hashcash::set_config at line 158 of Mail/SpamAssassin/Plugin/Hashcash.pm # once (68µs+156µs) by Mail::SpamAssassin::Plugin::AutoLearnThreshold::set_config at line 146 of Mail/SpamAssassin/Plugin/AutoLearnThreshold.pm # once (47µs+149µs) by Mail::SpamAssassin::Plugin::Razor2::set_config at line 134 of Mail/SpamAssassin/Plugin/Razor2.pm # once (71µs+107µs) by Mail::SpamAssassin::Plugin::WhiteListSubject::set_config at line 109 of Mail/SpamAssassin/Plugin/WhiteListSubject.pm # once (45µs+119µs) by Mail::SpamAssassin::Plugin::SpamCop::set_config at line 157 of Mail/SpamAssassin/Plugin/SpamCop.pm # once (70µs+82µs) by Mail::SpamAssassin::Plugin::MIMEHeader::set_config at line 163 of Mail/SpamAssassin/Plugin/MIMEHeader.pm # once (44µs+66µs) by Mail::SpamAssassin::Plugin::URIDetail::set_config at line 150 of Mail/SpamAssassin/Plugin/URIDetail.pm # once (42µs+60µs) by Mail::SpamAssassin::Plugin::VBounce::set_config at line 90 of Mail/SpamAssassin/Plugin/VBounce.pm # once (42µs+54µs) by Mail::SpamAssassin::Plugin::AskDNS::set_config at line 359 of Mail/SpamAssassin/Plugin/AskDNS.pm
sub register_commands {
1761633µs my($self, $arrref) = @_;
1771654µs my $conf = $self->{conf};
178
17916160µs162.08ms $self->set_defaults_from_command_list($arrref);
# spent 2.08ms making 16 calls to Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list, avg 130µs/call
18016126µs163.89ms $self->build_command_luts($arrref);
# spent 3.89ms making 16 calls to Mail::SpamAssassin::Conf::Parser::build_command_luts, avg 243µs/call
18148414µs push(@{$conf->{registered_commands}}, @{$arrref});
182}
183
184
# spent 2.08ms within Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list which was called 16 times, avg 130µs/call: # 16 times (2.08ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 179, avg 130µs/call
sub set_defaults_from_command_list {
1851644µs my ($self, $arrref) = @_;
1861640µs my $conf = $self->{conf};
18732311µs foreach my $cmd (@{$arrref}) {
188 # note! exists, not defined -- we want to be able to set
189 # "undef" default values.
190203915µs if (exists($cmd->{default})) {
191110837µs $conf->{$cmd->{setting}} = $cmd->{default};
192 }
193 }
194}
195
196
# spent 3.89ms within Mail::SpamAssassin::Conf::Parser::build_command_luts which was called 16 times, avg 243µs/call: # 16 times (3.89ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 180, avg 243µs/call
sub build_command_luts {
1971649µs my ($self, $arrref) = @_;
198
1991651µs my $conf = $self->{conf};
200
2011626µs my $set;
20232312µs foreach my $cmd (@{$arrref}) {
203 # first off, decide what set this is in.
204210674µs if ($cmd->{is_frequent}) { $set = 'frequent'; }
205196345µs else { $set = 'remaining'; }
206
207 # next, its priority (used to ensure frequently-used params
208 # are parsed first)
209203441µs my $cmdname = $cmd->{command} || $cmd->{setting};
2102031.33ms $self->{command_luts}->{$set}->{$cmdname} = $cmd;
211
212205716µs if ($cmd->{aliases} && scalar @{$cmd->{aliases}} > 0) {
213414µs foreach my $name (@{$cmd->{aliases}}) {
214221µs $self->{command_luts}->{$set}->{$name} = $cmd;
215 }
216 }
217 }
218}
219
220###########################################################################
221
222
# spent 4.55s (1.51+3.04) within Mail::SpamAssassin::Conf::Parser::parse which was called: # once (1.51s+3.04s) by Mail::SpamAssassin::Conf::parse_rules at line 4623 of Mail/SpamAssassin/Conf.pm
sub parse {
22314µs my ($self, undef, $scoresonly) = @_; # leave $rules in $_[1]
224
22513µs my $conf = $self->{conf};
22613µs $self->{scoresonly} = $scoresonly;
227
228 # Language selection:
229 # See http://www.gnu.org/manual/glibc-2.2.5/html_node/Locale-Categories.html
230 # and http://www.gnu.org/manual/glibc-2.2.5/html_node/Using-gettextized-software.html
23113µs my $lang = $ENV{'LANGUAGE'}; # LANGUAGE has the highest precedence but has a
23212µs if ($lang) { # special format: The user may specify more than
233 $lang =~ s/:.*$//; # one language here, colon separated. We use the
234 } # first one only (lazy bums we are :o)
23513µs $lang ||= $ENV{'LC_ALL'};
23613µs $lang ||= $ENV{'LC_MESSAGES'};
23713µs $lang ||= $ENV{'LANG'};
23812µs $lang ||= 'C'; # Nothing set means C/POSIX
239
240120µs17µs if ($lang =~ /^(C|POSIX)$/) {
# spent 7µs making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:match
24112µs $lang = 'en_US'; # Our default language
242 } else {
243 $lang =~ s/[@.+,].*$//; # Strip codeset, modifier/audience, etc.
244 } # (eg. .utf8 or @euro)
245
246 # get fast-access handles on the command lookup tables
24713µs my $lut_frequent = $self->{command_luts}->{frequent};
24813µs my $lut_remaining = $self->{command_luts}->{remaining};
249212µs my %migrated_keys = map { $_ => 1 }
250 @Mail::SpamAssassin::Conf::MIGRATED_SETTINGS;
251
25213µs $self->{currentfile} = '(no file)';
25312µs my $skip_parsing = 0;
25412µs my @curfile_stack;
255 my @if_stack;
2561364µs my @conf_lines = split (/\n/, $_[1]);
25712µs my $line;
25814µs $self->{if_stack} = \@if_stack;
25913µs $self->{file_scoped_attrs} = { };
260
26113µs my $keepmetadata = $conf->{main}->{keep_config_parsing_metadata};
262
263196.3ms while (defined ($line = shift @conf_lines)) {
2641643651.4ms local ($1); # bug 3838: prevent random taint flagging of $1
265
266 # bug 5545: used to support testing rules in the ruleqa system
2671643625.3ms if ($keepmetadata && $line =~ /^\#testrules/) {
268 $self->{file_scoped_attrs}->{testrules}++;
269 next;
270 }
271
272 # bug 6800: let X-Spam-Checker-Version also show what sa-update we are at
27316436177ms1643643.2ms if ($line =~ /^\# UPDATE version (\d+)$/) {
# spent 43.2ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
27415µs for ($self->{currentfile}) { # just aliasing, not a loop
275112µs $conf->{update_version}{$_} = $1 if defined $_ && $_ ne '(no file)';
276 }
277 }
278
27916436205ms1643666.5ms $line =~ s/(?<!\\)#.*$//; # remove comments
# spent 66.5ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
28016436182ms1643632.3ms $line =~ s/\\#/#/g; # hash chars are escaped, so unescape them
# spent 32.3ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
28116436162ms1643638.1ms $line =~ s/^\s+//; # remove leading whitespace
# spent 38.1ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
28216436201ms1643658.9ms $line =~ s/\s+$//; # remove tailing whitespace
# spent 58.9ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
2831643637.3ms next unless($line); # skip empty lines
284
285 # handle i18n
28610524112ms1199831.2ms if ($line =~ s/^lang\s+(\S+)\s+//) { next if ($lang !~ /^$1/i); }
# spent 21.5ms making 9050 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call # spent 5.96ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 4µs/call # spent 3.67ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
287
288757660.0ms my($key, $value) = split(/\s+/, $line, 2);
289757618.2ms $key = lc $key;
290 # convert all dashes in setting name to underscores.
291757683.4ms757625.8ms $key =~ s/-/_/g;
# spent 25.8ms making 7576 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
292757613.2ms $value = '' unless defined($value);
293
294# # Do a better job untainting this info ...
295# # $value = untaint_var($value);
296# Do NOT blindly untaint now, do it carefully later when semantics is known!
297
298757611.8ms my $parse_error; # undef by default, may be overridden
299
300 # File/line number assertions
301757613.8ms if ($key eq 'file') {
3021361.59ms136675µs if ($value =~ /^start\s+(.+)$/) {
# spent 675µs making 136 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call
30368354µs push (@curfile_stack, $self->{currentfile});
30468276µs $self->{currentfile} = $1;
30568307µs next;
306 }
307
30868880µs68380µs if ($value =~ /^end\s/) {
# spent 380µs making 68 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 6µs/call
30968335µs $self->{file_scoped_attrs} = { };
310
31168188µs if (scalar @if_stack > 0) {
312 my $cond = pop @if_stack;
313
314 if ($cond->{type} eq 'if') {
315 my $msg = "config: unclosed 'if' in ".
316 $self->{currentfile}.": if ".$cond->{conditional}."\n";
317 warn $msg;
318 $self->lint_warn($msg, undef);
319 }
320 else {
321 # die seems a bit excessive here, but this shouldn't be possible
322 # so I suppose it's okay.
323 die "config: unknown 'if' type: ".$cond->{type}."\n";
324 }
325
326 @if_stack = ();
327 }
32868141µs $skip_parsing = 0;
329
33068301µs my $curfile = pop @curfile_stack;
33168294µs if (defined $curfile) {
33268225µs $self->{currentfile} = $curfile;
333 } else {
334 $self->{currentfile} = '(no file)';
335 }
33668287µs next;
337 }
338 }
339
340 # now handle the commands.
341744012.5ms if ($key eq 'include') {
34258591µs5830.0ms $value = $self->fix_path_relative_to_current_file($value);
# spent 30.0ms making 58 calls to Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file, avg 517µs/call
34358759µs5825.7ms my $text = $conf->{main}->read_cf($value, 'included file');
# spent 25.7ms making 58 calls to Mail::SpamAssassin::read_cf, avg 444µs/call
3445828.7ms unshift (@conf_lines, split (/\n/, $text));
34558768µs next;
346 }
347
348738212.4ms if ($key eq 'ifplugin') {
3493605.23ms360120ms $self->handle_conditional ($key, "plugin ($value)",
# spent 120ms making 360 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 334µs/call
350 \@if_stack, \$skip_parsing);
3513601.48ms next;
352 }
353
354702211.6ms if ($key eq 'if') {
3551481.64ms14895.0ms $self->handle_conditional ($key, $value,
# spent 95.0ms making 148 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 642µs/call
356 \@if_stack, \$skip_parsing);
357148669µs next;
358 }
359
360687411.3ms if ($key eq 'else') {
361 # TODO: if/else/else won't get flagged here :(
36225µs if (!@if_stack) {
363 $parse_error = "config: found else without matching conditional";
364 goto failed_line;
365 }
366
36726µs $skip_parsing = !$skip_parsing;
36828µs next;
369 }
370
371 # and the endif statement:
372687211.6ms if ($key eq 'endif') {
3735081.15ms my $lastcond = pop @if_stack;
374508836µs if (!defined $lastcond) {
375 $parse_error = "config: found endif without matching conditional";
376 goto failed_line;
377 }
378
3795081.18ms $skip_parsing = $lastcond->{skip_parsing};
3805083.71ms next;
381 }
382
383 # preprocessing? skip all other commands
384636410.3ms next if $skip_parsing;
385
386618410.2ms if ($key eq 'require_version') {
387 # if it wasn't replaced during install, assume current version ...
3881752µs next if ($value eq "\@\@VERSION\@\@");
389
3901759µs my $ver = $Mail::SpamAssassin::VERSION;
391
392 # if we want to allow "require_version 3.0" be good for all
393 # "3.0.x" versions:
394 ## make sure it's a numeric value
395 #$value += 0.0;
396 ## convert 3.000000 -> 3.0, stay backward compatible ...
397 #$ver =~ s/^(\d+)\.(\d{1,3}).*$/sprintf "%d.%d", $1, $2/e;
398 #$value =~ s/^(\d+)\.(\d{1,3}).*$/sprintf "%d.%d", $1, $2/e;
399
4001737µs if ($ver ne $value) {
401 my $msg = "config: configuration file \"$self->{currentfile}\" requires ".
402 "version $value of SpamAssassin, but this is code version ".
403 "$ver. Maybe you need to use ".
404 "the -C switch, or remove the old config files? ".
405 "Skipping this file";
406 warn $msg;
407 $self->lint_warn($msg, undef);
408 $skip_parsing = 1;
409 }
4101765µs next;
411 }
412
413616715.1ms my $cmd = $lut_frequent->{$key}; # check the frequent command set
414616713.9ms if (!$cmd) {
41522085.17ms $cmd = $lut_remaining->{$key}; # no? try the rest
416 }
417
418 # we've either fallen through with no match, in which case this
419 # if() will fail, or we have a match.
420616710.1ms if ($cmd) {
421566610.2ms if ($self->{scoresonly}) { # reading user config from spamd
422 if ($cmd->{is_priv} && !$conf->{allow_user_rules}) {
423 info("config: not parsing, 'allow_user_rules' is 0: $line");
424 goto failed_line;
425 }
426 if ($cmd->{is_admin}) {
427 info("config: not parsing, administrator setting: $line");
428 goto failed_line;
429 }
430 }
431
432566611.4ms if (!$cmd->{code}) {
43321158µs21492µs if (! $self->setup_default_code_cb($cmd)) {
# spent 492µs making 21 calls to Mail::SpamAssassin::Conf::Parser::setup_default_code_cb, avg 23µs/call
434 goto failed_line;
435 }
436 }
437
4381133265.9ms56662.05s my $ret = &{$cmd->{code}} ($conf, $cmd->{setting}, $value, $line);
# spent 555ms making 27 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:4145], avg 20.6ms/call # spent 310ms making 465 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3174], avg 668µs/call # spent 262ms making 1276 calls to Mail::SpamAssassin::Conf::Parser::set_hash_key_value, avg 206µs/call # spent 250ms making 781 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2981], avg 320µs/call # spent 218ms making 655 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3020], avg 333µs/call # spent 146ms making 811 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:280], avg 180µs/call # spent 98.5ms making 30 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1685], avg 3.28ms/call # spent 43.9ms making 459 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3750], avg 96µs/call # spent 38.4ms making 46 calls to Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[Mail/SpamAssassin/Plugin/MIMEHeader.pm:160], avg 834µs/call # spent 26.2ms making 128 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3557], avg 205µs/call # spent 23.7ms making 71 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3052], avg 334µs/call # spent 15.7ms making 83 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:420], avg 189µs/call # spent 13.2ms making 40 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3088], avg 331µs/call # spent 11.1ms making 34 calls to Mail::SpamAssassin::Conf::Parser::set_addrlist_value, avg 327µs/call # spent 5.13ms making 85 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:468], avg 60µs/call # spent 5.03ms making 15 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2701], avg 336µs/call # spent 4.91ms making 270 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2044], avg 18µs/call # spent 3.80ms making 21 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:662], avg 181µs/call # spent 3.24ms making 63 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:783], avg 51µs/call # spent 3.17ms making 48 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3781], avg 66µs/call # spent 2.77ms making 19 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:433], avg 146µs/call # spent 2.71ms making 64 calls to Mail::SpamAssassin::Plugin::ReplaceTags::__ANON__[Mail/SpamAssassin/Plugin/ReplaceTags.pm:266], avg 42µs/call # spent 2.64ms making 77 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3206], avg 34µs/call # spent 1.89ms making 13 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3122], avg 145µs/call # spent 1.17ms making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3804] # spent 1.06ms making 5 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:935], avg 212µs/call # spent 739µs making 2 calls to Mail::SpamAssassin::Plugin::AskDNS::__ANON__[Mail/SpamAssassin/Plugin/AskDNS.pm:356], avg 369µs/call # spent 559µs making 17 calls to Mail::SpamAssassin::Conf::Parser::set_template_append, avg 33µs/call # spent 425µs making 4 calls to Mail::SpamAssassin::Conf::Parser::set_numeric_value, avg 106µs/call # spent 297µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:609] # spent 231µs making 5 calls to Mail::SpamAssassin::Conf::Parser::set_bool_value, avg 46µs/call # spent 201µs making 2 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1419], avg 101µs/call # spent 173µs making 36 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3402], avg 5µs/call # spent 89µs making 3 calls to Mail::SpamAssassin::Conf::Parser::set_string_value, avg 30µs/call # spent 78µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3835] # spent 78µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:581] # spent 77µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3858] # spent 50µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1007] # spent 46µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1054] # spent 45µs making 2 calls to Mail::SpamAssassin::Conf::Parser::set_template_clear, avg 23µs/call # spent 27µs making 1 call to Mail::SpamAssassin::Plugin::TxRep::__ANON__[Mail/SpamAssassin/Plugin/TxRep.pm:495] # spent 24µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1437]
439
440566612.3ms if ($ret && $ret eq $Mail::SpamAssassin::Conf::INVALID_VALUE)
441 {
442 $parse_error = "config: SpamAssassin failed to parse line, ".
443 "\"$value\" is not valid for \"$key\", ".
444 "skipping: $line";
445 goto failed_line;
446 }
447 elsif ($ret && $ret eq $Mail::SpamAssassin::Conf::INVALID_HEADER_FIELD_NAME)
448 {
449 $parse_error = "config: SpamAssassin failed to parse line, ".
450 "it does not specify a valid header field name, ".
451 "skipping: $line";
452 goto failed_line;
453 }
454 elsif ($ret && $ret eq $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE)
455 {
456 $parse_error = "config: SpamAssassin failed to parse line, ".
457 "no value provided for \"$key\", ".
458 "skipping: $line";
459 goto failed_line;
460 }
461 else {
462566629.2ms next;
463 }
464 }
465
466 # last ditch: try to see if the plugins know what to do with it
4675015.55ms501155ms if ($conf->{main}->call_plugins("parse_config", {
# spent 155ms making 501 calls to Mail::SpamAssassin::call_plugins, avg 310µs/call
468 key => $key,
469 value => $value,
470 line => $line,
471 conf => $conf,
472 user_config => $self->{scoresonly}
473 }))
474 {
475 # a plugin dealt with it successfully.
4765013.47ms next;
477 }
478
479failed_line:
480 my $msg = $parse_error;
481 my $is_error = 1;
482 if (!$msg) {
483 # use a default warning, if a more specific one wasn't output
484 if ($migrated_keys{$key}) {
485 # this key was moved into a plugin; non-fatal for lint
486 $is_error = 0;
487 $msg = "config: failed to parse, now a plugin, skipping, in \"$self->{currentfile}\": $line";
488 } else {
489 # a real syntax error; this is fatal for --lint
490 $msg = "config: failed to parse line, skipping, in \"$self->{currentfile}\": $line";
491 }
492 }
493
494 $self->lint_warn($msg, undef, $is_error);
495 }
496
49715µs delete $self->{if_stack};
498
499112µs112µs $self->lint_check();
# spent 12µs making 1 call to Mail::SpamAssassin::Conf::Parser::lint_check
50019µs1121ms $self->set_default_scores();
501115µs1139ms $self->check_for_missing_descriptions();
502
503122µs delete $self->{scoresonly};
504}
505
506
# spent 215ms (148+66.8) within Mail::SpamAssassin::Conf::Parser::handle_conditional which was called 508 times, avg 424µs/call: # 360 times (79.3ms+40.9ms) by Mail::SpamAssassin::Conf::Parser::parse at line 349, avg 334µs/call # 148 times (69.1ms+25.9ms) by Mail::SpamAssassin::Conf::Parser::parse at line 355, avg 642µs/call
sub handle_conditional {
5075082.52ms my ($self, $key, $value, $if_stack_ref, $skip_parsing_ref) = @_;
5085081.23ms my $conf = $self->{conf};
509
510508966µs my $lexer = ARITH_EXPRESSION_LEXER;
51150819.3ms101610.0ms my @tokens = ($value =~ m/($lexer)/g);
# spent 7.17ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 14µs/call # spent 2.84ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 6µs/call
512
5135081.12ms my $eval = '';
514508858µs my $bad = 0;
5155082.01ms foreach my $token (@tokens) {
516216151.6ms265010.3ms if ($token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/) {
# spent 10.3ms making 2650 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 4µs/call
517 # using tainted subr. argument may taint the whole expression, avoid
51811647.75ms116426.8ms my $u = untaint_var($token);
# spent 26.8ms making 1164 calls to Mail::SpamAssassin::Util::untaint_var, avg 23µs/call
51911642.63ms $eval .= $u . " ";
520 }
521 elsif ($token eq 'plugin') {
522 # replace with a method call
523434808µs $eval .= '$self->cond_clause_plugin_loaded';
524 }
525 elsif ($token eq 'can') {
526 # replace with a method call
52755131µs $eval .= '$self->cond_clause_can';
528 }
529 elsif ($token eq 'has') {
530 # replace with a method call
531 $eval .= '$self->cond_clause_has';
532 }
533 elsif ($token eq 'version') {
5341958µs $eval .= $Mail::SpamAssassin::VERSION." ";
535 }
536 elsif ($token eq 'perl_version') {
537 $eval .= $]." ";
538 }
539 elsif ($token =~ /^\w[\w\:]+$/) { # class name
5404893.24ms48910.7ms my $u = untaint_var($token);
# spent 10.7ms making 489 calls to Mail::SpamAssassin::Util::untaint_var, avg 22µs/call
5414891.26ms $eval .= '"' . $u . '" ';
542 }
543 else {
544 $bad++;
545 warn "config: unparseable chars in 'if $value': '$token'\n";
546 }
547 }
548
549508908µs if ($bad) {
550 $self->lint_warn("bad 'if' line, in \"$self->{currentfile}\"", undef);
551 return -1;
552 }
553
55410165.07ms push (@{$if_stack_ref}, {
555 type => 'if',
556 conditional => $value,
557 skip_parsing => $$skip_parsing_ref
558 });
559
56050833.3ms if (eval $eval) {
# spent 831µs executing statements in 72 string evals (merged) # spent 655µs executing statements in 59 string evals (merged) # spent 498µs executing statements in 41 string evals (merged) # spent 305µs executing statements in 26 string evals (merged) # spent 296µs executing statements in 25 string evals (merged) # spent 264µs executing statements in 20 string evals (merged) # spent 232µs executing statements in 21 string evals (merged) # spent 172µs executing statements in 14 string evals (merged) # spent 169µs executing statements in 15 string evals (merged) # spent 155µs executing statements in 13 string evals (merged) # spent 149µs executing statements in 12 string evals (merged) # spent 142µs executing statements in 11 string evals (merged) # spent 141µs executing statements in 11 string evals (merged) # spent 113µs executing statements in 8 string evals (merged) # spent 112µs executing statements in 7 string evals (merged) # spent 93µs executing statements in 7 string evals (merged) # spent 91µs executing statements in 7 string evals (merged) # spent 90µs executing statements in 7 string evals (merged) # spent 87µs executing statements in 6 string evals (merged) # spent 87µs executing statements in 6 string evals (merged) # spent 82µs executing statements in 7 string evals (merged) # spent 76µs executing statements in 6 string evals (merged) # spent 73µs executing statements in 5 string evals (merged) # spent 71µs executing statements in 5 string evals (merged) # spent 71µs executing statements in 5 string evals (merged) # spent 70µs executing statements in 7 string evals (merged) # spent 70µs executing statements in 12 string evals (merged) # spent 61µs executing statements in 5 string evals (merged) # spent 56µs executing statements in 5 string evals (merged) # spent 53µs executing statements in 4 string evals (merged) # spent 48µs executing statements in 4 string evals (merged) # spent 44µs executing statements in 4 string evals (merged) # spent 44µs executing statements in 3 string evals (merged) # spent 40µs executing statements in 3 string evals (merged) # spent 38µs executing statements in 3 string evals (merged) # spent 32µs executing statements in 3 string evals (merged) # spent 30µs executing statements in 2 string evals (merged) # spent 29µs executing statements in 2 string evals (merged) # spent 29µs executing statements in 2 string evals (merged) # spent 29µs executing statements in 2 string evals (merged) # spent 28µs executing statements in 2 string evals (merged) # spent 26µs executing statements in 2 string evals (merged) # spent 26µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 23µs executing statements in 2 string evals (merged) # spent 22µs executing statements in 2 string evals (merged) # spent 17µs executing statements in string eval # spent 16µs executing statements in 3 string evals (merged) # spent 16µs executing statements in string eval # spent 14µs executing statements in string eval # spent 13µs executing statements in string eval # spent 12µs executing statements in string eval # spent 12µs executing statements in string eval # spent 12µs executing statements in string eval # spent 11µs executing statements in string eval # spent 11µs executing statements in string eval # spent 11µs executing statements in 2 string evals (merged) # spent 11µs executing statements in string eval # spent 10µs executing statements in string eval # spent 10µs executing statements in string eval # spent 8µs executing statements in string eval # spent 6µs executing statements in string eval
561 # leave $skip_parsing as-is; we may not be parsing anyway in this block.
562 # in other words, support nested 'if's and 'require_version's
563 } else {
564127346µs warn "config: error in $key - $eval: $@" if $@ ne '';
565127266µs $$skip_parsing_ref = 1;
566 }
567}
568
569# functions supported in the "if" eval:
570
# spent 3.93ms within Mail::SpamAssassin::Conf::Parser::cond_clause_plugin_loaded which was called 434 times, avg 9µs/call: # 72 times (567µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 119)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 59 times (525µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 287)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 41 times (382µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 132)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 26 times (206µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 823)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 25 times (213µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 154)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 20 times (185µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 742)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 15 times (128µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 289)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 14 times (168µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 128)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call # 13 times (90µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 126)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call # 12 times (99µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 279)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 11 times (121µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 201)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call # 11 times (108µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 170)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 8 times (68µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 115)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 7 times (68µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 278)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 7 times (67µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 274)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 7 times (66µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 275)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 7 times (55µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 754)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 7 times (45µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 276)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call # 6 times (50µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 523)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 6 times (49µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 285)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 5 times (60µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 296)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call # 5 times (46µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 207)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 5 times (42µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 473)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 5 times (38µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 335)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 4 times (60µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 347)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 15µs/call # 4 times (57µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 284)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 14µs/call # 4 times (23µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 945)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call # 3 times (49µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 131)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 16µs/call # 3 times (18µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 304)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call # 2 times (33µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 129)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 16µs/call # 2 times (29µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 133)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 15µs/call # 2 times (26µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 363)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 13µs/call # 2 times (25µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 348)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 13µs/call # 2 times (22µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 925)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call # 2 times (21µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 261)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 2 times (20µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 286)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 2 times (11µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1007)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call # once (18µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 942)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (18µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 277)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (16µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 372)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (16µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1062)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (11µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 116)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (6µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 231)[Mail/SpamAssassin/Conf/Parser.pm:560]
sub cond_clause_plugin_loaded {
5714349.10ms return $_[0]->{conf}->{plugins_loaded}->{$_[1]};
572}
573
574
# spent 5.01ms (829µs+4.18) within Mail::SpamAssassin::Conf::Parser::cond_clause_can which was called 55 times, avg 91µs/call: # 21 times (274µs+1.45ms) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 634)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 82µs/call # 7 times (124µs+534µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 932)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 94µs/call # 6 times (85µs+492µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 718)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 96µs/call # 5 times (72µs+378µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 290)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 90µs/call # 3 times (39µs+252µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 940)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 97µs/call # 3 times (47µs+222µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 947)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 90µs/call # 2 times (43µs+175µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 531)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 109µs/call # 2 times (29µs+154µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 120)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 91µs/call # once (16µs+108µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 117)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (20µs+89µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 114)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (23µs+85µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 299)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (21µs+82µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 529)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (20µs+81µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1075)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (17µs+80µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 118)[Mail/SpamAssassin/Conf/Parser.pm:560]
sub cond_clause_can {
57555133µs my ($self, $method) = @_;
576551.14ms554.18ms $self->cond_clause_can_or_has('can', $method);
# spent 4.18ms making 55 calls to Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has, avg 76µs/call
577}
578
579sub cond_clause_has {
580 my ($self, $method) = @_;
581 $self->cond_clause_can_or_has('has', $method);
582}
583
584
# spent 4.18ms (2.61+1.57) within Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has which was called 55 times, avg 76µs/call: # 55 times (2.61ms+1.57ms) by Mail::SpamAssassin::Conf::Parser::cond_clause_can at line 576, avg 76µs/call
sub cond_clause_can_or_has {
58555126µs my ($self, $fn_name, $method) = @_;
586
58755297µs local($1,$2);
58855902µs55422µs if (!defined $method) {
# spent 422µs making 55 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 8µs/call
589 $self->lint_warn("bad 'if' line, no argument to $fn_name(), ".
590 "in \"$self->{currentfile}\"", undef);
591 } elsif ($method =~ /^(.*)::([^:]+)$/) {
592210.9ms2154µs
# spent 98µs (42+56) within Mail::SpamAssassin::Conf::Parser::BEGIN@592 which was called: # once (42µs+56µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 592
no strict "refs";
# spent 98µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@592 # spent 56µs making 1 call to strict::unimport
59355263µs my($module, $meth) = ($1, $2);
594 return 1 if UNIVERSAL::can($module,$meth) &&
5951102.24ms1101.15ms ( $fn_name eq 'has' || &{$method}() );
# spent 594µs making 55 calls to UNIVERSAL::can, avg 11µs/call # spent 219µs making 24 calls to Mail::SpamAssassin::Conf::feature_bug6558_free, avg 9µs/call # spent 99µs making 10 calls to Mail::SpamAssassin::Plugin::BodyEval::has_check_body_length, avg 10µs/call # spent 82µs making 7 calls to Mail::SpamAssassin::Conf::perl_min_version_5010000, avg 12µs/call # spent 46µs making 5 calls to Mail::SpamAssassin::Plugin::SPF::has_check_for_spf_errors, avg 9µs/call # spent 29µs making 2 calls to Mail::SpamAssassin::Plugin::MIMEEval::has_check_abundant_unicode_ratio, avg 14µs/call # spent 17µs making 2 calls to Mail::SpamAssassin::Conf::feature_registryboundaries, avg 8µs/call # spent 16µs making 1 call to Mail::SpamAssassin::Conf::feature_originating_ip_headers # spent 16µs making 1 call to Mail::SpamAssassin::Conf::feature_dns_local_ports_permit_avoid # spent 10µs making 1 call to Mail::SpamAssassin::Plugin::MIMEEval::has_check_for_ascii_text_illegal # spent 9µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::has_tflags_domains_only # spent 8µs making 1 call to Mail::SpamAssassin::Conf::feature_yesno_takes_args
596 } else {
597 $self->lint_warn("bad 'if' line, cannot find '::' in $fn_name($method), ".
598 "in \"$self->{currentfile}\"", undef);
599 }
600 return;
601}
602
603# Let's do some linting here ...
604# This is called from _parse(), BTW, so we can check for $conf->{tests}
605# easily before finish_parsing() is called and deletes it.
606#
607
# spent 12µs within Mail::SpamAssassin::Conf::Parser::lint_check which was called: # once (12µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 499
sub lint_check {
60812µs my ($self) = @_;
60913µs my $conf = $self->{conf};
610
611111µs if ($conf->{lint_rules}) {
612 # Check for description and score issues in lint fashion
613 while ( my $k = each %{$conf->{descriptions}} ) {
614 if (!exists $conf->{tests}->{$k}) {
615 $self->lint_warn("config: warning: description exists for non-existent rule $k\n", $k);
616 }
617 }
618
619 while ( my($sk) = each %{$conf->{scores}} ) {
620 if (!exists $conf->{tests}->{$sk}) {
621 # bug 5514: not a lint warning any more
622 dbg("config: warning: score set for non-existent rule $sk");
623 }
624 }
625 }
626}
627
628# we should set a default score for all valid rules... Do this here
629# instead of add_test because mostly 'score' occurs after the rule is
630# specified, so why set the scores to default, then set them again at
631# 'score'?
632#
633
# spent 121ms (116+4.70) within Mail::SpamAssassin::Conf::Parser::set_default_scores which was called: # once (116ms+4.70ms) by Mail::SpamAssassin::Conf::Parser::parse at line 500
sub set_default_scores {
63412µs my ($self) = @_;
63513µs my $conf = $self->{conf};
636
637206933.6ms while ( my $k = each %{$conf->{tests}} ) {
63820676.07ms if ( ! exists $conf->{scores}->{$k} ) {
639 # T_ rules (in a testing probationary period) get low, low scores
640128419.0ms12842.52ms my $set_score = ($k =~/^T_/) ? 0.01 : 1.0;
# spent 2.52ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
641
642128412.3ms12842.18ms $set_score = -$set_score if ( ($conf->{tflags}->{$k}||'') =~ /\bnice\b/ );
# spent 2.18ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
64312844.89ms for my $index (0..3) {
644513645.1ms $conf->{scoreset}->[$index]->{$k} = $set_score;
645 }
646 }
647 }
648}
649
650# loop through all the tests and if we are missing a description with debug
651# set, throw a warning except for testing T_ or meta __ rules.
652
# spent 139ms (59.5+79.1) within Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions which was called: # once (59.5ms+79.1ms) by Mail::SpamAssassin::Conf::Parser::parse at line 501
sub check_for_missing_descriptions {
65313µs my ($self) = @_;
65414µs my $conf = $self->{conf};
655
656206923.9ms while ( my $k = each %{$conf->{tests}} ) {
657206724.7ms20675.74ms if ($k !~ m/^(?:T_|__)/i) {
# spent 5.74ms making 2067 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
6588156.96ms81572.8ms if ( ! exists $conf->{descriptions}->{$k} ) {
# spent 72.8ms making 815 calls to Mail::SpamAssassin::Util::TieOneStringHash::EXISTS, avg 89µs/call
65969503µs69474µs dbg("config: warning: no description set for $k");
# spent 474µs making 69 calls to Mail::SpamAssassin::Logger::dbg, avg 7µs/call
660 }
661 }
662 }
663}
664
665###########################################################################
666
667
# spent 492µs within Mail::SpamAssassin::Conf::Parser::setup_default_code_cb which was called 21 times, avg 23µs/call: # 21 times (492µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 433, avg 23µs/call
sub setup_default_code_cb {
6682141µs my ($self, $cmd) = @_;
66921166µs my $type = $cmd->{type};
670
67121111µs if ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_STRING) {
672310µs $cmd->{code} = \&set_string_value;
673 }
674 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL) {
675412µs $cmd->{code} = \&set_bool_value;
676 }
677 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC) {
678412µs $cmd->{code} = \&set_numeric_value;
679 }
680 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE) {
681620µs $cmd->{code} = \&set_hash_key_value;
682 }
683 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST) {
68428µs $cmd->{code} = \&set_addrlist_value;
685 }
686 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_TEMPLATE) {
68726µs $cmd->{code} = \&set_template_append;
688 }
689 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_NOARGS) {
690 $cmd->{code} = \&set_no_value;
691 }
692 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_STRINGLIST) {
693 $cmd->{code} = \&set_string_list;
694 }
695 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_IPADDRLIST) {
696 $cmd->{code} = \&set_ipaddr_list;
697 }
698 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_DURATION) {
699 $cmd->{code} = \&set_duration_value;
700 }
701 else {
702 warn "config: unknown conf type $type!";
703 return 0;
704 }
70521169µs return 1;
706}
707
708sub set_no_value {
709 my ($conf, $key, $value, $line) = @_;
710
711 unless (!defined $value || $value eq '') {
712 return $Mail::SpamAssassin::Conf::INVALID_VALUE;
713 }
714}
715
716
# spent 425µs (202+223) within Mail::SpamAssassin::Conf::Parser::set_numeric_value which was called 4 times, avg 106µs/call: # 4 times (202µs+223µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 106µs/call
sub set_numeric_value {
717425µs my ($conf, $key, $value, $line) = @_;
718
719439µs412µs unless (defined $value && $value !~ /^$/) {
# spent 12µs making 4 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
720 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
721 }
722467µs439µs unless ($value =~ /^ [+-]? \d+ (?: \. \d* )? \z/sx) {
# spent 39µs making 4 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 10µs/call
723 return $Mail::SpamAssassin::Conf::INVALID_VALUE;
724 }
725 # it is safe to untaint now that we know the syntax is a valid number
726485µs4172µs $conf->{$key} = untaint_var($value) + 0;
# spent 172µs making 4 calls to Mail::SpamAssassin::Util::untaint_var, avg 43µs/call
727}
728
729sub set_duration_value {
730 my ($conf, $key, $value, $line) = @_;
731
732 local ($1,$2);
733 unless (defined $value && $value !~ /^$/) {
734 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
735 }
736 unless ($value =~ /^( \+? \d+ (?: \. \d* )? ) (?: \s* ([smhdw]))? \z/sxi) {
737 return $Mail::SpamAssassin::Conf::INVALID_VALUE;
738 }
739 $value = $1;
740 $value *= { s => 1, m => 60, h => 3600,
741 d => 24*3600, w => 7*24*3600 }->{lc $2} if defined $2;
742 # it is safe to untaint now that we know the syntax is a valid time interval
743 $conf->{$key} = untaint_var($value) + 0;
744}
745
746
# spent 231µs (217+14) within Mail::SpamAssassin::Conf::Parser::set_bool_value which was called 5 times, avg 46µs/call: # 5 times (217µs+14µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 46µs/call
sub set_bool_value {
747543µs my ($conf, $key, $value, $line) = @_;
748
749547µs514µs unless (defined $value && $value !~ /^$/) {
# spent 14µs making 5 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
750 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
751 }
752
753 # bug 4462: allow yes/1 and no/0 for boolean values
754514µs $value = lc $value;
755526µs if ($value eq 'yes' || $value eq '1') {
75648µs $value = 1;
757 }
758 elsif ($value eq 'no' || $value eq '0') {
75912µs $value = 0;
760 }
761 else {
762 return $Mail::SpamAssassin::Conf::INVALID_VALUE;
763 }
764
765556µs $conf->{$key} = $value;
766}
767
768
# spent 89µs (80+9) within Mail::SpamAssassin::Conf::Parser::set_string_value which was called 3 times, avg 30µs/call: # 3 times (80µs+9µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 30µs/call
sub set_string_value {
769317µs my ($conf, $key, $value, $line) = @_;
770
771332µs39µs unless (defined $value && $value !~ /^$/) {
# spent 9µs making 3 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
772 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
773 }
774
775334µs $conf->{$key} = $value; # keep tainted
776}
777
778sub set_string_list {
779 my ($conf, $key, $value, $line) = @_;
780
781 unless (defined $value && $value !~ /^$/) {
782 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
783 }
784
785 push(@{$conf->{$key}}, split(' ', $value));
786}
787
788sub set_ipaddr_list {
789 my ($conf, $key, $value, $line) = @_;
790
791 unless (defined $value && $value !~ /^$/) {
792 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
793 }
794
795 foreach my $net (split(' ', $value)) {
796 $conf->{$key}->add_cidr($net);
797 }
798 $conf->{$key.'_configured'} = 1;
799}
800
801
# spent 262ms (48.8+214) within Mail::SpamAssassin::Conf::Parser::set_hash_key_value which was called 1276 times, avg 206µs/call: # 1276 times (48.8ms+214ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 206µs/call
sub set_hash_key_value {
80212766.49ms my ($conf, $key, $value, $line) = @_;
80312768.39ms my($k,$v) = split(/\s+/, $value, 2);
804
80512762.62ms unless (defined $v && $v ne '') {
806 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
807 }
808
809127630.4ms1684214ms $conf->{$key}->{$k} = $v; # keep tainted
# spent 124ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::STORE, avg 147µs/call # spent 89.7ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::FETCH, avg 107µs/call
810}
811
812
# spent 11.1ms (912µs+10.2) within Mail::SpamAssassin::Conf::Parser::set_addrlist_value which was called 34 times, avg 327µs/call: # 34 times (912µs+10.2ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 327µs/call
sub set_addrlist_value {
81334170µs my ($conf, $key, $value, $line) = @_;
814
81534310µs3498µs unless (defined $value && $value !~ /^$/) {
# spent 98µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
816 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
817 }
81834479µs3410.1ms $conf->{parser}->add_to_addrlist ($key, split (' ', $value)); # keep tainted
# spent 10.1ms making 34 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist, avg 297µs/call
819}
820
821sub remove_addrlist_value {
822 my ($conf, $key, $value, $line) = @_;
823
824 unless (defined $value && $value !~ /^$/) {
825 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
826 }
827 $conf->{parser}->remove_from_addrlist ($key, split (' ', $value));
828}
829
830
# spent 559µs (512+48) within Mail::SpamAssassin::Conf::Parser::set_template_append which was called 17 times, avg 33µs/call: # 17 times (512µs+48µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 33µs/call
sub set_template_append {
83117211µs my ($conf, $key, $value, $line) = @_;
83218157µs1748µs if ( $value =~ /^"(.*?)"$/ ) { $value = $1; }
# spent 48µs making 17 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
83317201µs $conf->{$key} .= $value."\n"; # keep tainted
834}
835
836
# spent 45µs within Mail::SpamAssassin::Conf::Parser::set_template_clear which was called 2 times, avg 23µs/call: # 2 times (45µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 23µs/call
sub set_template_clear {
837219µs my ($conf, $key, $value, $line) = @_;
83825µs unless (!defined $value || $value eq '') {
839 return $Mail::SpamAssassin::Conf::INVALID_VALUE;
840 }
841220µs $conf->{$key} = '';
842}
843
844###########################################################################
845
846
# spent 6.05s (95.7ms+5.95) within Mail::SpamAssassin::Conf::Parser::finish_parsing which was called: # once (95.7ms+5.95s) by Mail::SpamAssassin::Conf::finish_parsing at line 4860 of Mail/SpamAssassin/Conf.pm
sub finish_parsing {
84712µs my ($self, $isuserconf) = @_;
84813µs my $conf = $self->{conf};
849
850 # note: this function is called once for system-wide configuration
851 # with $isuserconf set to 0, then again for user conf with $isuserconf set to 1.
85216µs if (!$isuserconf) {
853113µs1853µs $conf->{main}->call_plugins("finish_parsing_start", { conf => $conf });
# spent 853µs making 1 call to Mail::SpamAssassin::call_plugins
854 } else {
855 $conf->{main}->call_plugins("user_conf_parsing_start", { conf => $conf });
856 }
857
8581352µs15.54s $self->trace_meta_dependencies();
8591359µs1125ms $self->fix_priorities();
# spent 125ms making 1 call to Mail::SpamAssassin::Conf::Parser::fix_priorities
860
861 # don't do this if allow_user_rules is active, since it deletes entries
862 # from {tests}
863112µs if (!$conf->{allow_user_rules}) {
864120µs198.0ms $self->find_dup_rules(); # must be after fix_priorities()
# spent 98.0ms making 1 call to Mail::SpamAssassin::Conf::Parser::find_dup_rules
865 }
866
86718µs18µs dbg("config: finish parsing");
# spent 8µs making 1 call to Mail::SpamAssassin::Logger::dbg
868
869205836.5ms while (my ($name, $text) = each %{$conf->{tests}}) {
87020564.41ms my $type = $conf->{test_types}->{$name};
87120566.32ms my $priority = $conf->{priority}->{$name} || 0;
87220563.89ms $conf->{priorities}->{$priority}++;
873
874 # eval type handling
87520566.91ms if (($type & 1) == 1) {
8763799.33ms3794.76ms if (my ($function, $args) = ($text =~ m/(.*?)\s*\((.*?)\)\s*$/)) {
# spent 4.76ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 13µs/call
8773792.96ms37942.2ms my ($packed, $argsref) =
# spent 42.2ms making 379 calls to Mail::SpamAssassin::Conf::Parser::pack_eval_method, avg 111µs/call
878 $self->pack_eval_method($function, $args, $name, $text);
879
8803791.79ms if (!$packed) {
881 # we've already warned about this
882 }
883 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS) {
8841871.68ms $conf->{body_evals}->{$priority}->{$name} = $packed;
885 }
886 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS) {
887101986µs $conf->{head_evals}->{$priority}->{$name} = $packed;
888 }
889 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RBL_EVALS) {
890 # We don't do priorities for $Mail::SpamAssassin::Conf::TYPE_RBL_EVALS
891 # we also use the arrayref instead of the packed string
89273924µs $conf->{rbl_evals}->{$name} = [ $function, @$argsref ];
893 }
894 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_EVALS) {
895763µs $conf->{rawbody_evals}->{$priority}->{$name} = $packed;
896 }
897 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_EVALS) {
8981162µs $conf->{full_evals}->{$priority}->{$name} = $packed;
899 }
900 #elsif ($type == $Mail::SpamAssassin::Conf::TYPE_URI_EVALS) {
901 # $conf->{uri_evals}->{$priority}->{$name} = $packed;
902 #}
903 else {
904 $self->lint_warn("unknown type $type for $name: $text", $name);
905 }
906 }
907 else {
908 $self->lint_warn("syntax error for eval function $name: $text", $name);
909 }
910 }
911 # non-eval tests
912 else {
91316775.58ms if ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS) {
9145134.72ms $conf->{body_tests}->{$priority}->{$name} = $text;
915 }
916 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS) {
9175955.50ms $conf->{head_tests}->{$priority}->{$name} = $text;
918 }
919 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
9204634.15ms $conf->{meta_tests}->{$priority}->{$name} = $text;
921 }
922 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS) {
92369631µs $conf->{uri_tests}->{$priority}->{$name} = $text;
924 }
925 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS) {
92633319µs $conf->{rawbody_tests}->{$priority}->{$name} = $text;
927 }
928 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS) {
92928µs $conf->{full_tests}->{$priority}->{$name} = $text;
930 }
931 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_EMPTY_TESTS) {
932 }
933 else {
934 $self->lint_warn("unknown type $type for $name: $text", $name);
935 }
936 }
937 }
938
93919µs121µs $self->lint_trusted_networks();
940
94115µs if (!$isuserconf) {
942115µs1137ms $conf->{main}->call_plugins("finish_parsing_end", { conf => $conf });
# spent 137ms making 1 call to Mail::SpamAssassin::call_plugins
943 } else {
944 $conf->{main}->call_plugins("user_conf_parsing_end", { conf => $conf });
945 }
946
947112µs124µs $conf->found_any_rules(); # before we might delete {tests}
# spent 24µs making 1 call to Mail::SpamAssassin::Conf::found_any_rules
948
949122µs if (!$conf->{allow_user_rules}) {
950 # free up stuff we no longer need
95111.83ms delete $conf->{tests};
9521546µs delete $conf->{priority};
953 #test_types are needed - see bug 5503
954 #delete $conf->{test_types};
955 }
956}
957
958
# spent 5.54s (30.7ms+5.51) within Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies which was called: # once (30.7ms+5.51s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 858
sub trace_meta_dependencies {
95912µs my ($self) = @_;
96013µs my $conf = $self->{conf};
96114µs $conf->{meta_dependencies} = { };
962
96323.14ms foreach my $name (keys %{$conf->{tests}}) {
96420679.47ms next unless ($conf->{test_types}->{$name}
965 == $Mail::SpamAssassin::Conf::TYPE_META_TESTS);
966
967464970µs my $deps = [ ];
968464843µs my $alreadydone = { };
9694643.05ms4645.51s $self->_meta_deps_recurse($conf, $name, $name, $deps, $alreadydone);
# spent 5.51s making 464 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 11.9ms/call
97092812.7ms $conf->{meta_dependencies}->{$name} = join (' ', @{$deps});
971 }
972}
973
974
# spent 5.51s (4.04+1.47) within Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse which was called 13832 times, avg 398µs/call: # 13368 times (3.87s+-3.87s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 1000, avg 0s/call # 464 times (166ms+5.34s) by Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies at line 969, avg 11.9ms/call
sub _meta_deps_recurse {
9751383229.6ms my ($self, $conf, $toprule, $name, $deps, $alreadydone) = @_;
976
977 # Only do each rule once per top-level meta; avoid infinite recursion
9781383252.8ms return if $alreadydone->{$name};
9791132364.4ms $alreadydone->{$name} = 1;
980
981 # Obviously, don't trace empty or nonexistent rules
9821132352.5ms my $rule = $conf->{tests}->{$name};
9831132319.1ms return unless $rule;
984
985 # Lex the rule into tokens using a rather simple RE method ...
9861132118.6ms my $lexer = ARITH_EXPRESSION_LEXER;
98711321779ms22642505ms my @tokens = ($rule =~ m/$lexer/g);
# spent 463ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 41µs/call # spent 42.1ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 4µs/call
988
989 # Go through each token in the meta rule
9901132121.5ms my $conf_tests = $conf->{tests};
99111321597ms foreach my $token (@tokens) {
992 # has to be an alpha+numeric token
993 # next if $token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/;
9942694482.70s269448614ms next if $token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s; # faster
# spent 614ms making 269448 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
995 # and has to be a rule name
996120401533ms next unless exists $conf_tests->{$token};
997
998 # add and recurse
99926736137ms13368353ms push(@{$deps}, untaint_var($token));
# spent 353ms making 13368 calls to Mail::SpamAssassin::Util::untaint_var, avg 26µs/call
100013368110ms133680s $self->_meta_deps_recurse($conf, $toprule, $token, $deps, $alreadydone);
# spent 11.1s making 13368 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 831µs/call, recursion: max depth 7, sum of overlapping time 11.1s
1001 }
1002}
1003
1004
# spent 125ms (105+20.0) within Mail::SpamAssassin::Conf::Parser::fix_priorities which was called: # once (105ms+20.0ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 859
sub fix_priorities {
100512µs my ($self) = @_;
100613µs my $conf = $self->{conf};
1007
100812µs die unless $conf->{meta_dependencies}; # order requirement
100913µs my $pri = $conf->{priority};
1010
1011 # sort into priority order, lowest first -- this way we ensure that if we
1012 # rearrange the pri of a rule early on, we cannot accidentally increase its
1013 # priority later.
101413.08ms120.0ms foreach my $rule (sort {
# spent 20.0ms making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:sort
1015974220.0ms $pri->{$a} <=> $pri->{$b}
101612µs } keys %{$pri})
1017 {
1018 # we only need to worry about meta rules -- they are the
1019 # only type of rules which depend on other rules
102020676.51ms my $deps = $conf->{meta_dependencies}->{$rule};
102120673.31ms next unless (defined $deps);
1022
10234641.51ms my $basepri = $pri->{$rule};
102446412.0ms foreach my $dep (split ' ', $deps) {
10251336832.3ms my $deppri = $pri->{$dep};
10261336846.5ms if ($deppri > $basepri) {
1027 dbg("rules: $rule (pri $basepri) requires $dep (pri $deppri): fixed");
1028 $pri->{$dep} = $basepri;
1029 }
1030 }
1031 }
1032}
1033
1034
# spent 98.0ms (94.5+3.52) within Mail::SpamAssassin::Conf::Parser::find_dup_rules which was called: # once (94.5ms+3.52ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 864
sub find_dup_rules {
103515µs my ($self) = @_;
103614µs my $conf = $self->{conf};
1037
103812µs my %names_for_text;
1039 my %dups;
1040206935.9ms while (my ($name, $text) = each %{$conf->{tests}}) {
104120674.36ms my $type = $conf->{test_types}->{$name};
1042
1043 # skip eval and empty tests
104420673.98ms next if ($type & 1) ||
1045 ($type eq $Mail::SpamAssassin::Conf::TYPE_EMPTY_TESTS);
1046
1047337220.0ms16863.31ms my $tf = ($conf->{tflags}->{$name}||''); $tf =~ s/\s+/ /gs;
# spent 3.31ms making 1686 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1048 # ensure similar, but differently-typed, rules are not marked as dups;
1049 # take tflags into account too due to "tflags multiple"
105016864.97ms $text = "$type\t$text\t$tf";
1051
105216866.77ms if (defined $names_for_text{$text}) {
10531182µs $names_for_text{$text} .= " ".$name;
10541135µs $dups{$text} = undef; # found (at least) one
1055 } else {
1056167520.0ms $names_for_text{$text} = $name;
1057 }
1058 }
1059
10601577µs foreach my $text (keys %dups) {
10611016µs my $first;
1062 my $first_pri;
106322280µs1090µs my @names = sort {$a cmp $b} split(' ', $names_for_text{$text});
# spent 90µs making 10 calls to Mail::SpamAssassin::Conf::Parser::CORE:sort, avg 9µs/call
10641033µs foreach my $name (@names) {
106521167µs my $priority = $conf->{priority}->{$name} || 0;
1066
106721122µs if (!defined $first || $priority < $first_pri) {
10681017µs $first_pri = $priority;
10691024µs $first = $name;
1070 }
1071 }
1072 # $first is now the earliest-occurring rule. mark others as dups
1073
10741017µs my @dups;
10751051µs foreach my $name (@names) {
10762145µs next if $name eq $first;
10771149µs push @dups, $name;
107811102µs delete $conf->{tests}->{$name};
1079 }
1080
108110143µs10114µs dbg("rules: $first merged duplicates: ".join(' ', @dups));
# spent 114µs making 10 calls to Mail::SpamAssassin::Logger::dbg, avg 11µs/call
108210130µs $conf->{duplicate_rules}->{$first} = \@dups;
1083 }
1084}
1085
1086
# spent 42.2ms (35.5+6.68) within Mail::SpamAssassin::Conf::Parser::pack_eval_method which was called 379 times, avg 111µs/call: # 379 times (35.5ms+6.68ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 877, avg 111µs/call
sub pack_eval_method {
10873793.78ms my ($self, $function, $args, $name, $text) = @_;
1088
1089379652µs my @args;
10903791.27ms if (defined $args) {
1091 # bug 4419: Parse quoted strings, unquoted alphanumerics/floats,
1092 # unquoted IPv4 and IPv6 addresses, and unquoted common domain names.
1093 # s// is used so that we can determine whether or not we successfully
1094 # parsed ALL arguments.
10953791.59ms local($1,$2,$3);
10963796.17ms3792.54ms while ($args =~ s/^\s* (?: (['"]) (.*?) \1 | ( [\d\.:A-Za-z-]+? ) )
# spent 2.54ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µs/call
1097 \s* (?: , \s* | $ )//x) {
10984837.80ms4832.21ms if (defined $2) {
# spent 2.21ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 5µs/call
10994743.05ms push @args, $2;
1100 }
1101 else {
1102978µs push @args, $3;
1103 }
1104 }
1105 }
1106
1107379713µs if ($args ne '') {
1108 $self->lint_warn("syntax error (unparsable argument: $args) for eval function: $name: $text", $name);
1109 return;
1110 }
1111
1112379848µs my $argstr = $function;
11133793.02ms379908µs $argstr =~ s/\s+//gs;
# spent 908µs making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1114
11153791.33ms if (@args > 0) {
1116 $argstr .= ',' . join(', ',
111717049.41ms4831.03ms map { my $s = $_; $s =~ s/\#/[HASH]/gs; 'q#' . $s . '#' } @args);
# spent 1.03ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1118 }
11193792.95ms return ($argstr, \@args);
1120}
1121
1122###########################################################################
1123
1124
# spent 21µs within Mail::SpamAssassin::Conf::Parser::lint_trusted_networks which was called: # once (21µs+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 939
sub lint_trusted_networks {
112512µs my ($self) = @_;
112614µs my $conf = $self->{conf};
1127
1128 # validate trusted_networks and internal_networks, bug 4760.
1129 # check that all internal_networks are listed in trusted_networks
1130 # too. do the same for msa_networks, but check msa_networks against
1131 # internal_networks if trusted_networks aren't defined
1132
113312µs my ($nt, $matching_against);
113415µs if ($conf->{trusted_networks_configured}) {
1135 $nt = $conf->{trusted_networks};
1136 $matching_against = 'trusted_networks';
1137 } elsif ($conf->{internal_networks_configured}) {
1138 $nt = $conf->{internal_networks};
1139 $matching_against = 'internal_networks';
1140 } else {
1141114µs return;
1142 }
1143
1144 foreach my $net_type ('internal_networks', 'msa_networks') {
1145 next unless $conf->{"${net_type}_configured"};
1146 next if $net_type eq $matching_against;
1147
1148 my $replace_nets;
1149 my @valid_net_list;
1150 my $net_list = $conf->{$net_type};
1151
1152 foreach my $net (@{$net_list->{nets}}) {
1153 # don't check to see if an excluded network is included - that's senseless
1154 if (!$net->{exclude} && !$nt->contains_net($net)) {
1155 my $msg = "$matching_against doesn't contain $net_type entry '".
1156 ($net->{as_string})."'";
1157
1158 $self->lint_warn($msg, undef); # complain
1159 $replace_nets = 1; # and omit it from the new internal set
1160 }
1161 else {
1162 push @valid_net_list, $net;
1163 }
1164 }
1165
1166 if ($replace_nets) {
1167 # something was invalid. replace the old nets list with a fixed version
1168 # (which may be empty)
1169 $net_list->{nets} = \@valid_net_list;
1170 }
1171 }
1172}
1173
1174###########################################################################
1175
1176
# spent 703ms (191+512) within Mail::SpamAssassin::Conf::Parser::add_test which was called 2074 times, avg 339µs/call: # 548 times (59.6ms+114ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2979 of Mail/SpamAssassin/Conf.pm, avg 318µs/call # 513 times (42.1ms+128ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3020] at line 3018 of Mail/SpamAssassin/Conf.pm, avg 331µs/call # 465 times (48.3ms+243ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3174] at line 3173 of Mail/SpamAssassin/Conf.pm, avg 627µs/call # 142 times (9.99ms+998µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3020] at line 3011 of Mail/SpamAssassin/Conf.pm, avg 77µs/call # 102 times (6.87ms+660µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2958 of Mail/SpamAssassin/Conf.pm, avg 74µs/call # 73 times (4.98ms+776µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2955 of Mail/SpamAssassin/Conf.pm, avg 79µs/call # 71 times (6.20ms+15.2ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3052] at line 3051 of Mail/SpamAssassin/Conf.pm, avg 302µs/call # 58 times (4.74ms+1.12ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2970 of Mail/SpamAssassin/Conf.pm, avg 101µs/call # 46 times (3.64ms+306µs) by Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/MIMEHeader.pm:160] at line 140 of Mail/SpamAssassin/Plugin/MIMEHeader.pm, avg 86µs/call # 33 times (3.19ms+7.12ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3088] at line 3086 of Mail/SpamAssassin/Conf.pm, avg 312µs/call # 11 times (803µs+71µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3122] at line 3114 of Mail/SpamAssassin/Conf.pm, avg 79µs/call # 7 times (438µs+97µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3088] at line 3080 of Mail/SpamAssassin/Conf.pm, avg 76µs/call # 2 times (140µs+289µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3122] at line 3120 of Mail/SpamAssassin/Conf.pm, avg 215µs/call # 2 times (111µs+44µs) by Mail::SpamAssassin::Plugin::AskDNS::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/AskDNS.pm:356] at line 353 of Mail/SpamAssassin/Plugin/AskDNS.pm, avg 77µs/call # once (82µs+6µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3206] at line 3204 of Mail/SpamAssassin/Conf.pm
sub add_test {
117720749.71ms my ($self, $name, $text, $type) = @_;
117820744.21ms my $conf = $self->{conf};
1179
1180 # Don't allow invalid names ...
1181207430.1ms20748.74ms if ($name !~ /^\D\w*$/) {
# spent 8.74ms making 2074 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 4µs/call
1182 $self->lint_warn("config: error: rule '$name' has invalid characters ".
1183 "(not Alphanumeric + Underscore + starting with a non-digit)\n", $name);
1184 return;
1185 }
1186
1187 # Also set a hard limit for ALL rules (rule names longer than 242
1188 # characters throw warnings). Check this separately from the above
1189 # pattern to avoid vague error messages.
119020744.55ms if (length $name > 200) {
1191 $self->lint_warn("config: error: rule '$name' is way too long ".
1192 "(recommended maximum length is 22 characters)\n", $name);
1193 return;
1194 }
1195
1196 # Warn about, but use, long rule names during --lint
119720743.75ms if ($conf->{lint_rules}) {
1198 if (length($name) > 50 && $name !~ /^__/ && $name !~ /^T_/) {
1199 $self->lint_warn("config: warning: rule name '$name' is over 50 chars ".
1200 "(recommended maximum length is 22 characters)\n", $name);
1201 }
1202 }
1203
1204 # all of these rule types are regexps
120520745.12ms if ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS ||
1206 $type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS ||
1207 $type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS ||
1208 $type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS)
1209 {
12106194.30ms619146ms return unless $self->is_delimited_regexp_valid($name, $text);
# spent 146ms making 619 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 236µs/call
1211 }
121220745.65ms if ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS)
1213 {
1214 # RFC 5322 section 3.6.8, ftext printable US-ASCII chars not including ":"
1215 # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables...
12166066.83ms6061.94ms if ($text =~ /^!?defined\([!-9;-\176]+\)$/) {
# spent 1.94ms making 606 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
1217 # fine, implements 'exists:'
1218 } else {
121954811.8ms5487.58ms my ($pat) = ($text =~ /^\s*\S+\s*(?:\=|\!)\~\s*(\S.*?\S)\s*$/);
# spent 7.58ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 14µs/call
122010966.69ms5481.41ms if ($pat) { $pat =~ s/\s+\[if-unset:\s+(.+)\]\s*$//; }
# spent 1.41ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
12215483.87ms548101ms return unless $self->is_delimited_regexp_valid($name, $pat);
# spent 101ms making 548 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 184µs/call
1222 }
1223 }
1224 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS)
1225 {
12264653.32ms465240ms return unless $self->is_meta_valid($name, $text);
# spent 240ms making 465 calls to Mail::SpamAssassin::Conf::Parser::is_meta_valid, avg 516µs/call
1227 }
1228
1229207426.4ms $conf->{tests}->{$name} = $text;
123020748.64ms $conf->{test_types}->{$name} = $type;
1231
1232207418.9ms20745.66ms if ($name =~ /AUTOLEARNTEST/i) {
# spent 5.66ms making 2074 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
1233 dbg("config: auto-learn: $name has type $type = $conf->{test_types}->{$name} during add_test\n");
1234 }
1235
1236
123720746.79ms if ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
12384653.73ms $conf->{priority}->{$name} ||= 500;
1239 }
1240 else {
1241160911.6ms $conf->{priority}->{$name} ||= 0;
1242 }
124320744.35ms $conf->{priority}->{$name} ||= 0;
1244207416.6ms $conf->{source_file}->{$name} = $self->{currentfile};
1245
124620743.91ms if ($conf->{main}->{keep_config_parsing_metadata}) {
1247 $conf->{if_stack}->{$name} = $self->get_if_stack_as_string();
1248
1249 if ($self->{file_scoped_attrs}->{testrules}) {
1250 $conf->{testrules}->{$name} = 1; # used in build/mkupdates/listpromotable
1251 }
1252 }
1253
1254 # if we found this rule in a user_prefs file, it's a user rule -- note that
1255 # we may need to recompile the rule code for this type (if they've already
1256 # been compiled, e.g. in spamd).
1257 #
1258 # Note: the want_rebuild_for_type 'flag' is actually a counter; it is decremented
1259 # after each scan. This ensures that we always recompile at least once more;
1260 # once to *define* the rule, and once afterwards to *undefine* the rule in the
1261 # compiled ruleset again.
1262 #
1263 # If two consecutive scans use user rules, that's ok -- the second one will
1264 # reset the counter, and we'll still recompile just once afterwards to undefine
1265 # the rule again.
1266 #
1267207425.8ms if ($self->{scoresonly}) {
1268 $conf->{want_rebuild_for_type}->{$type} = 2;
1269 $conf->{user_defined_rules}->{$name} = 1;
1270 }
1271}
1272
1273sub add_regression_test {
1274 my ($self, $name, $ok_or_fail, $string) = @_;
1275 my $conf = $self->{conf};
1276
1277 if ($conf->{regression_tests}->{$name}) {
1278 push @{$conf->{regression_tests}->{$name}}, [$ok_or_fail, $string];
1279 }
1280 else {
1281 # initialize the array, and create one element
1282 $conf->{regression_tests}->{$name} = [ [$ok_or_fail, $string] ];
1283 }
1284}
1285
1286
# spent 240ms (181+58.9) within Mail::SpamAssassin::Conf::Parser::is_meta_valid which was called 465 times, avg 516µs/call: # 465 times (181ms+58.9ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1226, avg 516µs/call
sub is_meta_valid {
12874652.16ms my ($self, $name, $rule) = @_;
1288
1289465963µs my $meta = '';
12904653.32ms46519.6ms $rule = untaint_var($rule); # must be careful below
# spent 19.6ms making 465 calls to Mail::SpamAssassin::Util::untaint_var, avg 42µs/call
1291
1292 # Lex the rule into tokens using a rather simple RE method ...
1293465876µs my $lexer = ARITH_EXPRESSION_LEXER;
129446528.4ms93019.0ms my @tokens = ($rule =~ m/$lexer/g);
# spent 16.3ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 35µs/call # spent 2.70ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 6µs/call
12954651.15ms if (length($name) == 1) {
1296 for (@tokens) {
1297 print "$name $_\n " or die "Error writing token: $!";
1298 }
1299 }
1300 # Go through each token in the meta rule
13014651.75ms foreach my $token (@tokens) {
1302 # Numbers can't be rule names
13037210120ms721020.3ms if ($token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s) {
# spent 20.3ms making 7210 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
130441127.78ms $meta .= "$token ";
1305 }
1306 # Zero will probably cause more errors
1307 else {
130830985.50ms $meta .= "0 ";
1309 }
1310 }
1311
13124651.64ms my $evalstr = 'my $x = ' . $meta . '; 1;';
131346529.5ms if (eval $evalstr) {
# spent 412µs executing statements in 37 string evals (merged) # spent 397µs executing statements in 42 string evals (merged) # spent 261µs executing statements in 26 string evals (merged) # spent 236µs executing statements in 24 string evals (merged) # spent 206µs executing statements in 20 string evals (merged) # spent 201µs executing statements in 17 string evals (merged) # spent 118µs executing statements in 12 string evals (merged) # spent 112µs executing statements in 14 string evals (merged) # spent 92µs executing statements in 8 string evals (merged) # spent 79µs executing statements in 6 string evals (merged) # spent 73µs executing statements in 8 string evals (merged) # spent 73µs executing statements in 6 string evals (merged) # spent 70µs executing statements in 8 string evals (merged) # spent 68µs executing statements in 5 string evals (merged) # spent 65µs executing statements in 7 string evals (merged) # spent 64µs executing statements in 8 string evals (merged) # spent 60µs executing statements in 7 string evals (merged) # spent 54µs executing statements in 6 string evals (merged) # spent 44µs executing statements in 6 string evals (merged) # spent 43µs executing statements in 5 string evals (merged) # spent 42µs executing statements in 5 string evals (merged) # spent 40µs executing statements in 4 string evals (merged) # spent 40µs executing statements in 3 string evals (merged) # spent 39µs executing statements in 3 string evals (merged) # spent 37µs executing statements in 5 string evals (merged) # spent 37µs executing statements in 3 string evals (merged) # spent 33µs executing statements in 2 string evals (merged) # spent 32µs executing statements in 4 string evals (merged) # spent 32µs executing statements in 2 string evals (merged) # spent 31µs executing statements in 4 string evals (merged) # spent 29µs executing statements in 2 string evals (merged) # spent 29µs executing statements in 2 string evals (merged) # spent 27µs executing statements in 3 string evals (merged) # spent 26µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 3 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 3 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 23µs executing statements in 2 string evals (merged) # spent 23µs executing statements in 3 string evals (merged) # spent 23µs executing statements in 3 string evals (merged) # spent 22µs executing statements in 3 string evals (merged) # spent 22µs executing statements in 2 string evals (merged) # spent 22µs executing statements in 2 string evals (merged) # spent 21µs executing statements in 2 string evals (merged) # spent 21µs executing statements in string eval # spent 21µs executing statements in 2 string evals (merged) # spent 20µs executing statements in string eval # spent 20µs executing statements in string eval # spent 20µs executing statements in string eval # spent 19µs executing statements in string eval # spent 19µs executing statements in 2 string evals (merged) # spent 18µs executing statements in string eval # spent 18µs executing statements in 2 string evals (merged) # spent 18µs executing statements in string eval # spent 17µs executing statements in string eval # spent 17µs executing statements in string eval # spent 17µs executing statements in string eval # spent 17µs executing statements in string eval # spent 16µs executing statements in 2 string evals (merged) # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in 2 string evals (merged) # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in 2 string evals (merged) # spent 16µs executing statements in string eval # spent 15µs executing statements in string eval # spent 15µs executing statements in 2 string evals (merged) # spent 15µs executing statements in string eval # spent 15µs executing statements in string eval # spent 15µs executing statements in string eval # spent 15µs executing statements in 2 string evals (merged) # spent 14µs executing statements in string eval # spent 14µs executing statements in 2 string evals (merged) # spent 14µs executing statements in 2 string evals (merged) # spent 14µs executing statements in string eval # spent 13µs executing statements in string eval # spent 13µs executing statements in string eval # spent 13µs executing statements in string eval # spent 13µs executing statements in string eval # spent 12µs executing statements in string eval # spent 12µs executing statements in string eval # spent 12µs executing statements in string eval # spent 11µs executing statements in string eval # spent 11µs executing statements in string eval # spent 10µs executing statements in string eval # spent 10µs executing statements in string eval # spent 10µs executing statements in string eval # spent 10µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval
13144656.51ms return 1;
1315 }
1316 my $err = $@ ne '' ? $@ : "errno=$!"; chomp $err;
1317 $err =~ s/\s+(?:at|near)\b.*//s;
1318 $err =~ s/Illegal division by zero/division by zero possible/i;
1319 $self->lint_warn("config: invalid expression for rule $name: \"$rule\": $err\n", $name);
1320 return 0;
1321}
1322
1323
# spent 258ms (37.0+221) within Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid which was called 1228 times, avg 210µs/call: # 619 times (15.4ms+131ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1210, avg 236µs/call # 548 times (20.1ms+80.6ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1221, avg 184µs/call # 46 times (1.19ms+7.49ms) by Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/MIMEHeader.pm:160] at line 116 of Mail/SpamAssassin/Plugin/MIMEHeader.pm, avg 189µs/call # 15 times (366µs+2.64ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2701] at line 2685 of Mail/SpamAssassin/Conf.pm, avg 201µs/call
sub is_delimited_regexp_valid {
132412285.68ms my ($self, $name, $re) = @_;
1325
1326122816.5ms12287.36ms if (!$re || $re !~ /^\s*m?(\W).*(?:\1|>|}|\)|\])[a-z]*\s*$/) {
# spent 7.36ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 6µs/call
1327 $re ||= '';
1328 $self->lint_warn("config: invalid regexp for rule $name: $re: missing or invalid delimiters\n", $name);
1329 return 0;
1330 }
1331122814.4ms1228214ms return $self->is_regexp_valid($name, $re);
# spent 214ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::is_regexp_valid, avg 174µs/call
1332}
1333
1334
# spent 214ms (108+106) within Mail::SpamAssassin::Conf::Parser::is_regexp_valid which was called 1228 times, avg 174µs/call: # 1228 times (108ms+106ms) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1331, avg 174µs/call
sub is_regexp_valid {
133512285.80ms my ($self, $name, $re) = @_;
1336
1337 # OK, try to remove any normal perl-style regexp delimiters at
1338 # the start and end, and modifiers at the end if present,
1339 # so we can validate those too.
134012282.82ms my $origre = $re;
134112282.77ms my $safere = $re;
134212282.35ms my $mods = '';
134312284.44ms local ($1,$2);
1344122858.9ms603420.1ms if ($re =~ s/^m\{//) {
# spent 20.1ms making 6034 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
134528255µs1489µs $re =~ s/\}([a-z]*)\z//; $mods = $1;
# spent 89µs making 14 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 6µs/call
1346 }
1347 elsif ($re =~ s/^m\(//) {
1348 $re =~ s/\)([a-z]*)\z//; $mods = $1;
1349 }
1350 elsif ($re =~ s/^m<//) {
1351 $re =~ s/>([a-z]*)\z//; $mods = $1;
1352 }
1353 elsif ($re =~ s/^m(\W)//) {
13541002.37ms1001.28ms $re =~ s/\Q$1\E([a-z]*)\z//; $mods = $1;
# spent 840µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 17µs/call # spent 442µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 9µs/call
1355 }
1356 elsif ($re =~ s{^/(.*)/([a-z]*)\z}{$1}) {
135711643.63ms $mods = $2;
1358 }
1359 else {
1360 $safere = "m#".$re."#";
1361 }
1362
136312283.07ms if ($self->{conf}->{lint_rules} ||
1364 $self->{conf}->{ignore_always_matching_regexps})
1365 {
1366 my $msg = $self->is_always_matching_regexp($name, $re);
1367
1368 if (defined $msg) {
1369 if ($self->{conf}->{lint_rules}) {
1370 $self->lint_warn($msg, $name);
1371 } else {
1372 warn $msg;
1373 return 0;
1374 }
1375 }
1376 }
1377
1378 # now prepend the modifiers, in order to check if they're valid
137912283.44ms if ($mods) {
13807883.61ms $re = "(?" . $mods . ")" . $re;
1381 }
1382
1383 # note: this MUST use m/...${re}.../ in some form or another, ie.
1384 # interpolation of the $re variable into a code regexp, in order to test the
1385 # security of the regexp. simply using ("" =~ $re) will NOT do that, and
1386 # will therefore open a hole!
1387 { # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables...
13886140130ms245684.5ms if (eval { ("" =~ m{$re}); 1; }) { return 1 }
# spent 82.1ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 67µs/call # spent 2.37ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
1389 }
1390 my $err = $@ ne '' ? $@ : "errno=$!"; chomp $err;
1391 $err =~ s/ at .*? line \d.*$//;
1392 $self->lint_warn("config: invalid regexp for rule $name: $origre: $err\n", $name);
1393 return 0;
1394}
1395
1396# check the pattern for some basic errors, and warn if found
1397sub is_always_matching_regexp {
1398 my ($self, $name, $re) = @_;
1399
1400 if ($re =~ /(?<!\\)\|\|/) {
1401 return "config: regexp for rule $name always matches due to '||'";
1402 }
1403 elsif ($re =~ /^\|/) {
1404 return "config: regexp for rule $name always matches due to " .
1405 "pattern starting with '|'";
1406 }
1407 elsif ($re =~ /\|(?<!\\\|)$/) {
1408 return "config: regexp for rule $name always matches due to " .
1409 "pattern ending with '|'";
1410 }
1411 return;
1412}
1413
1414###########################################################################
1415
1416
# spent 10.1ms (9.29+823µs) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist which was called 34 times, avg 297µs/call: # 34 times (9.29ms+823µs) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 818, avg 297µs/call
sub add_to_addrlist {
141734130µs my ($self, $singlelist, @addrs) = @_;
14183465µs my $conf = $self->{conf};
1419
142034347µs foreach my $addr (@addrs) {
14213492µs $addr = lc $addr;
14223473µs my $re = $addr;
142334296µs3484µs $re =~ s/[\000\\\(]/_/gs; # paranoia
# spent 84µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1424348.15ms152556µs $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
# spent 425µs making 118 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 4µs/call # spent 131µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
14253495µs $re =~ tr/?/./; # "?" -> "."
142634417µs34184µs $re =~ s/\*+/\.\*/g; # "*" -> "any string"
# spent 184µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 5µs/call
142734534µs $conf->{$singlelist}->{$addr} = "^${re}\$";
1428 }
1429}
1430
1431
# spent 10.3ms (7.89+2.41) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd which was called 102 times, avg 101µs/call: # 83 times (6.36ms+1.95ms) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim at line 1470, avg 100µs/call # 19 times (1.53ms+463µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:433] at line 431 of Mail/SpamAssassin/Conf.pm, avg 105µs/call
sub add_to_addrlist_rcvd {
1432102426µs my ($self, $listname, $addr, $domain) = @_;
1433102208µs my $conf = $self->{conf};
1434
1435102213µs $domain = lc $domain;
1436102236µs $addr = lc $addr;
1437102988µs if ($conf->{$listname}->{$addr}) {
14381044µs push @{$conf->{$listname}->{$addr}{domain}}, $domain;
1439 }
1440 else {
144197201µs my $re = $addr;
144297825µs97232µs $re =~ s/[\000\\\(]/_/gs; # paranoia
# spent 232µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1443974.10ms4581.64ms $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
# spent 1.24ms making 361 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 3µs/call # spent 393µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
144497270µs $re =~ tr/?/./; # "?" -> "."
1445971.16ms97540µs $re =~ s/\*+/\.\*/g; # "*" -> "any string"
# spent 540µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 6µs/call
1446971.37ms $conf->{$listname}->{$addr}{re} = "^${re}\$";
144797486µs $conf->{$listname}->{$addr}{domain} = [ $domain ];
1448 }
1449}
1450
1451sub remove_from_addrlist {
1452 my ($self, $singlelist, @addrs) = @_;
1453 my $conf = $self->{conf};
1454
1455 foreach my $addr (@addrs) {
1456 delete($conf->{$singlelist}->{lc $addr});
1457 }
1458}
1459
1460sub remove_from_addrlist_rcvd {
1461 my ($self, $listname, @addrs) = @_;
1462 my $conf = $self->{conf};
1463
1464 foreach my $addr (@addrs) {
1465 delete($conf->{$listname}->{lc $addr});
1466 }
1467}
1468
1469
# spent 9.28ms (968µs+8.31) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim which was called 83 times, avg 112µs/call: # 83 times (968µs+8.31ms) by Mail::SpamAssassin::Plugin::DKIM::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/DKIM.pm:420] at line 418 of Mail/SpamAssassin/Plugin/DKIM.pm, avg 112µs/call
sub add_to_addrlist_dkim {
147083866µs838.31ms add_to_addrlist_rcvd(@_);
# spent 8.31ms making 83 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd, avg 100µs/call
1471}
1472
1473sub remove_from_addrlist_dkim {
1474 my ($self, $listname, $addr, $domain) = @_;
1475 my $conf = $self->{conf};
1476 my $conf_lname = $conf->{$listname};
1477
1478 $addr = lc $addr;
1479 if ($conf_lname->{$addr}) {
1480 $domain = lc $domain;
1481 my $domains_listref = $conf_lname->{$addr}{domain};
1482 # removing $domain from the list
1483 my @replacement = grep { lc $_ ne $domain } @$domains_listref;
1484 if (!@replacement) { # nothing left, remove the entire addr entry
1485 delete($conf_lname->{$addr});
1486 } elsif (@replacement != @$domains_listref) { # anything changed?
1487 $conf_lname->{$addr}{domain} = \@replacement;
1488 }
1489 }
1490}
1491
1492
1493###########################################################################
1494
1495
# spent 30.0ms (4.63+25.3) within Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file which was called 58 times, avg 517µs/call: # 58 times (4.63ms+25.3ms) by Mail::SpamAssassin::Conf::Parser::parse at line 342, avg 517µs/call
sub fix_path_relative_to_current_file {
149658253µs my ($self, $path) = @_;
1497
1498 # the path may be specified as "~/foo", so deal with that
149958604µs5819.7ms $path = $self->{conf}->{main}->sed_path($path);
# spent 19.7ms making 58 calls to Mail::SpamAssassin::sed_path, avg 340µs/call
1500
150158972µs581.09ms if (!File::Spec->file_name_is_absolute ($path)) {
# spent 1.09ms making 58 calls to File::Spec::Unix::file_name_is_absolute, avg 19µs/call
150258662µs582.64ms my ($vol, $dirs, $file) = File::Spec->splitpath ($self->{currentfile});
# spent 2.64ms making 58 calls to File::Spec::Unix::splitpath, avg 46µs/call
150358564µs581.18ms $path = File::Spec->catpath ($vol, $dirs, $path);
# spent 1.18ms making 58 calls to File::Spec::Unix::catpath, avg 20µs/call
150458727µs58698µs dbg("config: fixed relative path: $path");
# spent 698µs making 58 calls to Mail::SpamAssassin::Logger::dbg, avg 12µs/call
1505 }
150658551µs return $path;
1507}
1508
1509###########################################################################
1510
1511sub lint_warn {
1512 my ($self, $msg, $rule, $iserror) = @_;
1513
1514 if (!defined $iserror) { $iserror = 1; }
1515
1516 if ($self->{conf}->{main}->{lint_callback}) {
1517 $self->{conf}->{main}->{lint_callback}->(
1518 msg => $msg,
1519 rule => $rule,
1520 iserror => $iserror
1521 );
1522 }
1523 elsif ($self->{conf}->{lint_rules}) {
1524 warn $msg."\n";
1525 }
1526 else {
1527 info($msg);
1528 }
1529
1530 if ($iserror) {
1531 $self->{conf}->{errors}++;
1532 }
1533}
1534
1535###########################################################################
1536
1537sub get_if_stack_as_string {
1538 my ($self) = @_;
1539 return join ' ', map {
1540 $_->{conditional}
1541 } @{$self->{if_stack}};
1542}
1543
1544###########################################################################
1545
1546111µs1;
 
# spent 1.23s within Mail::SpamAssassin::Conf::Parser::CORE:match which was called 322611 times, avg 4µs/call: # 269448 times (614ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 994, avg 2µs/call # 16436 times (43.2ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 273, avg 3µs/call # 11321 times (463ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 41µs/call # 7210 times (20.3ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1303, avg 3µs/call # 2650 times (10.3ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 516, avg 4µs/call # 2074 times (8.74ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1181, avg 4µs/call # 2074 times (5.66ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1232, avg 3µs/call # 2067 times (5.74ms+0s) by Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions at line 657, avg 3µs/call # 1474 times (3.67ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 2µs/call # 1284 times (2.52ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 640, avg 2µs/call # 1284 times (2.18ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 642, avg 2µs/call # 1228 times (7.36ms+0s) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1326, avg 6µs/call # 1228 times (2.37ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 2µs/call # 606 times (1.94ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1216, avg 3µs/call # 548 times (7.58ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1219, avg 14µs/call # 508 times (7.17ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 14µs/call # 465 times (16.3ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 35µs/call # 379 times (4.76ms+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 876, avg 13µs/call # 136 times (675µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 302, avg 5µs/call # 68 times (380µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 308, avg 6µs/call # 55 times (422µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 588, avg 8µs/call # 34 times (98µs+0s) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 815, avg 3µs/call # 17 times (48µs+0s) by Mail::SpamAssassin::Conf::Parser::set_template_append at line 832, avg 3µs/call # 5 times (14µs+0s) by Mail::SpamAssassin::Conf::Parser::set_bool_value at line 749, avg 3µs/call # 4 times (39µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 722, avg 10µs/call # 4 times (12µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 719, avg 3µs/call # 3 times (9µs+0s) by Mail::SpamAssassin::Conf::Parser::set_string_value at line 771, avg 3µs/call # once (7µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 240
sub Mail::SpamAssassin::Conf::Parser::CORE:match; # opcode
# spent 137ms within Mail::SpamAssassin::Conf::Parser::CORE:regcomp which was called 15046 times, avg 9µs/call: # 11321 times (42.1ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 4µs/call # 1474 times (5.96ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 4µs/call # 1228 times (82.1ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 67µs/call # 508 times (2.84ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 6µs/call # 465 times (2.70ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 6µs/call # 50 times (840µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 17µs/call
sub Mail::SpamAssassin::Conf::Parser::CORE:regcomp; # opcode
# spent 20.1ms within Mail::SpamAssassin::Conf::Parser::CORE:sort which was called 11 times, avg 1.83ms/call: # 10 times (90µs+0s) by Mail::SpamAssassin::Conf::Parser::find_dup_rules at line 1063, avg 9µs/call # once (20.0ms+0s) by Mail::SpamAssassin::Conf::Parser::fix_priorities at line 1014
sub Mail::SpamAssassin::Conf::Parser::CORE:sort; # opcode
# spent 277ms within Mail::SpamAssassin::Conf::Parser::CORE:subst which was called 92819 times, avg 3µs/call: # 16436 times (66.5ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 279, avg 4µs/call # 16436 times (58.9ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 282, avg 4µs/call # 16436 times (38.1ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 281, avg 2µs/call # 16436 times (32.3ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 280, avg 2µs/call # 9050 times (21.5ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 2µs/call # 7576 times (25.8ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 291, avg 3µs/call # 6034 times (20.1ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1344, avg 3µs/call # 1686 times (3.31ms+0s) by Mail::SpamAssassin::Conf::Parser::find_dup_rules at line 1047, avg 2µs/call # 548 times (1.41ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1220, avg 3µs/call # 483 times (2.21ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1098, avg 5µs/call # 483 times (1.03ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1117, avg 2µs/call # 379 times (2.54ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1096, avg 7µs/call # 379 times (908µs+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1113, avg 2µs/call # 97 times (540µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1445, avg 6µs/call # 97 times (393µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 4µs/call # 97 times (232µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1442, avg 2µs/call # 50 times (442µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 9µs/call # 34 times (184µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1426, avg 5µs/call # 34 times (131µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 4µs/call # 34 times (84µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1423, avg 2µs/call # 14 times (89µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1345, avg 6µs/call
sub Mail::SpamAssassin::Conf::Parser::CORE:subst; # opcode
# spent 1.67ms within Mail::SpamAssassin::Conf::Parser::CORE:substcont which was called 479 times, avg 3µs/call: # 361 times (1.24ms+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 3µs/call # 118 times (425µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 4µs/call
sub Mail::SpamAssassin::Conf::Parser::CORE:substcont; # opcode