← Index
NYTProf Performance Profile   « line view »
For /usr/local/bin/sa-learn
  Run on Sun Nov 5 03:09:29 2017
Reported on Mon Nov 6 13:20:46 2017

Filename/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf/Parser.pm
StatementsExecuted 1032653 statements in 10.4s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
13832215.47s7.09sMail::SpamAssassin::Conf::Parser::::_meta_deps_recurseMail::SpamAssassin::Conf::Parser::_meta_deps_recurse (recurses: max depth 7, inclusive time 14.6s)
1111.83s5.03sMail::SpamAssassin::Conf::Parser::::parseMail::SpamAssassin::Conf::Parser::parse
3226112811.32s1.32sMail::SpamAssassin::Conf::Parser::::CORE:matchMail::SpamAssassin::Conf::Parser::CORE:match (opcode)
92819211272ms272msMail::SpamAssassin::Conf::Parser::::CORE:substMail::SpamAssassin::Conf::Parser::CORE:subst (opcode)
2074153226ms785msMail::SpamAssassin::Conf::Parser::::add_testMail::SpamAssassin::Conf::Parser::add_test
46511198ms252msMail::SpamAssassin::Conf::Parser::::is_meta_validMail::SpamAssassin::Conf::Parser::is_meta_valid
1504661157ms157msMail::SpamAssassin::Conf::Parser::::CORE:regcompMail::SpamAssassin::Conf::Parser::CORE:regcomp (opcode)
50821142ms240msMail::SpamAssassin::Conf::Parser::::handle_conditionalMail::SpamAssassin::Conf::Parser::handle_conditional
122811132ms238msMail::SpamAssassin::Conf::Parser::::is_regexp_validMail::SpamAssassin::Conf::Parser::is_regexp_valid
111120ms125msMail::SpamAssassin::Conf::Parser::::set_default_scoresMail::SpamAssassin::Conf::Parser::set_default_scores
111114ms137msMail::SpamAssassin::Conf::Parser::::fix_prioritiesMail::SpamAssassin::Conf::Parser::fix_priorities
111101ms105msMail::SpamAssassin::Conf::Parser::::find_dup_rulesMail::SpamAssassin::Conf::Parser::find_dup_rules
11188.7ms7.67sMail::SpamAssassin::Conf::Parser::::finish_parsingMail::SpamAssassin::Conf::Parser::finish_parsing
11175.2ms171msMail::SpamAssassin::Conf::Parser::::check_for_missing_descriptionsMail::SpamAssassin::Conf::Parser::check_for_missing_descriptions
12761157.0ms273msMail::SpamAssassin::Conf::Parser::::set_hash_key_valueMail::SpamAssassin::Conf::Parser::set_hash_key_value
3791151.1ms58.2msMail::SpamAssassin::Conf::Parser::::pack_eval_methodMail::SpamAssassin::Conf::Parser::pack_eval_method
12284344.6ms291msMail::SpamAssassin::Conf::Parser::::is_delimited_regexp_validMail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid
11133.1ms7.12sMail::SpamAssassin::Conf::Parser::::trace_meta_dependenciesMail::SpamAssassin::Conf::Parser::trace_meta_dependencies
112122.5ms22.5msMail::SpamAssassin::Conf::Parser::::CORE:sortMail::SpamAssassin::Conf::Parser::CORE:sort (opcode)
581111.5ms41.2msMail::SpamAssassin::Conf::Parser::::fix_path_relative_to_current_fileMail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file
1022210.2ms13.3msMail::SpamAssassin::Conf::Parser::::add_to_addrlist_rcvdMail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd
83119.77ms20.5msMail::SpamAssassin::Conf::Parser::::add_to_addrlist_dkimMail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim
43443433.80ms3.80msMail::SpamAssassin::Conf::Parser::::cond_clause_plugin_loadedMail::SpamAssassin::Conf::Parser::cond_clause_plugin_loaded
16112.98ms2.98msMail::SpamAssassin::Conf::Parser::::build_command_lutsMail::SpamAssassin::Conf::Parser::build_command_luts
34112.91ms4.09msMail::SpamAssassin::Conf::Parser::::add_to_addrlistMail::SpamAssassin::Conf::Parser::add_to_addrlist
55112.90ms4.59msMail::SpamAssassin::Conf::Parser::::cond_clause_can_or_hasMail::SpamAssassin::Conf::Parser::cond_clause_can_or_has
479212.18ms2.18msMail::SpamAssassin::Conf::Parser::::CORE:substcontMail::SpamAssassin::Conf::Parser::CORE:substcont (opcode)
16111.48ms1.48msMail::SpamAssassin::Conf::Parser::::set_defaults_from_command_listMail::SpamAssassin::Conf::Parser::set_defaults_from_command_list
3411987µs5.24msMail::SpamAssassin::Conf::Parser::::set_addrlist_valueMail::SpamAssassin::Conf::Parser::set_addrlist_value
551414960µs5.55msMail::SpamAssassin::Conf::Parser::::cond_clause_canMail::SpamAssassin::Conf::Parser::cond_clause_can
161616791µs5.25msMail::SpamAssassin::Conf::Parser::::register_commandsMail::SpamAssassin::Conf::Parser::register_commands
2111427µs427µsMail::SpamAssassin::Conf::Parser::::setup_default_code_cbMail::SpamAssassin::Conf::Parser::setup_default_code_cb
1711324µs368µsMail::SpamAssassin::Conf::Parser::::set_template_appendMail::SpamAssassin::Conf::Parser::set_template_append
511164µs184µsMail::SpamAssassin::Conf::Parser::::set_bool_valueMail::SpamAssassin::Conf::Parser::set_bool_value
411158µs302µsMail::SpamAssassin::Conf::Parser::::set_numeric_valueMail::SpamAssassin::Conf::Parser::set_numeric_value
31183µs92µsMail::SpamAssassin::Conf::Parser::::set_string_valueMail::SpamAssassin::Conf::Parser::set_string_value
11142µs42µsMail::SpamAssassin::Conf::Parser::::BEGIN@137Mail::SpamAssassin::Conf::Parser::BEGIN@137
21135µs35µsMail::SpamAssassin::Conf::Parser::::set_template_clearMail::SpamAssassin::Conf::Parser::set_template_clear
11130µs87µsMail::SpamAssassin::Conf::Parser::::BEGIN@592Mail::SpamAssassin::Conf::Parser::BEGIN@592
11130µs30µsMail::SpamAssassin::Conf::Parser::::newMail::SpamAssassin::Conf::Parser::new
11124µs155µsMail::SpamAssassin::Conf::Parser::::BEGIN@139Mail::SpamAssassin::Conf::Parser::BEGIN@139
11123µs239µsMail::SpamAssassin::Conf::Parser::::BEGIN@140Mail::SpamAssassin::Conf::Parser::BEGIN@140
11121µs21µsMail::SpamAssassin::Conf::Parser::::lint_trusted_networksMail::SpamAssassin::Conf::Parser::lint_trusted_networks
11120µs27µsMail::SpamAssassin::Conf::Parser::::BEGIN@145Mail::SpamAssassin::Conf::Parser::BEGIN@145
11120µs60µsMail::SpamAssassin::Conf::Parser::::BEGIN@144Mail::SpamAssassin::Conf::Parser::BEGIN@144
11120µs91µsMail::SpamAssassin::Conf::Parser::::BEGIN@146Mail::SpamAssassin::Conf::Parser::BEGIN@146
11119µs530µsMail::SpamAssassin::Conf::Parser::::BEGIN@138Mail::SpamAssassin::Conf::Parser::BEGIN@138
11119µs30µsMail::SpamAssassin::Conf::Parser::::BEGIN@143Mail::SpamAssassin::Conf::Parser::BEGIN@143
11118µs81µsMail::SpamAssassin::Conf::Parser::::BEGIN@148Mail::SpamAssassin::Conf::Parser::BEGIN@148
11113µs13µsMail::SpamAssassin::Conf::Parser::::lint_checkMail::SpamAssassin::Conf::Parser::lint_check
11111µs11µsMail::SpamAssassin::Conf::Parser::::BEGIN@141Mail::SpamAssassin::Conf::Parser::BEGIN@141
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
137271µs142µs
# spent 42µs within Mail::SpamAssassin::Conf::Parser::BEGIN@137 which was called: # once (42µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 137
use Mail::SpamAssassin::Conf;
# spent 42µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@137
138263µs21.04ms
# spent 530µs (19+511) within Mail::SpamAssassin::Conf::Parser::BEGIN@138 which was called: # once (19µs+511µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 138
use Mail::SpamAssassin::Constants qw(:sa);
# spent 530µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@138 # spent 511µs making 1 call to Exporter::import
139262µs2286µs
# spent 155µs (24+131) within Mail::SpamAssassin::Conf::Parser::BEGIN@139 which was called: # once (24µs+131µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 139
use Mail::SpamAssassin::Logger;
# spent 155µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@139 # spent 131µs making 1 call to Exporter::import
140262µs2455µs
# spent 239µs (23+216) within Mail::SpamAssassin::Conf::Parser::BEGIN@140 which was called: # once (23µs+216µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 140
use Mail::SpamAssassin::Util qw(untaint_var);
# spent 239µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@140 # spent 216µs making 1 call to Exporter::import
141248µs111µs
# spent 11µs within Mail::SpamAssassin::Conf::Parser::BEGIN@141 which was called: # once (11µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 141
use Mail::SpamAssassin::NetSet;
# spent 11µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@141
142
143250µs241µs
# spent 30µs (19+11) within Mail::SpamAssassin::Conf::Parser::BEGIN@143 which was called: # once (19µs+11µ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 11µs making 1 call to strict::import
144254µs299µs
# spent 60µs (20+40) within Mail::SpamAssassin::Conf::Parser::BEGIN@144 which was called: # once (20µs+40µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 144
use warnings;
# spent 60µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@144 # spent 40µs making 1 call to warnings::import
145254µs234µs
# spent 27µs (20+7) within Mail::SpamAssassin::Conf::Parser::BEGIN@145 which was called: # once (20µs+7µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 145
use bytes;
# spent 27µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@145 # spent 7µs making 1 call to bytes::import
146260µs2162µs
# spent 91µs (20+71) within Mail::SpamAssassin::Conf::Parser::BEGIN@146 which was called: # once (20µs+71µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 146
use re 'taint';
# spent 91µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@146 # spent 71µs making 1 call to re::import
147
14812µs
# spent 81µs (18+62) within Mail::SpamAssassin::Conf::Parser::BEGIN@148 which was called: # once (18µs+62µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 150
use vars qw{
149 @ISA
15014.15ms2143µs};
# spent 81µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@148 # spent 62µ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;
15813µs $class = ref($class) || $class;
15912µs my ($conf) = @_;
160
16113µs my $self = {
162 'conf' => $conf
163 };
164
16513µs $self->{command_luts} = { };
16614µs $self->{command_luts}->{frequent} = { };
16714µs $self->{command_luts}->{remaining} = { };
168
16912µs bless ($self, $class);
170110µs $self;
171}
172
173###########################################################################
174
175
# spent 5.25ms (791µs+4.46) within Mail::SpamAssassin::Conf::Parser::register_commands which was called 16 times, avg 328µs/call: # once (104µs+2.17ms) by Mail::SpamAssassin::Conf::new at line 4516 of Mail/SpamAssassin/Conf.pm # once (49µs+601µs) by Mail::SpamAssassin::Plugin::TxRep::set_config at line 1067 of Mail/SpamAssassin/Plugin/TxRep.pm # once (54µs+267µs) by Mail::SpamAssassin::Plugin::URIDNSBL::set_config at line 813 of Mail/SpamAssassin/Plugin/URIDNSBL.pm # once (44µs+174µs) by Mail::SpamAssassin::Plugin::SPF::set_config at line 228 of Mail/SpamAssassin/Plugin/SPF.pm # once (45µs+163µs) by Mail::SpamAssassin::Plugin::Hashcash::set_config at line 158 of Mail/SpamAssassin/Plugin/Hashcash.pm # once (47µs+157µs) by Mail::SpamAssassin::Plugin::DKIM::set_config at line 502 of Mail/SpamAssassin/Plugin/DKIM.pm # once (49µs+152µs) by Mail::SpamAssassin::Plugin::FreeMail::set_config at line 213 of Mail/SpamAssassin/Plugin/FreeMail.pm # once (37µs+154µs) by Mail::SpamAssassin::Plugin::ReplaceTags::set_config at line 292 of Mail/SpamAssassin/Plugin/ReplaceTags.pm # once (53µs+110µs) by Mail::SpamAssassin::Plugin::SpamCop::set_config at line 157 of Mail/SpamAssassin/Plugin/SpamCop.pm # once (45µs+105µs) by Mail::SpamAssassin::Plugin::Razor2::set_config at line 134 of Mail/SpamAssassin/Plugin/Razor2.pm # once (52µs+95µs) by Mail::SpamAssassin::Plugin::AutoLearnThreshold::set_config at line 146 of Mail/SpamAssassin/Plugin/AutoLearnThreshold.pm # once (48µs+66µs) by Mail::SpamAssassin::Plugin::AskDNS::set_config at line 359 of Mail/SpamAssassin/Plugin/AskDNS.pm # once (36µs+73µs) by Mail::SpamAssassin::Plugin::WhiteListSubject::set_config at line 109 of Mail/SpamAssassin/Plugin/WhiteListSubject.pm # once (45µs+61µs) by Mail::SpamAssassin::Plugin::VBounce::set_config at line 90 of Mail/SpamAssassin/Plugin/VBounce.pm # once (46µs+59µs) by Mail::SpamAssassin::Plugin::URIDetail::set_config at line 150 of Mail/SpamAssassin/Plugin/URIDetail.pm # once (37µs+50µs) by Mail::SpamAssassin::Plugin::MIMEHeader::set_config at line 163 of Mail/SpamAssassin/Plugin/MIMEHeader.pm
sub register_commands {
1761636µs my($self, $arrref) = @_;
1771666µs my $conf = $self->{conf};
178
17916134µs161.48ms $self->set_defaults_from_command_list($arrref);
# spent 1.48ms making 16 calls to Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list, avg 93µs/call
18016133µs162.98ms $self->build_command_luts($arrref);
# spent 2.98ms making 16 calls to Mail::SpamAssassin::Conf::Parser::build_command_luts, avg 186µs/call
18148365µs push(@{$conf->{registered_commands}}, @{$arrref});
182}
183
184
# spent 1.48ms within Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list which was called 16 times, avg 93µs/call: # 16 times (1.48ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 179, avg 93µs/call
sub set_defaults_from_command_list {
1851633µs my ($self, $arrref) = @_;
1861644µs my $conf = $self->{conf};
18732259µs foreach my $cmd (@{$arrref}) {
188 # note! exists, not defined -- we want to be able to set
189 # "undef" default values.
190203860µs if (exists($cmd->{default})) {
191110342µs $conf->{$cmd->{setting}} = $cmd->{default};
192 }
193 }
194}
195
196
# spent 2.98ms within Mail::SpamAssassin::Conf::Parser::build_command_luts which was called 16 times, avg 186µs/call: # 16 times (2.98ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 180, avg 186µs/call
sub build_command_luts {
1971632µs my ($self, $arrref) = @_;
198
1991645µs my $conf = $self->{conf};
200
2011630µs my $set;
20232242µs foreach my $cmd (@{$arrref}) {
203 # first off, decide what set this is in.
204210660µs if ($cmd->{is_frequent}) { $set = 'frequent'; }
205196339µs else { $set = 'remaining'; }
206
207 # next, its priority (used to ensure frequently-used params
208 # are parsed first)
209203401µs my $cmdname = $cmd->{command} || $cmd->{setting};
210203570µs $self->{command_luts}->{$set}->{$cmdname} = $cmd;
211
212205686µs if ($cmd->{aliases} && scalar @{$cmd->{aliases}} > 0) {
213415µs foreach my $name (@{$cmd->{aliases}}) {
214210µs $self->{command_luts}->{$set}->{$name} = $cmd;
215 }
216 }
217 }
218}
219
220###########################################################################
221
222
# spent 5.03s (1.83+3.20) within Mail::SpamAssassin::Conf::Parser::parse which was called: # once (1.83s+3.20s) by Mail::SpamAssassin::Conf::parse_rules at line 4623 of Mail/SpamAssassin/Conf.pm
sub parse {
22315µ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'};
23612µs $lang ||= $ENV{'LC_MESSAGES'};
23712µs $lang ||= $ENV{'LANG'};
23813µs $lang ||= 'C'; # Nothing set means C/POSIX
239
240122µs18µs if ($lang =~ /^(C|POSIX)$/) {
# spent 8µs making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:match
24113µ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};
249213µs my %migrated_keys = map { $_ => 1 }
250 @Mail::SpamAssassin::Conf::MIGRATED_SETTINGS;
251
25214µs $self->{currentfile} = '(no file)';
25312µs my $skip_parsing = 0;
25412µs my @curfile_stack;
255 my @if_stack;
2561461µs my @conf_lines = split (/\n/, $_[1]);
25712µs my $line;
25815µs $self->{if_stack} = \@if_stack;
25914µs $self->{file_scoped_attrs} = { };
260
26114µs my $keepmetadata = $conf->{main}->{keep_config_parsing_metadata};
262
263189.8ms while (defined ($line = shift @conf_lines)) {
2641643651.8ms 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
27316436227ms1643646.1ms if ($line =~ /^\# UPDATE version (\d+)$/) {
# spent 46.1ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
27415µs for ($self->{currentfile}) { # just aliasing, not a loop
275110µs $conf->{update_version}{$_} = $1 if defined $_ && $_ ne '(no file)';
276 }
277 }
278
27916436227ms1643665.2ms $line =~ s/(?<!\\)#.*$//; # remove comments
# spent 65.2ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
28016436192ms1643633.2ms $line =~ s/\\#/#/g; # hash chars are escaped, so unescape them
# spent 33.2ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
28116436208ms1643641.3ms $line =~ s/^\s+//; # remove leading whitespace
# spent 41.3ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
28216436272ms1643655.1ms $line =~ s/\s+$//; # remove tailing whitespace
# spent 55.1ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
2831643637.7ms next unless($line); # skip empty lines
284
285 # handle i18n
28610524161ms1199833.8ms if ($line =~ s/^lang\s+(\S+)\s+//) { next if ($lang !~ /^$1/i); }
# spent 23.4ms making 9050 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call # spent 6.59ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 4µs/call # spent 3.81ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
287
288757662.6ms my($key, $value) = split(/\s+/, $line, 2);
289757618.9ms $key = lc $key;
290 # convert all dashes in setting name to underscores.
2917576141ms757619.1ms $key =~ s/-/_/g;
# spent 19.1ms making 7576 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
292757613.6ms $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
298757612.0ms my $parse_error; # undef by default, may be overridden
299
300 # File/line number assertions
301757615.3ms if ($key eq 'file') {
3021361.70ms136711µs if ($value =~ /^start\s+(.+)$/) {
# spent 711µs making 136 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call
30368291µs push (@curfile_stack, $self->{currentfile});
30468276µs $self->{currentfile} = $1;
30568322µs next;
306 }
307
30868884µs68340µs if ($value =~ /^end\s/) {
# spent 340µs making 68 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call
30968300µs $self->{file_scoped_attrs} = { };
310
31168178µ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 }
32868147µs $skip_parsing = 0;
329
33068294µs my $curfile = pop @curfile_stack;
33168248µs if (defined $curfile) {
33268230µs $self->{currentfile} = $curfile;
333 } else {
334 $self->{currentfile} = '(no file)';
335 }
33668295µs next;
337 }
338 }
339
340 # now handle the commands.
341744013.3ms if ($key eq 'include') {
34258659µs5841.2ms $value = $self->fix_path_relative_to_current_file($value);
# spent 41.2ms making 58 calls to Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file, avg 711µs/call
34358742µs5830.2ms my $text = $conf->{main}->read_cf($value, 'included file');
# spent 30.2ms making 58 calls to Mail::SpamAssassin::read_cf, avg 520µs/call
3445831.1ms unshift (@conf_lines, split (/\n/, $text));
34558858µs next;
346 }
347
348738212.9ms if ($key eq 'ifplugin') {
3493605.99ms360160ms $self->handle_conditional ($key, "plugin ($value)",
# spent 160ms making 360 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 446µs/call
350 \@if_stack, \$skip_parsing);
3513601.63ms next;
352 }
353
354702212.3ms if ($key eq 'if') {
3551481.78ms14879.4ms $self->handle_conditional ($key, $value,
# spent 79.4ms making 148 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 537µs/call
356 \@if_stack, \$skip_parsing);
357148762µs next;
358 }
359
360687411.6ms 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;
36827µs next;
369 }
370
371 # and the endif statement:
372687212.3ms if ($key eq 'endif') {
3735081.45ms my $lastcond = pop @if_stack;
374508943µs if (!defined $lastcond) {
375 $parse_error = "config: found endif without matching conditional";
376 goto failed_line;
377 }
378
3795081.42ms $skip_parsing = $lastcond->{skip_parsing};
3805083.43ms next;
381 }
382
383 # preprocessing? skip all other commands
384636410.5ms next if $skip_parsing;
385
386618410.4ms if ($key eq 'require_version') {
387 # if it wasn't replaced during install, assume current version ...
3881736µs next if ($value eq "\@\@VERSION\@\@");
389
3901750µ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
4001741µ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 }
4101768µs next;
411 }
412
413616718.3ms my $cmd = $lut_frequent->{$key}; # check the frequent command set
414616713.8ms if (!$cmd) {
41522085.47ms $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.
420616711.2ms if ($cmd) {
421566610.8ms 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
432566612.7ms if (!$cmd->{code}) {
43321158µs21427µs if (! $self->setup_default_code_cb($cmd)) {
# spent 427µs making 21 calls to Mail::SpamAssassin::Conf::Parser::setup_default_code_cb, avg 20µs/call
434 goto failed_line;
435 }
436 }
437
4381133267.1ms56662.14s my $ret = &{$cmd->{code}} ($conf, $cmd->{setting}, $value, $line);
# spent 510ms making 27 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:4145], avg 18.9ms/call # spent 324ms making 781 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2981], avg 415µs/call # spent 322ms making 465 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3174], avg 693µs/call # spent 273ms making 1276 calls to Mail::SpamAssassin::Conf::Parser::set_hash_key_value, avg 214µs/call # spent 233ms making 655 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3020], avg 356µs/call # spent 189ms making 811 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:280], avg 233µs/call # spent 87.4ms making 30 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1685], avg 2.91ms/call # spent 41.1ms making 46 calls to Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[Mail/SpamAssassin/Plugin/MIMEHeader.pm:160], avg 893µs/call # spent 30.0ms making 83 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:420], avg 362µs/call # spent 28.2ms making 459 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3750], avg 61µs/call # spent 24.1ms making 71 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3052], avg 340µs/call # spent 15.9ms making 128 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3557], avg 124µs/call # spent 13.9ms making 40 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3088], avg 347µs/call # spent 6.48ms making 85 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:468], avg 76µs/call # spent 5.85ms making 270 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2044], avg 22µs/call # spent 5.28ms making 15 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2701], avg 352µs/call # spent 5.24ms making 34 calls to Mail::SpamAssassin::Conf::Parser::set_addrlist_value, avg 154µs/call # spent 3.87ms making 63 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:783], avg 61µs/call # spent 3.76ms making 21 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:662], avg 179µs/call # spent 3.75ms making 19 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:433], avg 198µs/call # spent 3.15ms making 64 calls to Mail::SpamAssassin::Plugin::ReplaceTags::__ANON__[Mail/SpamAssassin/Plugin/ReplaceTags.pm:266], avg 49µs/call # spent 2.70ms making 77 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3206], avg 35µs/call # spent 2.33ms making 13 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3122], avg 179µs/call # spent 1.91ms making 48 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3781], avg 40µs/call # spent 1.20ms making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3804] # spent 865µs making 5 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:935], avg 173µs/call # spent 630µs making 2 calls to Mail::SpamAssassin::Plugin::AskDNS::__ANON__[Mail/SpamAssassin/Plugin/AskDNS.pm:356], avg 315µs/call # spent 368µs making 17 calls to Mail::SpamAssassin::Conf::Parser::set_template_append, avg 22µs/call # spent 310µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:609] # spent 302µs making 4 calls to Mail::SpamAssassin::Conf::Parser::set_numeric_value, avg 76µs/call # spent 215µs making 36 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3402], avg 6µs/call # spent 184µs making 5 calls to Mail::SpamAssassin::Conf::Parser::set_bool_value, avg 37µs/call # spent 132µs making 2 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1419], avg 66µs/call # spent 132µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3835] # spent 92µs making 3 calls to Mail::SpamAssassin::Conf::Parser::set_string_value, avg 31µs/call # spent 90µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:581] # spent 88µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3858] # spent 51µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1007] # spent 41µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1054] # spent 35µs making 2 calls to Mail::SpamAssassin::Conf::Parser::set_template_clear, avg 18µs/call # spent 22µs making 1 call to Mail::SpamAssassin::Plugin::TxRep::__ANON__[Mail/SpamAssassin/Plugin/TxRep.pm:495] # spent 17µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1437]
439
440566612.5ms 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 {
462566627.0ms next;
463 }
464 }
465
466 # last ditch: try to see if the plugins know what to do with it
4675016.95ms501153ms if ($conf->{main}->call_plugins("parse_config", {
# spent 153ms making 501 calls to Mail::SpamAssassin::call_plugins, avg 305µ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.68ms 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
49919µs113µs $self->lint_check();
# spent 13µs making 1 call to Mail::SpamAssassin::Conf::Parser::lint_check
50019µs1125ms $self->set_default_scores();
501116µs1171ms $self->check_for_missing_descriptions();
502
503123µs delete $self->{scoresonly};
504}
505
506
# spent 240ms (142+97.7) within Mail::SpamAssassin::Conf::Parser::handle_conditional which was called 508 times, avg 472µs/call: # 360 times (100ms+60.1ms) by Mail::SpamAssassin::Conf::Parser::parse at line 349, avg 446µs/call # 148 times (41.9ms+37.6ms) by Mail::SpamAssassin::Conf::Parser::parse at line 355, avg 537µs/call
sub handle_conditional {
5075082.82ms my ($self, $key, $value, $if_stack_ref, $skip_parsing_ref) = @_;
5085081.44ms my $conf = $self->{conf};
509
510508976µs my $lexer = ARITH_EXPRESSION_LEXER;
51150823.2ms101610.9ms my @tokens = ($value =~ m/($lexer)/g);
# spent 7.60ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 15µs/call # spent 3.31ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 7µs/call
512
5135081.21ms my $eval = '';
514508956µs my $bad = 0;
5155082.12ms foreach my $token (@tokens) {
516216146.3ms265011.9ms if ($token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/) {
# spent 11.9ms 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.99ms116443.7ms my $u = untaint_var($token);
# spent 43.7ms making 1164 calls to Mail::SpamAssassin::Util::untaint_var, avg 38µs/call
51911642.65ms $eval .= $u . " ";
520 }
521 elsif ($token eq 'plugin') {
522 # replace with a method call
523434835µs $eval .= '$self->cond_clause_plugin_loaded';
524 }
525 elsif ($token eq 'can') {
526 # replace with a method call
52755118µ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') {
5341952µs $eval .= $Mail::SpamAssassin::VERSION." ";
535 }
536 elsif ($token eq 'perl_version') {
537 $eval .= $]." ";
538 }
539 elsif ($token =~ /^\w[\w\:]+$/) { # class name
5404893.34ms48921.8ms my $u = untaint_var($token);
# spent 21.8ms making 489 calls to Mail::SpamAssassin::Util::untaint_var, avg 45µs/call
5414891.35ms $eval .= '"' . $u . '" ';
542 }
543 else {
544 $bad++;
545 warn "config: unparseable chars in 'if $value': '$token'\n";
546 }
547 }
548
549508904µs if ($bad) {
550 $self->lint_warn("bad 'if' line, in \"$self->{currentfile}\"", undef);
551 return -1;
552 }
553
55410166.27ms push (@{$if_stack_ref}, {
555 type => 'if',
556 conditional => $value,
557 skip_parsing => $$skip_parsing_ref
558 });
559
56050837.0ms if (eval $eval) {
# spent 879µs executing statements in 72 string evals (merged) # spent 705µs executing statements in 59 string evals (merged) # spent 490µs executing statements in 41 string evals (merged) # spent 322µs executing statements in 26 string evals (merged) # spent 289µs executing statements in 25 string evals (merged) # spent 275µs executing statements in 21 string evals (merged) # spent 268µs executing statements in 20 string evals (merged) # spent 208µs executing statements in 15 string evals (merged) # spent 170µs executing statements in 14 string evals (merged) # spent 155µs executing statements in 13 string evals (merged) # spent 140µs executing statements in 12 string evals (merged) # spent 138µs executing statements in 11 string evals (merged) # spent 133µs executing statements in 11 string evals (merged) # spent 101µs executing statements in 7 string evals (merged) # spent 95µs executing statements in 8 string evals (merged) # spent 92µs executing statements in 7 string evals (merged) # spent 90µs executing statements in 7 string evals (merged) # spent 90µs executing statements in 7 string evals (merged) # spent 83µs executing statements in 6 string evals (merged) # spent 81µs executing statements in 7 string evals (merged) # spent 76µs executing statements in 7 string evals (merged) # spent 76µs executing statements in 6 string evals (merged) # spent 70µs executing statements in 6 string evals (merged) # spent 70µs executing statements in 5 string evals (merged) # spent 68µs executing statements in 12 string evals (merged) # spent 67µs executing statements in 5 string evals (merged) # spent 64µs executing statements in 5 string evals (merged) # spent 62µs executing statements in 5 string evals (merged) # spent 60µs executing statements in 5 string evals (merged) # spent 50µs executing statements in 4 string evals (merged) # spent 49µs executing statements in 4 string evals (merged) # spent 46µs executing statements in 4 string evals (merged) # spent 37µs executing statements in 3 string evals (merged) # spent 37µs executing statements in 3 string evals (merged) # spent 36µs executing statements in 3 string evals (merged) # spent 35µs executing statements in 2 string evals (merged) # spent 34µs executing statements in 3 string evals (merged) # spent 33µs executing statements in 2 string evals (merged) # spent 30µs executing statements in 2 string evals (merged) # spent 30µs executing statements in 2 string evals (merged) # spent 28µs executing statements in 2 string evals (merged) # spent 27µs executing statements in 2 string evals (merged) # spent 27µs executing statements in 2 string evals (merged) # spent 25µs executing statements in 2 string evals (merged) # spent 25µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 20µs executing statements in string eval # 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 15µs executing statements in string eval # spent 14µ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 11µs executing statements in string eval # spent 10µ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 {
564127322µs warn "config: error in $key - $eval: $@" if $@ ne '';
565127305µs $$skip_parsing_ref = 1;
566 }
567}
568
569# functions supported in the "if" eval:
570
# spent 3.80ms within Mail::SpamAssassin::Conf::Parser::cond_clause_plugin_loaded which was called 434 times, avg 9µs/call: # 72 times (626µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 119)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 59 times (442µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 287)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call # 41 times (317µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 132)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 26 times (194µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 823)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call # 25 times (210µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 154)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 20 times (180µ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 (135µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 289)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 14 times (140µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 128)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 13 times (110µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 126)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 12 times (110µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 279)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 11 times (117µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 170)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call # 11 times (102µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 201)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 8 times (74µ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 (73µ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 (65µ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 278)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 7 times (54µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 276)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 7 times (52µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 754)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call # 6 times (68µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 523)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call # 6 times (59µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 285)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 5 times (51µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 296)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 5 times (50µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 473)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 5 times (47µ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 (45µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 335)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 4 times (41µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 347)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 4 times (40µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 284)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 4 times (35µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 945)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 3 times (28µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 131)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 3 times (20µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 304)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call # 2 times (31µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 286)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 16µs/call # 2 times (27µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 348)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 14µs/call # 2 times (27µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 925)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 14µs/call # 2 times (23µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 129)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call # 2 times (23µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 363)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call # 2 times (22µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 261)[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 1007)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call # 2 times (19µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 133)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # once (15µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 942)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (15µ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 231)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (9µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 277)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (8µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 372)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (7µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 116)[Mail/SpamAssassin/Conf/Parser.pm:560]
sub cond_clause_plugin_loaded {
5714348.21ms return $_[0]->{conf}->{plugins_loaded}->{$_[1]};
572}
573
574
# spent 5.55ms (960µs+4.59) within Mail::SpamAssassin::Conf::Parser::cond_clause_can which was called 55 times, avg 101µs/call: # 21 times (362µs+1.85ms) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 634)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 106µs/call # 7 times (106µs+531µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 932)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 91µs/call # 6 times (126µs+466µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 718)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 99µs/call # 5 times (80µs+388µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 290)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 93µs/call # 3 times (63µs+282µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 940)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 115µs/call # 3 times (50µs+240µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 947)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 96µs/call # 2 times (37µs+183µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 531)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 110µs/call # 2 times (33µs+163µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 120)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 98µs/call # once (21µs+88µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 299)[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 (18µs+83µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 529)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (16µs+80µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 117)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (16µs+76µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1075)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (12µs+64µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 118)[Mail/SpamAssassin/Conf/Parser.pm:560]
sub cond_clause_can {
57555138µs my ($self, $method) = @_;
576551.01ms554.59ms $self->cond_clause_can_or_has('can', $method);
# spent 4.59ms making 55 calls to Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has, avg 83µ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.59ms (2.90+1.68) within Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has which was called 55 times, avg 83µs/call: # 55 times (2.90ms+1.68ms) by Mail::SpamAssassin::Conf::Parser::cond_clause_can at line 576, avg 83µs/call
sub cond_clause_can_or_has {
58555130µs my ($self, $fn_name, $method) = @_;
586
58755394µs local($1,$2);
588551.02ms55440µs if (!defined $method) {
# spent 440µ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.1ms2143µs
# spent 87µs (30+56) within Mail::SpamAssassin::Conf::Parser::BEGIN@592 which was called: # once (30µs+56µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 592
no strict "refs";
# spent 87µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@592 # spent 56µs making 1 call to strict::unimport
59355229µs my($module, $meth) = ($1, $2);
594 return 1 if UNIVERSAL::can($module,$meth) &&
5951102.51ms1101.24ms ( $fn_name eq 'has' || &{$method}() );
# spent 618µs making 55 calls to UNIVERSAL::can, avg 11µs/call # spent 301µs making 24 calls to Mail::SpamAssassin::Conf::feature_bug6558_free, avg 13µs/call # spent 101µs making 10 calls to Mail::SpamAssassin::Plugin::BodyEval::has_check_body_length, avg 10µs/call # spent 70µs making 7 calls to Mail::SpamAssassin::Conf::perl_min_version_5010000, avg 10µs/call # spent 59µs making 5 calls to Mail::SpamAssassin::Plugin::SPF::has_check_for_spf_errors, avg 12µs/call # spent 21µs making 2 calls to Mail::SpamAssassin::Plugin::MIMEEval::has_check_abundant_unicode_ratio, avg 11µs/call # spent 19µs making 2 calls to Mail::SpamAssassin::Conf::feature_registryboundaries, avg 10µs/call # spent 15µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::has_tflags_domains_only # spent 10µs making 1 call to Mail::SpamAssassin::Plugin::MIMEEval::has_check_for_ascii_text_illegal # spent 10µs making 1 call to Mail::SpamAssassin::Conf::feature_originating_ip_headers # spent 9µs making 1 call to Mail::SpamAssassin::Conf::feature_yesno_takes_args # spent 8µs making 1 call to Mail::SpamAssassin::Conf::feature_dns_local_ports_permit_avoid
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 13µs within Mail::SpamAssassin::Conf::Parser::lint_check which was called: # once (13µ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
611112µ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 125ms (120+4.91) within Mail::SpamAssassin::Conf::Parser::set_default_scores which was called: # once (120ms+4.91ms) by Mail::SpamAssassin::Conf::Parser::parse at line 500
sub set_default_scores {
63412µs my ($self) = @_;
63512µs my $conf = $self->{conf};
636
637206932.0ms while ( my $k = each %{$conf->{tests}} ) {
63820675.95ms if ( ! exists $conf->{scores}->{$k} ) {
639 # T_ rules (in a testing probationary period) get low, low scores
640128415.7ms12842.76ms my $set_score = ($k =~/^T_/) ? 0.01 : 1.0;
# spent 2.76ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
641
642128426.0ms12842.15ms $set_score = -$set_score if ( ($conf->{tflags}->{$k}||'') =~ /\bnice\b/ );
# spent 2.15ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
64312848.57ms for my $index (0..3) {
644513636.3ms $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 171ms (75.2+96.3) within Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions which was called: # once (75.2ms+96.3ms) by Mail::SpamAssassin::Conf::Parser::parse at line 501
sub check_for_missing_descriptions {
65314µs my ($self) = @_;
65414µs my $conf = $self->{conf};
655
656206930.4ms while ( my $k = each %{$conf->{tests}} ) {
657206737.3ms20675.73ms if ($k !~ m/^(?:T_|__)/i) {
# spent 5.73ms making 2067 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
6588157.06ms81590.0ms if ( ! exists $conf->{descriptions}->{$k} ) {
# spent 90.0ms making 815 calls to Mail::SpamAssassin::Util::TieOneStringHash::EXISTS, avg 110µs/call
65969649µs69551µs dbg("config: warning: no description set for $k");
# spent 551µs making 69 calls to Mail::SpamAssassin::Logger::dbg, avg 8µs/call
660 }
661 }
662 }
663}
664
665###########################################################################
666
667
# spent 427µs within Mail::SpamAssassin::Conf::Parser::setup_default_code_cb which was called 21 times, avg 20µs/call: # 21 times (427µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 433, avg 20µs/call
sub setup_default_code_cb {
6682142µs my ($self, $cmd) = @_;
6692189µs my $type = $cmd->{type};
670
67121109µ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 }
70521148µ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 302µs (158+144) within Mail::SpamAssassin::Conf::Parser::set_numeric_value which was called 4 times, avg 76µs/call: # 4 times (158µs+144µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 76µs/call
sub set_numeric_value {
717423µs my ($conf, $key, $value, $line) = @_;
718
719440µ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 }
722450µs422µs unless ($value =~ /^ [+-]? \d+ (?: \. \d* )? \z/sx) {
# spent 22µs making 4 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 6µ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
726476µs4110µs $conf->{$key} = untaint_var($value) + 0;
# spent 110µs making 4 calls to Mail::SpamAssassin::Util::untaint_var, avg 27µ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 184µs (164+20) within Mail::SpamAssassin::Conf::Parser::set_bool_value which was called 5 times, avg 37µs/call: # 5 times (164µs+20µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 37µs/call
sub set_bool_value {
747530µs my ($conf, $key, $value, $line) = @_;
748
749554µs520µs unless (defined $value && $value !~ /^$/) {
# spent 20µs making 5 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 4µ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;
755529µ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
765550µs $conf->{$key} = $value;
766}
767
768
# spent 92µs (83+10) within Mail::SpamAssassin::Conf::Parser::set_string_value which was called 3 times, avg 31µs/call: # 3 times (83µs+10µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 31µs/call
sub set_string_value {
769317µs my ($conf, $key, $value, $line) = @_;
770
771333µs310µs unless (defined $value && $value !~ /^$/) {
# spent 10µ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
775338µ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 273ms (57.0+216) within Mail::SpamAssassin::Conf::Parser::set_hash_key_value which was called 1276 times, avg 214µs/call: # 1276 times (57.0ms+216ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 214µs/call
sub set_hash_key_value {
80212767.73ms my ($conf, $key, $value, $line) = @_;
80312769.44ms my($k,$v) = split(/\s+/, $value, 2);
804
80512762.65ms unless (defined $v && $v ne '') {
806 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
807 }
808
809127634.5ms1684216ms $conf->{$key}->{$k} = $v; # keep tainted
# spent 121ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::STORE, avg 144µs/call # spent 94.7ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::FETCH, avg 112µs/call
810}
811
812
# spent 5.24ms (987µs+4.26) within Mail::SpamAssassin::Conf::Parser::set_addrlist_value which was called 34 times, avg 154µs/call: # 34 times (987µs+4.26ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 154µs/call
sub set_addrlist_value {
81334158µs my ($conf, $key, $value, $line) = @_;
814
81534438µs34167µs unless (defined $value && $value !~ /^$/) {
# spent 167µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call
816 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
817 }
81834543µs344.09ms $conf->{parser}->add_to_addrlist ($key, split (' ', $value)); # keep tainted
# spent 4.09ms making 34 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist, avg 120µ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 368µs (324+44) within Mail::SpamAssassin::Conf::Parser::set_template_append which was called 17 times, avg 22µs/call: # 17 times (324µs+44µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 22µs/call
sub set_template_append {
8311781µs my ($conf, $key, $value, $line) = @_;
83218146µs1744µs if ( $value =~ /^"(.*?)"$/ ) { $value = $1; }
# spent 44µs making 17 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
83317158µs $conf->{$key} .= $value."\n"; # keep tainted
834}
835
836
# spent 35µs within Mail::SpamAssassin::Conf::Parser::set_template_clear which was called 2 times, avg 18µs/call: # 2 times (35µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 18µs/call
sub set_template_clear {
837211µs my ($conf, $key, $value, $line) = @_;
83826µs unless (!defined $value || $value eq '') {
839 return $Mail::SpamAssassin::Conf::INVALID_VALUE;
840 }
841222µs $conf->{$key} = '';
842}
843
844###########################################################################
845
846
# spent 7.67s (88.7ms+7.58) within Mail::SpamAssassin::Conf::Parser::finish_parsing which was called: # once (88.7ms+7.58s) 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µs1685µs $conf->{main}->call_plugins("finish_parsing_start", { conf => $conf });
# spent 685µs making 1 call to Mail::SpamAssassin::call_plugins
854 } else {
855 $conf->{main}->call_plugins("user_conf_parsing_start", { conf => $conf });
856 }
857
8581474µs17.12s $self->trace_meta_dependencies();
8591478µs1137ms $self->fix_priorities();
# spent 137ms 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}
863111µs if (!$conf->{allow_user_rules}) {
864120µs1105ms $self->find_dup_rules(); # must be after fix_priorities()
# spent 105ms making 1 call to Mail::SpamAssassin::Conf::Parser::find_dup_rules
865 }
866
86718µs17µs dbg("config: finish parsing");
# spent 7µs making 1 call to Mail::SpamAssassin::Logger::dbg
868
869205830.9ms while (my ($name, $text) = each %{$conf->{tests}}) {
87020564.14ms my $type = $conf->{test_types}->{$name};
87120565.50ms my $priority = $conf->{priority}->{$name} || 0;
87220563.79ms $conf->{priorities}->{$priority}++;
873
874 # eval type handling
87520566.73ms if (($type & 1) == 1) {
8763799.55ms3794.41ms if (my ($function, $args) = ($text =~ m/(.*?)\s*\((.*?)\)\s*$/)) {
# spent 4.41ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 12µs/call
8773793.07ms37958.2ms my ($packed, $argsref) =
# spent 58.2ms making 379 calls to Mail::SpamAssassin::Conf::Parser::pack_eval_method, avg 154µ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.49ms $conf->{body_evals}->{$priority}->{$name} = $packed;
885 }
886 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS) {
887101749µ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
89273831µs $conf->{rbl_evals}->{$name} = [ $function, @$argsref ];
893 }
894 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_EVALS) {
895753µs $conf->{rawbody_evals}->{$priority}->{$name} = $packed;
896 }
897 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_EVALS) {
89811110µ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.52ms if ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS) {
9145134.14ms $conf->{body_tests}->{$priority}->{$name} = $text;
915 }
916 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS) {
9175954.81ms $conf->{head_tests}->{$priority}->{$name} = $text;
918 }
919 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
9204633.51ms $conf->{meta_tests}->{$priority}->{$name} = $text;
921 }
922 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS) {
92369573µs $conf->{uri_tests}->{$priority}->{$name} = $text;
924 }
925 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS) {
92633242µs $conf->{rawbody_tests}->{$priority}->{$name} = $text;
927 }
928 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS) {
929211µ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
94116µs if (!$isuserconf) {
942114µs1155ms $conf->{main}->call_plugins("finish_parsing_end", { conf => $conf });
# spent 155ms making 1 call to Mail::SpamAssassin::call_plugins
943 } else {
944 $conf->{main}->call_plugins("user_conf_parsing_end", { conf => $conf });
945 }
946
947113µs128µs $conf->found_any_rules(); # before we might delete {tests}
# spent 28µs making 1 call to Mail::SpamAssassin::Conf::found_any_rules
948
949127µs if (!$conf->{allow_user_rules}) {
950 # free up stuff we no longer need
95112.33ms delete $conf->{tests};
9521590µs delete $conf->{priority};
953 #test_types are needed - see bug 5503
954 #delete $conf->{test_types};
955 }
956}
957
958
# spent 7.12s (33.1ms+7.09) within Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies which was called: # once (33.1ms+7.09s) 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.50ms foreach my $name (keys %{$conf->{tests}}) {
96420677.97ms next unless ($conf->{test_types}->{$name}
965 == $Mail::SpamAssassin::Conf::TYPE_META_TESTS);
966
9674641.15ms my $deps = [ ];
968464893µs my $alreadydone = { };
9694643.38ms4647.09s $self->_meta_deps_recurse($conf, $name, $name, $deps, $alreadydone);
# spent 7.09s making 464 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 15.3ms/call
97092814.7ms $conf->{meta_dependencies}->{$name} = join (' ', @{$deps});
971 }
972}
973
974
# spent 7.09s (5.47+1.62) within Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse which was called 13832 times, avg 513µs/call: # 13368 times (5.26s+-5.26s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 1000, avg 0s/call # 464 times (219ms+6.87s) by Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies at line 969, avg 15.3ms/call
sub _meta_deps_recurse {
9751383229.9ms my ($self, $conf, $toprule, $name, $deps, $alreadydone) = @_;
976
977 # Only do each rule once per top-level meta; avoid infinite recursion
9781383259.7ms return if $alreadydone->{$name};
9791132376.1ms $alreadydone->{$name} = 1;
980
981 # Obviously, don't trace empty or nonexistent rules
9821132345.0ms my $rule = $conf->{tests}->{$name};
9831132319.2ms return unless $rule;
984
985 # Lex the rule into tokens using a rather simple RE method ...
9861132119.7ms my $lexer = ARITH_EXPRESSION_LEXER;
98711321940ms22642560ms my @tokens = ($rule =~ m/$lexer/g);
# spent 498ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 44µs/call # spent 61.9ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 5µs/call
988
989 # Go through each token in the meta rule
9901132124.9ms my $conf_tests = $conf->{tests};
99111321688ms foreach my $token (@tokens) {
992 # has to be an alpha+numeric token
993 # next if $token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/;
9942694484.02s269448659ms next if $token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s; # faster
# spent 659ms making 269448 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
995 # and has to be a rule name
996120401431ms next unless exists $conf_tests->{$token};
997
998 # add and recurse
99926736144ms13368396ms push(@{$deps}, untaint_var($token));
# spent 396ms making 13368 calls to Mail::SpamAssassin::Util::untaint_var, avg 30µs/call
100013368129ms133680s $self->_meta_deps_recurse($conf, $toprule, $token, $deps, $alreadydone);
# spent 14.6s making 13368 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 1.09ms/call, recursion: max depth 7, sum of overlapping time 14.6s
1001 }
1002}
1003
1004
# spent 137ms (114+22.4) within Mail::SpamAssassin::Conf::Parser::fix_priorities which was called: # once (114ms+22.4ms) 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.
101416.18ms122.4ms foreach my $rule (sort {
# spent 22.4ms making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:sort
1015973522.4ms $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.81ms my $deps = $conf->{meta_dependencies}->{$rule};
102120673.29ms next unless (defined $deps);
1022
10234641.34ms my $basepri = $pri->{$rule};
102446411.8ms foreach my $dep (split ' ', $deps) {
10251336838.6ms my $deppri = $pri->{$dep};
10261336846.2ms 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 105ms (101+3.69) within Mail::SpamAssassin::Conf::Parser::find_dup_rules which was called: # once (101ms+3.69ms) 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;
1040206928.7ms while (my ($name, $text) = each %{$conf->{tests}}) {
104120674.28ms my $type = $conf->{test_types}->{$name};
1042
1043 # skip eval and empty tests
104420674.02ms next if ($type & 1) ||
1045 ($type eq $Mail::SpamAssassin::Conf::TYPE_EMPTY_TESTS);
1046
1047337239.7ms16863.47ms my $tf = ($conf->{tflags}->{$name}||''); $tf =~ s/\s+/ /gs;
# spent 3.47ms 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.92ms $text = "$type\t$text\t$tf";
1051
105216869.44ms if (defined $names_for_text{$text}) {
10531172µs $names_for_text{$text} .= " ".$name;
10541146µs $dups{$text} = undef; # found (at least) one
1055 } else {
1056167511.5ms $names_for_text{$text} = $name;
1057 }
1058 }
1059
10601839µs foreach my $text (keys %dups) {
10611015µs my $first;
1062 my $first_pri;
106322276µs1078µs my @names = sort {$a cmp $b} split(' ', $names_for_text{$text});
# spent 78µs making 10 calls to Mail::SpamAssassin::Conf::Parser::CORE:sort, avg 8µs/call
10641033µs foreach my $name (@names) {
106521154µs my $priority = $conf->{priority}->{$name} || 0;
1066
10672187µs if (!defined $first || $priority < $first_pri) {
10681017µs $first_pri = $priority;
10691022µs $first = $name;
1070 }
1071 }
1072 # $first is now the earliest-occurring rule. mark others as dups
1073
10741026µs my @dups;
10751047µs foreach my $name (@names) {
10762137µs next if $name eq $first;
10771159µs push @dups, $name;
107811111µs delete $conf->{tests}->{$name};
1079 }
1080
108110171µs10144µs dbg("rules: $first merged duplicates: ".join(' ', @dups));
# spent 144µs making 10 calls to Mail::SpamAssassin::Logger::dbg, avg 14µs/call
108210113µs $conf->{duplicate_rules}->{$first} = \@dups;
1083 }
1084}
1085
1086
# spent 58.2ms (51.1+7.09) within Mail::SpamAssassin::Conf::Parser::pack_eval_method which was called 379 times, avg 154µs/call: # 379 times (51.1ms+7.09ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 877, avg 154µs/call
sub pack_eval_method {
10873793.50ms my ($self, $function, $args, $name, $text) = @_;
1088
1089379603µs my @args;
10903791.28ms 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.58ms local($1,$2,$3);
109637919.0ms3792.79ms while ($args =~ s/^\s* (?: (['"]) (.*?) \1 | ( [\d\.:A-Za-z-]+? ) )
# spent 2.79ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µs/call
1097 \s* (?: , \s* | $ )//x) {
10984838.78ms4832.35ms if (defined $2) {
# spent 2.35ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 5µs/call
10994742.60ms push @args, $2;
1100 }
1101 else {
1102967µs push @args, $3;
1103 }
1104 }
1105 }
1106
1107379695µs if ($args ne '') {
1108 $self->lint_warn("syntax error (unparsable argument: $args) for eval function: $name: $text", $name);
1109 return;
1110 }
1111
1112379824µs my $argstr = $function;
11133794.23ms379907µs $argstr =~ s/\s+//gs;
# spent 907µs making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1114
11153791.33ms if (@args > 0) {
1116 $argstr .= ',' . join(', ',
1117170411.1ms4831.04ms map { my $s = $_; $s =~ s/\#/[HASH]/gs; 'q#' . $s . '#' } @args);
# spent 1.04ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1118 }
11193794.23ms 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);
113414µ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 {
1141115µ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 785ms (226+559) within Mail::SpamAssassin::Conf::Parser::add_test which was called 2074 times, avg 379µs/call: # 548 times (83.6ms+145ms) 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 417µs/call # 513 times (49.0ms+131ms) 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 351µs/call # 465 times (43.5ms+256ms) 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 643µs/call # 142 times (18.5ms+978µ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 137µs/call # 102 times (6.93ms+651µ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 (5.54ms+504µ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 83µs/call # 71 times (5.95ms+15.8ms) 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 306µs/call # 58 times (4.52ms+769µs) 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 91µs/call # 46 times (3.51ms+377µ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 85µs/call # 33 times (3.49ms+7.77ms) 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 341µs/call # 11 times (977µ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 95µs/call # 7 times (357µs+44µ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 57µs/call # 2 times (206µs+358µ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 282µs/call # 2 times (98µs+12µ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 55µs/call # once (67µs+9µ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 {
1177207411.3ms my ($self, $name, $text, $type) = @_;
117820744.38ms my $conf = $self->{conf};
1179
1180 # Don't allow invalid names ...
1181207441.9ms20749.18ms if ($name !~ /^\D\w*$/) {
# spent 9.18ms 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.83ms 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.97ms 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.89ms 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.24ms619151ms return unless $self->is_delimited_regexp_valid($name, $text);
# spent 151ms making 619 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 244µs/call
1211 }
121220746.02ms 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...
12166069.36ms6063.10ms if ($text =~ /^!?defined\([!-9;-\176]+\)$/) {
# spent 3.10ms making 606 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call
1217 # fine, implements 'exists:'
1218 } else {
121954814.5ms5489.11ms my ($pat) = ($text =~ /^\s*\S+\s*(?:\=|\!)\~\s*(\S.*?\S)\s*$/);
# spent 9.11ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 17µs/call
122010968.48ms5481.73ms if ($pat) { $pat =~ s/\s+\[if-unset:\s+(.+)\]\s*$//; }
# spent 1.73ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
12215484.19ms548127ms return unless $self->is_delimited_regexp_valid($name, $pat);
# spent 127ms making 548 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 232µs/call
1222 }
1223 }
1224 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS)
1225 {
12264653.53ms465252ms return unless $self->is_meta_valid($name, $text);
# spent 252ms making 465 calls to Mail::SpamAssassin::Conf::Parser::is_meta_valid, avg 543µs/call
1227 }
1228
1229207421.1ms $conf->{tests}->{$name} = $text;
123020747.99ms $conf->{test_types}->{$name} = $type;
1231
1232207429.0ms20745.87ms if ($name =~ /AUTOLEARNTEST/i) {
# spent 5.87ms 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.89ms if ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
12384652.94ms $conf->{priority}->{$name} ||= 500;
1239 }
1240 else {
124116099.41ms $conf->{priority}->{$name} ||= 0;
1242 }
124320744.67ms $conf->{priority}->{$name} ||= 0;
1244207416.3ms $conf->{source_file}->{$name} = $self->{currentfile};
1245
124620744.23ms 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 #
1267207424.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 252ms (198+54.1) within Mail::SpamAssassin::Conf::Parser::is_meta_valid which was called 465 times, avg 543µs/call: # 465 times (198ms+54.1ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1226, avg 543µs/call
sub is_meta_valid {
12874652.21ms my ($self, $name, $rule) = @_;
1288
12894651.02ms my $meta = '';
12904653.51ms46513.5ms $rule = untaint_var($rule); # must be careful below
# spent 13.5ms making 465 calls to Mail::SpamAssassin::Util::untaint_var, avg 29µs/call
1291
1292 # Lex the rule into tokens using a rather simple RE method ...
12934651.00ms my $lexer = ARITH_EXPRESSION_LEXER;
129446530.1ms93019.1ms my @tokens = ($rule =~ m/$lexer/g);
# spent 16.5ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 35µs/call # spent 2.69ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 6µs/call
12954651.27ms 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.89ms foreach my $token (@tokens) {
1302 # Numbers can't be rule names
13037210142ms721021.5ms if ($token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s) {
# spent 21.5ms making 7210 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
130441127.74ms $meta .= "$token ";
1305 }
1306 # Zero will probably cause more errors
1307 else {
130830985.36ms $meta .= "0 ";
1309 }
1310 }
1311
13124651.76ms my $evalstr = 'my $x = ' . $meta . '; 1;';
131346530.1ms if (eval $evalstr) {
# spent 350µs executing statements in 42 string evals (merged) # spent 347µs executing statements in 37 string evals (merged) # spent 243µs executing statements in 26 string evals (merged) # spent 219µs executing statements in 24 string evals (merged) # spent 181µs executing statements in 20 string evals (merged) # spent 148µs executing statements in 17 string evals (merged) # spent 105µs executing statements in 14 string evals (merged) # spent 97µs executing statements in 12 string evals (merged) # spent 77µs executing statements in 8 string evals (merged) # spent 72µs executing statements in 8 string evals (merged) # spent 70µs executing statements in 8 string evals (merged) # spent 69µs executing statements in 7 string evals (merged) # spent 64µs executing statements in 8 string evals (merged) # spent 63µs executing statements in 7 string evals (merged) # spent 56µs executing statements in 6 string evals (merged) # spent 53µs executing statements in 6 string evals (merged) # spent 50µs executing statements in 6 string evals (merged) # spent 46µs executing statements in 6 string evals (merged) # spent 45µs executing statements in 4 string evals (merged) # spent 45µs executing statements in 5 string evals (merged) # spent 45µs executing statements in 5 string evals (merged) # spent 43µs executing statements in 5 string evals (merged) # spent 40µs executing statements in 5 string evals (merged) # spent 35µs executing statements in 4 string evals (merged) # spent 32µs executing statements in string eval # spent 32µs executing statements in 3 string evals (merged) # spent 31µs executing statements in 4 string evals (merged) # spent 31µs executing statements in 3 string evals (merged) # spent 30µs executing statements in 3 string evals (merged) # spent 30µs executing statements in 3 string evals (merged) # spent 29µs executing statements in 3 string evals (merged) # spent 26µs executing statements in 2 string evals (merged) # spent 25µs executing statements in 2 string evals (merged) # spent 25µ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 3 string evals (merged) # spent 24µs executing statements in 3 string evals (merged) # spent 23µs executing statements in 2 string evals (merged) # spent 23µs executing statements in string eval # spent 22µs executing statements in 3 string evals (merged) # spent 21µs executing statements in 2 string evals (merged) # spent 21µs executing statements in 2 string evals (merged) # spent 21µs executing statements in 2 string evals (merged) # spent 20µs executing statements in 2 string evals (merged) # spent 20µs executing statements in 2 string evals (merged) # spent 20µs executing statements in 2 string evals (merged) # spent 19µs executing statements in 2 string evals (merged) # spent 19µs executing statements in 2 string evals (merged) # spent 18µs executing statements in 2 string evals (merged) # spent 17µs executing statements in string eval # spent 17µs executing statements in 2 string evals (merged) # spent 16µs executing statements in 2 string evals (merged) # spent 16µs executing statements in 2 string evals (merged) # spent 16µs executing statements in 2 string evals (merged) # spent 15µs executing statements in 2 string evals (merged) # spent 15µs executing statements in 2 string evals (merged) # 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 2 string evals (merged) # spent 15µs executing statements in string eval # 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 14µs executing statements in string eval # spent 14µs executing statements in 2 string evals (merged) # spent 14µs executing statements in string eval # spent 14µs executing statements in string eval # 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 12µ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 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 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 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 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 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
13144658.06ms 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 291ms (44.6+246) within Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid which was called 1228 times, avg 237µs/call: # 619 times (17.7ms+133ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1210, avg 244µs/call # 548 times (24.9ms+102ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1221, avg 232µs/call # 46 times (1.51ms+8.14ms) 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 210µs/call # 15 times (460µs+2.90ms) 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 224µs/call
sub is_delimited_regexp_valid {
132412286.29ms my ($self, $name, $re) = @_;
1325
1326122827.7ms12288.32ms if (!$re || $re !~ /^\s*m?(\W).*(?:\1|>|}|\)|\])[a-z]*\s*$/) {
# spent 8.32ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 7µ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 }
1331122827.7ms1228238ms return $self->is_regexp_valid($name, $re);
# spent 238ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::is_regexp_valid, avg 194µs/call
1332}
1333
1334
# spent 238ms (132+105) within Mail::SpamAssassin::Conf::Parser::is_regexp_valid which was called 1228 times, avg 194µs/call: # 1228 times (132ms+105ms) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1331, avg 194µs/call
sub is_regexp_valid {
133512286.60ms 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.96ms my $origre = $re;
134112282.93ms my $safere = $re;
134212282.37ms my $mods = '';
134312285.02ms local ($1,$2);
1344122876.2ms603420.2ms if ($re =~ s/^m\{//) {
# spent 20.2ms making 6034 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
134528228µs1493µs $re =~ s/\}([a-z]*)\z//; $mods = $1;
# spent 93µs making 14 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µ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.26ms $re =~ s/\Q$1\E([a-z]*)\z//; $mods = $1;
# spent 815µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 16µs/call # spent 448µ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.68ms $mods = $2;
1358 }
1359 else {
1360 $safere = "m#".$re."#";
1361 }
1362
136312283.32ms 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.53ms if ($mods) {
13807884.23ms $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...
13886140131ms245683.9ms if (eval { ("" =~ m{$re}); 1; }) { return 1 }
# spent 81.7ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 67µs/call # spent 2.26ms 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 4.09ms (2.91+1.18) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist which was called 34 times, avg 120µs/call: # 34 times (2.91ms+1.18ms) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 818, avg 120µs/call
sub add_to_addrlist {
141734140µs my ($self, $singlelist, @addrs) = @_;
14183475µs my $conf = $self->{conf};
1419
142034447µs foreach my $addr (@addrs) {
142134100µs $addr = lc $addr;
14223473µs my $re = $addr;
142334447µs3493µs $re =~ s/[\000\\\(]/_/gs; # paranoia
# spent 93µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
1424341.78ms152682µs $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
# spent 540µs making 118 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 5µs/call # spent 142µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
14253494µs $re =~ tr/?/./; # "?" -> "."
142634634µs34408µs $re =~ s/\*+/\.\*/g; # "*" -> "any string"
# spent 408µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 12µs/call
142734443µs $conf->{$singlelist}->{$addr} = "^${re}\$";
1428 }
1429}
1430
1431
# spent 13.3ms (10.2+3.13) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd which was called 102 times, avg 131µs/call: # 83 times (8.29ms+2.42ms) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim at line 1470, avg 129µs/call # 19 times (1.92ms+710µ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 138µs/call
sub add_to_addrlist_rcvd {
1432102422µs my ($self, $listname, $addr, $domain) = @_;
1433102203µs my $conf = $self->{conf};
1434
1435102228µs $domain = lc $domain;
1436102315µs $addr = lc $addr;
14371029.89ms if ($conf->{$listname}->{$addr}) {
14381068µs push @{$conf->{$listname}->{$addr}{domain}}, $domain;
1439 }
1440 else {
144197211µs my $re = $addr;
1442971.39ms97315µs $re =~ s/[\000\\\(]/_/gs; # paranoia
# spent 315µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
1443975.85ms4582.14ms $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
# spent 1.64ms making 361 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 5µs/call # spent 498µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 5µs/call
144497401µs $re =~ tr/?/./; # "?" -> "."
1445971.79ms97674µs $re =~ s/\*+/\.\*/g; # "*" -> "any string"
# spent 674µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µs/call
1446971.01ms $conf->{$listname}->{$addr}{re} = "^${re}\$";
144797528µ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 20.5ms (9.77+10.7) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim which was called 83 times, avg 247µs/call: # 83 times (9.77ms+10.7ms) 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 247µs/call
sub add_to_addrlist_dkim {
1470831.29ms8310.7ms add_to_addrlist_rcvd(@_);
# spent 10.7ms making 83 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd, avg 129µ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 41.2ms (11.5+29.8) within Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file which was called 58 times, avg 711µs/call: # 58 times (11.5ms+29.8ms) by Mail::SpamAssassin::Conf::Parser::parse at line 342, avg 711µs/call
sub fix_path_relative_to_current_file {
149658279µs my ($self, $path) = @_;
1497
1498 # the path may be specified as "~/foo", so deal with that
149958672µs5822.5ms $path = $self->{conf}->{main}->sed_path($path);
# spent 22.5ms making 58 calls to Mail::SpamAssassin::sed_path, avg 388µs/call
1500
150158996µs581.23ms if (!File::Spec->file_name_is_absolute ($path)) {
# spent 1.23ms making 58 calls to File::Spec::Unix::file_name_is_absolute, avg 21µs/call
150258632µs584.10ms my ($vol, $dirs, $file) = File::Spec->splitpath ($self->{currentfile});
# spent 4.10ms making 58 calls to File::Spec::Unix::splitpath, avg 71µs/call
150358565µs581.32ms $path = File::Spec->catpath ($vol, $dirs, $path);
# spent 1.32ms making 58 calls to File::Spec::Unix::catpath, avg 23µs/call
150458655µs58601µs dbg("config: fixed relative path: $path");
# spent 601µs making 58 calls to Mail::SpamAssassin::Logger::dbg, avg 10µs/call
1505 }
150658624µ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.32s within Mail::SpamAssassin::Conf::Parser::CORE:match which was called 322611 times, avg 4µs/call: # 269448 times (659ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 994, avg 2µs/call # 16436 times (46.1ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 273, avg 3µs/call # 11321 times (498ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 44µs/call # 7210 times (21.5ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1303, avg 3µs/call # 2650 times (11.9ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 516, avg 4µs/call # 2074 times (9.18ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1181, avg 4µs/call # 2074 times (5.87ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1232, avg 3µs/call # 2067 times (5.73ms+0s) by Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions at line 657, avg 3µs/call # 1474 times (3.81ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 3µs/call # 1284 times (2.76ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 640, avg 2µs/call # 1284 times (2.15ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 642, avg 2µs/call # 1228 times (8.32ms+0s) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1326, avg 7µs/call # 1228 times (2.26ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 2µs/call # 606 times (3.10ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1216, avg 5µs/call # 548 times (9.11ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1219, avg 17µs/call # 508 times (7.60ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 15µs/call # 465 times (16.5ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 35µs/call # 379 times (4.41ms+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 876, avg 12µs/call # 136 times (711µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 302, avg 5µs/call # 68 times (340µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 308, avg 5µs/call # 55 times (440µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 588, avg 8µs/call # 34 times (167µs+0s) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 815, avg 5µs/call # 17 times (44µs+0s) by Mail::SpamAssassin::Conf::Parser::set_template_append at line 832, avg 3µs/call # 5 times (20µs+0s) by Mail::SpamAssassin::Conf::Parser::set_bool_value at line 749, avg 4µs/call # 4 times (22µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 722, avg 6µs/call # 4 times (12µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 719, avg 3µs/call # 3 times (10µs+0s) by Mail::SpamAssassin::Conf::Parser::set_string_value at line 771, avg 3µs/call # once (8µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 240
sub Mail::SpamAssassin::Conf::Parser::CORE:match; # opcode
# spent 157ms within Mail::SpamAssassin::Conf::Parser::CORE:regcomp which was called 15046 times, avg 10µs/call: # 11321 times (61.9ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 5µs/call # 1474 times (6.59ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 4µs/call # 1228 times (81.7ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 67µs/call # 508 times (3.31ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 7µs/call # 465 times (2.69ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 6µs/call # 50 times (815µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 16µs/call
sub Mail::SpamAssassin::Conf::Parser::CORE:regcomp; # opcode
# spent 22.5ms within Mail::SpamAssassin::Conf::Parser::CORE:sort which was called 11 times, avg 2.04ms/call: # 10 times (78µs+0s) by Mail::SpamAssassin::Conf::Parser::find_dup_rules at line 1063, avg 8µs/call # once (22.4ms+0s) by Mail::SpamAssassin::Conf::Parser::fix_priorities at line 1014
sub Mail::SpamAssassin::Conf::Parser::CORE:sort; # opcode
# spent 272ms within Mail::SpamAssassin::Conf::Parser::CORE:subst which was called 92819 times, avg 3µs/call: # 16436 times (65.2ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 279, avg 4µs/call # 16436 times (55.1ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 282, avg 3µs/call # 16436 times (41.3ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 281, avg 3µs/call # 16436 times (33.2ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 280, avg 2µs/call # 9050 times (23.4ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 3µs/call # 7576 times (19.1ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 291, avg 3µs/call # 6034 times (20.2ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1344, avg 3µs/call # 1686 times (3.47ms+0s) by Mail::SpamAssassin::Conf::Parser::find_dup_rules at line 1047, avg 2µs/call # 548 times (1.73ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1220, avg 3µs/call # 483 times (2.35ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1098, avg 5µs/call # 483 times (1.04ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1117, avg 2µs/call # 379 times (2.79ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1096, avg 7µs/call # 379 times (907µs+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1113, avg 2µs/call # 97 times (674µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1445, avg 7µs/call # 97 times (498µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 5µs/call # 97 times (315µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1442, avg 3µs/call # 50 times (448µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 9µs/call # 34 times (408µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1426, avg 12µs/call # 34 times (142µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 4µs/call # 34 times (93µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1423, avg 3µs/call # 14 times (93µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1345, avg 7µs/call
sub Mail::SpamAssassin::Conf::Parser::CORE:subst; # opcode
# spent 2.18ms within Mail::SpamAssassin::Conf::Parser::CORE:substcont which was called 479 times, avg 5µs/call: # 361 times (1.64ms+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 5µs/call # 118 times (540µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 5µs/call
sub Mail::SpamAssassin::Conf::Parser::CORE:substcont; # opcode