← Index
NYTProf Performance Profile   « line view »
For /usr/local/bin/sa-learn
  Run on Sun Nov 5 02:36:06 2017
Reported on Sun Nov 5 02:56:18 2017

Filename/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf/Parser.pm
StatementsExecuted 1032701 statements in 8.48s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
13832214.00s5.46sMail::SpamAssassin::Conf::Parser::::_meta_deps_recurseMail::SpamAssassin::Conf::Parser::_meta_deps_recurse (recurses: max depth 7, inclusive time 11.0s)
1111.56s4.68sMail::SpamAssassin::Conf::Parser::::parseMail::SpamAssassin::Conf::Parser::parse
3226112811.24s1.24sMail::SpamAssassin::Conf::Parser::::CORE:matchMail::SpamAssassin::Conf::Parser::CORE:match (opcode)
92819211265ms265msMail::SpamAssassin::Conf::Parser::::CORE:substMail::SpamAssassin::Conf::Parser::CORE:subst (opcode)
2074153207ms726msMail::SpamAssassin::Conf::Parser::::add_testMail::SpamAssassin::Conf::Parser::add_test
46511169ms222msMail::SpamAssassin::Conf::Parser::::is_meta_validMail::SpamAssassin::Conf::Parser::is_meta_valid
50821142ms211msMail::SpamAssassin::Conf::Parser::::handle_conditionalMail::SpamAssassin::Conf::Parser::handle_conditional
1504661137ms137msMail::SpamAssassin::Conf::Parser::::CORE:regcompMail::SpamAssassin::Conf::Parser::CORE:regcomp (opcode)
122811123ms231msMail::SpamAssassin::Conf::Parser::::is_regexp_validMail::SpamAssassin::Conf::Parser::is_regexp_valid
111119ms123msMail::SpamAssassin::Conf::Parser::::set_default_scoresMail::SpamAssassin::Conf::Parser::set_default_scores
111112ms116msMail::SpamAssassin::Conf::Parser::::find_dup_rulesMail::SpamAssassin::Conf::Parser::find_dup_rules
111104ms6.01sMail::SpamAssassin::Conf::Parser::::finish_parsingMail::SpamAssassin::Conf::Parser::finish_parsing
11191.0ms111msMail::SpamAssassin::Conf::Parser::::fix_prioritiesMail::SpamAssassin::Conf::Parser::fix_priorities
11163.0ms154msMail::SpamAssassin::Conf::Parser::::check_for_missing_descriptionsMail::SpamAssassin::Conf::Parser::check_for_missing_descriptions
12761157.2ms260msMail::SpamAssassin::Conf::Parser::::set_hash_key_valueMail::SpamAssassin::Conf::Parser::set_hash_key_value
12284346.2ms285msMail::SpamAssassin::Conf::Parser::::is_delimited_regexp_validMail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid
3791139.4ms47.1msMail::SpamAssassin::Conf::Parser::::pack_eval_methodMail::SpamAssassin::Conf::Parser::pack_eval_method
11131.3ms5.49sMail::SpamAssassin::Conf::Parser::::trace_meta_dependenciesMail::SpamAssassin::Conf::Parser::trace_meta_dependencies
112120.1ms20.1msMail::SpamAssassin::Conf::Parser::::CORE:sortMail::SpamAssassin::Conf::Parser::CORE:sort (opcode)
102227.71ms10.4msMail::SpamAssassin::Conf::Parser::::add_to_addrlist_rcvdMail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd
58114.67ms23.2msMail::SpamAssassin::Conf::Parser::::fix_path_relative_to_current_fileMail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file
16114.09ms4.09msMail::SpamAssassin::Conf::Parser::::build_command_lutsMail::SpamAssassin::Conf::Parser::build_command_luts
43443433.99ms3.99msMail::SpamAssassin::Conf::Parser::::cond_clause_plugin_loadedMail::SpamAssassin::Conf::Parser::cond_clause_plugin_loaded
34112.73ms3.63msMail::SpamAssassin::Conf::Parser::::add_to_addrlistMail::SpamAssassin::Conf::Parser::add_to_addrlist
55112.63ms4.20msMail::SpamAssassin::Conf::Parser::::cond_clause_can_or_hasMail::SpamAssassin::Conf::Parser::cond_clause_can_or_has
16112.16ms2.16msMail::SpamAssassin::Conf::Parser::::set_defaults_from_command_listMail::SpamAssassin::Conf::Parser::set_defaults_from_command_list
479211.67ms1.67msMail::SpamAssassin::Conf::Parser::::CORE:substcontMail::SpamAssassin::Conf::Parser::CORE:substcont (opcode)
8311980µs9.26msMail::SpamAssassin::Conf::Parser::::add_to_addrlist_dkimMail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim
551414942µs5.14msMail::SpamAssassin::Conf::Parser::::cond_clause_canMail::SpamAssassin::Conf::Parser::cond_clause_can
3411885µs4.60msMail::SpamAssassin::Conf::Parser::::set_addrlist_valueMail::SpamAssassin::Conf::Parser::set_addrlist_value
161616842µs7.09msMail::SpamAssassin::Conf::Parser::::register_commandsMail::SpamAssassin::Conf::Parser::register_commands
2111510µs510µsMail::SpamAssassin::Conf::Parser::::setup_default_code_cbMail::SpamAssassin::Conf::Parser::setup_default_code_cb
1711494µs542µsMail::SpamAssassin::Conf::Parser::::set_template_appendMail::SpamAssassin::Conf::Parser::set_template_append
511242µs255µsMail::SpamAssassin::Conf::Parser::::set_bool_valueMail::SpamAssassin::Conf::Parser::set_bool_value
411209µs394µsMail::SpamAssassin::Conf::Parser::::set_numeric_valueMail::SpamAssassin::Conf::Parser::set_numeric_value
31178µs94µsMail::SpamAssassin::Conf::Parser::::set_string_valueMail::SpamAssassin::Conf::Parser::set_string_value
21152µs52µsMail::SpamAssassin::Conf::Parser::::set_template_clearMail::SpamAssassin::Conf::Parser::set_template_clear
11149µs49µsMail::SpamAssassin::Conf::Parser::::BEGIN@137Mail::SpamAssassin::Conf::Parser::BEGIN@137
11137µs95µsMail::SpamAssassin::Conf::Parser::::BEGIN@592Mail::SpamAssassin::Conf::Parser::BEGIN@592
11130µs30µsMail::SpamAssassin::Conf::Parser::::newMail::SpamAssassin::Conf::Parser::new
11128µs38µsMail::SpamAssassin::Conf::Parser::::BEGIN@143Mail::SpamAssassin::Conf::Parser::BEGIN@143
11127µs377µsMail::SpamAssassin::Conf::Parser::::BEGIN@140Mail::SpamAssassin::Conf::Parser::BEGIN@140
11123µs229µsMail::SpamAssassin::Conf::Parser::::BEGIN@139Mail::SpamAssassin::Conf::Parser::BEGIN@139
11122µs29µsMail::SpamAssassin::Conf::Parser::::BEGIN@145Mail::SpamAssassin::Conf::Parser::BEGIN@145
11121µs90µsMail::SpamAssassin::Conf::Parser::::BEGIN@146Mail::SpamAssassin::Conf::Parser::BEGIN@146
11120µs57µsMail::SpamAssassin::Conf::Parser::::BEGIN@144Mail::SpamAssassin::Conf::Parser::BEGIN@144
11120µs20µsMail::SpamAssassin::Conf::Parser::::lint_trusted_networksMail::SpamAssassin::Conf::Parser::lint_trusted_networks
11120µs88µsMail::SpamAssassin::Conf::Parser::::BEGIN@148Mail::SpamAssassin::Conf::Parser::BEGIN@148
11119µs719µsMail::SpamAssassin::Conf::Parser::::BEGIN@138Mail::SpamAssassin::Conf::Parser::BEGIN@138
11114µs14µsMail::SpamAssassin::Conf::Parser::::BEGIN@141Mail::SpamAssassin::Conf::Parser::BEGIN@141
11113µs13µsMail::SpamAssassin::Conf::Parser::::lint_checkMail::SpamAssassin::Conf::Parser::lint_check
0000s0sMail::SpamAssassin::Conf::Parser::::add_regression_testMail::SpamAssassin::Conf::Parser::add_regression_test
0000s0sMail::SpamAssassin::Conf::Parser::::cond_clause_hasMail::SpamAssassin::Conf::Parser::cond_clause_has
0000s0sMail::SpamAssassin::Conf::Parser::::get_if_stack_as_stringMail::SpamAssassin::Conf::Parser::get_if_stack_as_string
0000s0sMail::SpamAssassin::Conf::Parser::::is_always_matching_regexpMail::SpamAssassin::Conf::Parser::is_always_matching_regexp
0000s0sMail::SpamAssassin::Conf::Parser::::lint_warnMail::SpamAssassin::Conf::Parser::lint_warn
0000s0sMail::SpamAssassin::Conf::Parser::::remove_addrlist_valueMail::SpamAssassin::Conf::Parser::remove_addrlist_value
0000s0sMail::SpamAssassin::Conf::Parser::::remove_from_addrlistMail::SpamAssassin::Conf::Parser::remove_from_addrlist
0000s0sMail::SpamAssassin::Conf::Parser::::remove_from_addrlist_dkimMail::SpamAssassin::Conf::Parser::remove_from_addrlist_dkim
0000s0sMail::SpamAssassin::Conf::Parser::::remove_from_addrlist_rcvdMail::SpamAssassin::Conf::Parser::remove_from_addrlist_rcvd
0000s0sMail::SpamAssassin::Conf::Parser::::set_duration_valueMail::SpamAssassin::Conf::Parser::set_duration_value
0000s0sMail::SpamAssassin::Conf::Parser::::set_ipaddr_listMail::SpamAssassin::Conf::Parser::set_ipaddr_list
0000s0sMail::SpamAssassin::Conf::Parser::::set_no_valueMail::SpamAssassin::Conf::Parser::set_no_value
0000s0sMail::SpamAssassin::Conf::Parser::::set_string_listMail::SpamAssassin::Conf::Parser::set_string_list
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# <@LICENSE>
2# Licensed to the Apache Software Foundation (ASF) under one or more
3# contributor license agreements. See the NOTICE file distributed with
4# this work for additional information regarding copyright ownership.
5# The ASF licenses this file to you under the Apache License, Version 2.0
6# (the "License"); you may not use this file except in compliance with
7# the License. You may obtain a copy of the License at:
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16# </@LICENSE>
17
18=head1 NAME
19
20Mail::SpamAssassin::Conf::Parser - parse SpamAssassin configuration
21
22=head1 SYNOPSIS
23
24 (see Mail::SpamAssassin)
25
26=head1 DESCRIPTION
27
28Mail::SpamAssassin is a module to identify spam using text analysis and
29several internet-based realtime blacklists.
30
31This class is used internally by SpamAssassin to parse its configuration files.
32Please refer to the C<Mail::SpamAssassin> documentation for public interfaces.
33
34=head1 STRUCTURE OF A CONFIG BLOCK
35
36This is the structure of a config-setting block. Each is a hashref which may
37contain these keys:
38
39=over 4
40
41=item setting
42
43the name of the setting it modifies, e.g. "required_score". this also doubles
44as the default for 'command' (below). THIS IS REQUIRED.
45
46=item command
47
48The command string used in the config file for this setting. Optional;
49'setting' will be used for the command if this is omitted.
50
51=item aliases
52
53An [aryref] of other aliases for the same command. optional.
54
55=item type
56
57The type of this setting:
58
59 - $CONF_TYPE_NOARGS: must not have any argument, like "clear_headers"
60 - $CONF_TYPE_STRING: string
61 - $CONF_TYPE_NUMERIC: numeric value (float or int)
62 - $CONF_TYPE_BOOL: boolean (0/no or 1/yes)
63 - $CONF_TYPE_TEMPLATE: template, like "report"
64 - $CONF_TYPE_ADDRLIST: list of mail addresses, like "whitelist_from"
65 - $CONF_TYPE_HASH_KEY_VALUE: hash key/value pair, like "describe" or tflags
66 - $CONF_TYPE_STRINGLIST list of strings, stored as an array
67 - $CONF_TYPE_IPADDRLIST list of IP addresses, stored as an array of SA::NetSet
68 - $CONF_TYPE_DURATION a nonnegative time interval in seconds - a numeric value
69 (float or int), optionally suffixed by a time unit (s, m,
70 h, d, w), seconds are implied if unit is missing
71
72If this is set, and a 'code' block does not already exist, a 'code' block is
73assigned based on the type.
74
75In addition, the SpamAssassin test suite will validate that the settings
76do not 'leak' between users.
77
78Note that C<$CONF_TYPE_HASH_KEY_VALUE>-type settings require that the
79value be non-empty, otherwise they'll produce a warning message.
80
81=item code
82
83A subroutine to deal with the setting. ONE OF B<code> OR B<type> IS REQUIRED.
84The arguments passed to the function are C<($self, $key, $value, $line)>,
85where $key is the setting (*not* the command), $value is the value string,
86and $line is the entire line.
87
88There are two special return values that the B<code> subroutine may return
89to signal that there is an error in the configuration:
90
91C<$Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE> -- this setting requires
92that a value be set, but one was not provided.
93
94C<$Mail::SpamAssassin::Conf::INVALID_VALUE> -- this setting requires a value
95from a set of 'valid' values, but the user provided an invalid one.
96
97C<$Mail::SpamAssassin::Conf::INVALID_HEADER_FIELD_NAME> -- this setting
98requires a syntactically valid header field name, but the user provided
99an invalid one.
100
101Any other values -- including C<undef> -- returned from the subroutine are
102considered to mean 'success'.
103
104It is good practice to set a 'type', if possible, describing how your settings
105are stored on the Conf object; this allows the SpamAssassin test suite to
106validate that the settings do not 'leak' between users.
107
108=item default
109
110The default value for the setting. may be omitted if the default value is a
111non-scalar type, which should be set in the Conf ctor. note for path types:
112using "__userstate__" is recommended for defaults, as it allows
113Mail::SpamAssassin module users who set that configuration setting, to receive
114the correct values.
115
116=item is_priv
117
118Set to 1 if this setting requires 'allow_user_rules' when run from spamd.
119
120=item is_admin
121
122Set to 1 if this setting can only be set in the system-wide config when run
123from spamd. (All settings can be used by local programs run directly by the
124user.)
125
126=item is_frequent
127
128Set to 1 if this value occurs frequently in the config. this means it's looked
129up first for speed.
130
131=back
132
133=cut
134
135package Mail::SpamAssassin::Conf::Parser;
136
137279µs149µs
# spent 49µs within Mail::SpamAssassin::Conf::Parser::BEGIN@137 which was called: # once (49µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 137
use Mail::SpamAssassin::Conf;
# spent 49µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@137
138272µs21.42ms
# spent 719µs (19+700) within Mail::SpamAssassin::Conf::Parser::BEGIN@138 which was called: # once (19µs+700µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 138
use Mail::SpamAssassin::Constants qw(:sa);
# spent 719µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@138 # spent 700µs making 1 call to Exporter::import
139275µs2435µs
# spent 229µs (23+206) within Mail::SpamAssassin::Conf::Parser::BEGIN@139 which was called: # once (23µs+206µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 139
use Mail::SpamAssassin::Logger;
# spent 229µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@139 # spent 206µs making 1 call to Exporter::import
140275µs2727µs
# spent 377µs (27+350) within Mail::SpamAssassin::Conf::Parser::BEGIN@140 which was called: # once (27µs+350µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 140
use Mail::SpamAssassin::Util qw(untaint_var);
# spent 377µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@140 # spent 350µs making 1 call to Exporter::import
141273µs114µs
# spent 14µs within Mail::SpamAssassin::Conf::Parser::BEGIN@141 which was called: # once (14µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 141
use Mail::SpamAssassin::NetSet;
# spent 14µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@141
142
143260µs249µs
# spent 38µs (28+11) within Mail::SpamAssassin::Conf::Parser::BEGIN@143 which was called: # once (28µs+11µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 143
use strict;
# spent 38µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@143 # spent 11µs making 1 call to strict::import
144266µs293µs
# spent 57µs (20+37) within Mail::SpamAssassin::Conf::Parser::BEGIN@144 which was called: # once (20µs+37µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 144
use warnings;
# spent 57µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@144 # spent 36µs making 1 call to warnings::import
145260µs235µs
# spent 29µs (22+7) within Mail::SpamAssassin::Conf::Parser::BEGIN@145 which was called: # once (22µs+7µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 145
use bytes;
# spent 29µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@145 # spent 7µs making 1 call to bytes::import
146274µs2159µs
# spent 90µs (21+69) within Mail::SpamAssassin::Conf::Parser::BEGIN@146 which was called: # once (21µs+69µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 146
use re 'taint';
# spent 90µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@146 # spent 69µs making 1 call to re::import
147
14812µs
# spent 88µs (20+68) within Mail::SpamAssassin::Conf::Parser::BEGIN@148 which was called: # once (20µs+68µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 150
use vars qw{
149 @ISA
15014.39ms2157µs};
# spent 88µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@148 # spent 68µ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
16114µs my $self = {
162 'conf' => $conf
163 };
164
16513µs $self->{command_luts} = { };
16614µs $self->{command_luts}->{frequent} = { };
16713µs $self->{command_luts}->{remaining} = { };
168
16912µs bless ($self, $class);
170111µs $self;
171}
172
173###########################################################################
174
175
# spent 7.09ms (842µs+6.25) within Mail::SpamAssassin::Conf::Parser::register_commands which was called 16 times, avg 443µs/call: # once (88µs+3.09ms) by Mail::SpamAssassin::Conf::new at line 4516 of Mail/SpamAssassin/Conf.pm # once (49µs+855µs) by Mail::SpamAssassin::Plugin::TxRep::set_config at line 1058 of Mail/SpamAssassin/Plugin/TxRep.pm # once (49µs+377µs) by Mail::SpamAssassin::Plugin::URIDNSBL::set_config at line 813 of Mail/SpamAssassin/Plugin/URIDNSBL.pm # once (52µs+250µs) by Mail::SpamAssassin::Plugin::ReplaceTags::set_config at line 292 of Mail/SpamAssassin/Plugin/ReplaceTags.pm # once (45µs+242µs) by Mail::SpamAssassin::Plugin::SPF::set_config at line 228 of Mail/SpamAssassin/Plugin/SPF.pm # once (56µs+229µs) by Mail::SpamAssassin::Plugin::FreeMail::set_config at line 213 of Mail/SpamAssassin/Plugin/FreeMail.pm # once (58µs+208µs) by Mail::SpamAssassin::Plugin::DKIM::set_config at line 502 of Mail/SpamAssassin/Plugin/DKIM.pm # once (44µs+208µs) by Mail::SpamAssassin::Plugin::Hashcash::set_config at line 158 of Mail/SpamAssassin/Plugin/Hashcash.pm # once (62µs+137µs) by Mail::SpamAssassin::Plugin::AutoLearnThreshold::set_config at line 146 of Mail/SpamAssassin/Plugin/AutoLearnThreshold.pm # once (46µs+145µs) by Mail::SpamAssassin::Plugin::SpamCop::set_config at line 157 of Mail/SpamAssassin/Plugin/SpamCop.pm # once (55µs+132µs) by Mail::SpamAssassin::Plugin::WhiteListSubject::set_config at line 109 of Mail/SpamAssassin/Plugin/WhiteListSubject.pm # once (44µs+133µs) by Mail::SpamAssassin::Plugin::Razor2::set_config at line 134 of Mail/SpamAssassin/Plugin/Razor2.pm # once (60µs+62µs) by Mail::SpamAssassin::Plugin::MIMEHeader::set_config at line 163 of Mail/SpamAssassin/Plugin/MIMEHeader.pm # once (44µs+62µs) by Mail::SpamAssassin::Plugin::URIDetail::set_config at line 150 of Mail/SpamAssassin/Plugin/URIDetail.pm # once (47µs+59µs) by Mail::SpamAssassin::Plugin::AskDNS::set_config at line 359 of Mail/SpamAssassin/Plugin/AskDNS.pm # once (43µs+60µs) by Mail::SpamAssassin::Plugin::VBounce::set_config at line 90 of Mail/SpamAssassin/Plugin/VBounce.pm
sub register_commands {
1761635µs my($self, $arrref) = @_;
1771661µs my $conf = $self->{conf};
178
17916126µs162.16ms $self->set_defaults_from_command_list($arrref);
# spent 2.16ms making 16 calls to Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list, avg 135µs/call
18016148µs164.09ms $self->build_command_luts($arrref);
# spent 4.09ms making 16 calls to Mail::SpamAssassin::Conf::Parser::build_command_luts, avg 256µs/call
18148397µs push(@{$conf->{registered_commands}}, @{$arrref});
182}
183
184
# spent 2.16ms within Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list which was called 16 times, avg 135µs/call: # 16 times (2.16ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 179, avg 135µs/call
sub set_defaults_from_command_list {
1851639µs my ($self, $arrref) = @_;
1861650µs my $conf = $self->{conf};
18732341µs foreach my $cmd (@{$arrref}) {
188 # note! exists, not defined -- we want to be able to set
189 # "undef" default values.
190203877µs if (exists($cmd->{default})) {
191110950µs $conf->{$cmd->{setting}} = $cmd->{default};
192 }
193 }
194}
195
196
# spent 4.09ms within Mail::SpamAssassin::Conf::Parser::build_command_luts which was called 16 times, avg 256µs/call: # 16 times (4.09ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 180, avg 256µs/call
sub build_command_luts {
1971632µs my ($self, $arrref) = @_;
198
1991648µs my $conf = $self->{conf};
200
2011630µs my $set;
20232304µs foreach my $cmd (@{$arrref}) {
203 # first off, decide what set this is in.
204210722µs if ($cmd->{is_frequent}) { $set = 'frequent'; }
205196337µs else { $set = 'remaining'; }
206
207 # next, its priority (used to ensure frequently-used params
208 # are parsed first)
209203456µs my $cmdname = $cmd->{command} || $cmd->{setting};
2102031.45ms $self->{command_luts}->{$set}->{$cmdname} = $cmd;
211
212205748µs if ($cmd->{aliases} && scalar @{$cmd->{aliases}} > 0) {
213415µs foreach my $name (@{$cmd->{aliases}}) {
214214µs $self->{command_luts}->{$set}->{$name} = $cmd;
215 }
216 }
217 }
218}
219
220###########################################################################
221
222
# spent 4.68s (1.56+3.12) within Mail::SpamAssassin::Conf::Parser::parse which was called: # once (1.56s+3.12s) by Mail::SpamAssassin::Conf::parse_rules at line 4623 of Mail/SpamAssassin/Conf.pm
sub parse {
22314µs my ($self, undef, $scoresonly) = @_; # leave $rules in $_[1]
224
22513µs my $conf = $self->{conf};
22614µ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
23114µ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)
23514µs $lang ||= $ENV{'LC_ALL'};
23613µs $lang ||= $ENV{'LC_MESSAGES'};
23712µs $lang ||= $ENV{'LANG'};
23812µ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
24112µs $lang = 'en_US'; # Our default language
242 } else {
243 $lang =~ s/[@.+,].*$//; # Strip codeset, modifier/audience, etc.
244 } # (eg. .utf8 or @euro)
245
246 # get fast-access handles on the command lookup tables
24713µs my $lut_frequent = $self->{command_luts}->{frequent};
24813µs my $lut_remaining = $self->{command_luts}->{remaining};
249212µs my %migrated_keys = map { $_ => 1 }
250 @Mail::SpamAssassin::Conf::MIGRATED_SETTINGS;
251
25213µs $self->{currentfile} = '(no file)';
25312µs my $skip_parsing = 0;
25412µs my @curfile_stack;
255 my @if_stack;
2561472µs my @conf_lines = split (/\n/, $_[1]);
25712µs my $line;
25814µs $self->{if_stack} = \@if_stack;
25914µs $self->{file_scoped_attrs} = { };
260
26114µs my $keepmetadata = $conf->{main}->{keep_config_parsing_metadata};
262
263199.0ms while (defined ($line = shift @conf_lines)) {
2641643651.4ms local ($1); # bug 3838: prevent random taint flagging of $1
265
266 # bug 5545: used to support testing rules in the ruleqa system
2671643625.6ms 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
27316436203ms1643644.9ms if ($line =~ /^\# UPDATE version (\d+)$/) {
# spent 44.9ms 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
27916436212ms1643664.6ms $line =~ s/(?<!\\)#.*$//; # remove comments
# spent 64.6ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
28016436147ms1643632.7ms $line =~ s/\\#/#/g; # hash chars are escaped, so unescape them
# spent 32.7ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
28116436172ms1643639.5ms $line =~ s/^\s+//; # remove leading whitespace
# spent 39.5ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
28216436200ms1643654.7ms $line =~ s/\s+$//; # remove tailing whitespace
# spent 54.7ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
2831643638.0ms next unless($line); # skip empty lines
284
285 # handle i18n
28610524128ms1199831.7ms if ($line =~ s/^lang\s+(\S+)\s+//) { next if ($lang !~ /^$1/i); }
# spent 22.0ms making 9050 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call # spent 6.07ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 4µs/call # spent 3.60ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
287
288757657.4ms my($key, $value) = split(/\s+/, $line, 2);
289757618.7ms $key = lc $key;
290 # convert all dashes in setting name to underscores.
291757684.5ms757617.2ms $key =~ s/-/_/g;
# spent 17.2ms making 7576 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µ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.2ms my $parse_error; # undef by default, may be overridden
299
300 # File/line number assertions
301757614.1ms if ($key eq 'file') {
3021361.78ms136734µs if ($value =~ /^start\s+(.+)$/) {
# spent 734µs making 136 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call
30368310µs push (@curfile_stack, $self->{currentfile});
30468326µs $self->{currentfile} = $1;
30568319µs next;
306 }
307
30868859µs68382µs if ($value =~ /^end\s/) {
# spent 382µs making 68 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 6µs/call
30968327µs $self->{file_scoped_attrs} = { };
310
31168192µ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 }
32868138µs $skip_parsing = 0;
329
33068351µs my $curfile = pop @curfile_stack;
33168253µs if (defined $curfile) {
33268260µs $self->{currentfile} = $curfile;
333 } else {
334 $self->{currentfile} = '(no file)';
335 }
33668315µs next;
337 }
338 }
339
340 # now handle the commands.
341744012.7ms if ($key eq 'include') {
34258653µs5823.2ms $value = $self->fix_path_relative_to_current_file($value);
# spent 23.2ms making 58 calls to Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file, avg 400µs/call
34358795µs5826.7ms my $text = $conf->{main}->read_cf($value, 'included file');
# spent 26.7ms making 58 calls to Mail::SpamAssassin::read_cf, avg 461µs/call
3445829.0ms unshift (@conf_lines, split (/\n/, $text));
34558733µs next;
346 }
347
348738212.7ms if ($key eq 'ifplugin') {
3493605.39ms360130ms $self->handle_conditional ($key, "plugin ($value)",
# spent 130ms making 360 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 361µs/call
350 \@if_stack, \$skip_parsing);
3513601.58ms next;
352 }
353
354702211.7ms if ($key eq 'if') {
3551481.65ms14880.7ms $self->handle_conditional ($key, $value,
# spent 80.7ms making 148 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 546µs/call
356 \@if_stack, \$skip_parsing);
357148663µs next;
358 }
359
360687411.5ms if ($key eq 'else') {
361 # TODO: if/else/else won't get flagged here :(
36224µ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:
372687211.7ms if ($key eq 'endif') {
3735081.12ms my $lastcond = pop @if_stack;
374508878µs if (!defined $lastcond) {
375 $parse_error = "config: found endif without matching conditional";
376 goto failed_line;
377 }
378
3795081.18ms $skip_parsing = $lastcond->{skip_parsing};
3805086.33ms next;
381 }
382
383 # preprocessing? skip all other commands
384636410.4ms next if $skip_parsing;
385
386618410.3ms if ($key eq 'require_version') {
387 # if it wasn't replaced during install, assume current version ...
3881749µs next if ($value eq "\@\@VERSION\@\@");
389
3901743µ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
4001748µ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 }
4101788µs next;
411 }
412
413616715.2ms my $cmd = $lut_frequent->{$key}; # check the frequent command set
414616713.9ms if (!$cmd) {
41522085.29ms $cmd = $lut_remaining->{$key}; # no? try the rest
416 }
417
418 # we've either fallen through with no match, in which case this
419 # if() will fail, or we have a match.
420616710.1ms if ($cmd) {
421566610.4ms 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.1ms if (!$cmd->{code}) {
43321159µs21510µs if (! $self->setup_default_code_cb($cmd)) {
# spent 510µs making 21 calls to Mail::SpamAssassin::Conf::Parser::setup_default_code_cb, avg 24µs/call
434 goto failed_line;
435 }
436 }
437
4381133266.0ms56662.13s my $ret = &{$cmd->{code}} ($conf, $cmd->{setting}, $value, $line);
# spent 581ms making 27 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:4145], avg 21.5ms/call # spent 302ms making 465 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3174], avg 649µs/call # spent 282ms making 781 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2981], avg 361µs/call # spent 260ms making 1276 calls to Mail::SpamAssassin::Conf::Parser::set_hash_key_value, avg 203µs/call # spent 228ms making 655 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3020], avg 349µs/call # spent 156ms making 811 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:280], avg 192µs/call # spent 97.7ms making 30 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1685], avg 3.26ms/call # spent 45.4ms making 46 calls to Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[Mail/SpamAssassin/Plugin/MIMEHeader.pm:160], avg 986µs/call # spent 34.5ms making 459 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3750], avg 75µs/call # spent 30.3ms making 71 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3052], avg 427µs/call # spent 24.8ms making 128 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3557], avg 194µs/call # spent 22.7ms making 83 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:420], avg 274µs/call # spent 13.4ms making 40 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3088], avg 335µs/call # spent 8.03ms making 64 calls to Mail::SpamAssassin::Plugin::ReplaceTags::__ANON__[Mail/SpamAssassin/Plugin/ReplaceTags.pm:266], avg 126µs/call # spent 5.17ms making 85 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:468], avg 61µs/call # spent 5.01ms making 270 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2044], avg 19µs/call # spent 4.99ms making 15 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2701], avg 333µs/call # spent 4.60ms making 34 calls to Mail::SpamAssassin::Conf::Parser::set_addrlist_value, avg 135µs/call # spent 3.88ms making 21 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:662], avg 185µs/call # spent 3.64ms making 63 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:783], avg 58µs/call # spent 2.87ms making 19 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:433], avg 151µs/call # spent 2.66ms making 77 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3206], avg 35µs/call # spent 2.29ms making 48 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3781], avg 48µs/call # spent 2.09ms making 13 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3122], avg 161µs/call # spent 1.25ms making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3804] # spent 1.05ms making 5 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:935], avg 211µs/call # spent 680µs making 2 calls to Mail::SpamAssassin::Plugin::AskDNS::__ANON__[Mail/SpamAssassin/Plugin/AskDNS.pm:356], avg 340µs/call # spent 542µs making 17 calls to Mail::SpamAssassin::Conf::Parser::set_template_append, avg 32µs/call # spent 394µs making 4 calls to Mail::SpamAssassin::Conf::Parser::set_numeric_value, avg 99µs/call # spent 314µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:609] # spent 255µs making 5 calls to Mail::SpamAssassin::Conf::Parser::set_bool_value, avg 51µs/call # spent 201µs making 2 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1419], avg 100µs/call # spent 195µs making 36 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3402], avg 5µs/call # spent 94µs making 3 calls to Mail::SpamAssassin::Conf::Parser::set_string_value, avg 31µs/call # spent 87µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:581] # spent 85µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3835] # spent 80µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3858] # spent 56µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1007] # spent 52µs making 2 calls to Mail::SpamAssassin::Conf::Parser::set_template_clear, avg 26µs/call # spent 48µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1054] # spent 32µs making 1 call to Mail::SpamAssassin::Plugin::TxRep::__ANON__[Mail/SpamAssassin/Plugin/TxRep.pm:491] # spent 22µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1437]
439
440566613.3ms if ($ret && $ret eq $Mail::SpamAssassin::Conf::INVALID_VALUE)
441 {
442 $parse_error = "config: SpamAssassin failed to parse line, ".
443 "\"$value\" is not valid for \"$key\", ".
444 "skipping: $line";
445 goto failed_line;
446 }
447 elsif ($ret && $ret eq $Mail::SpamAssassin::Conf::INVALID_HEADER_FIELD_NAME)
448 {
449 $parse_error = "config: SpamAssassin failed to parse line, ".
450 "it does not specify a valid header field name, ".
451 "skipping: $line";
452 goto failed_line;
453 }
454 elsif ($ret && $ret eq $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE)
455 {
456 $parse_error = "config: SpamAssassin failed to parse line, ".
457 "no value provided for \"$key\", ".
458 "skipping: $line";
459 goto failed_line;
460 }
461 else {
462566626.1ms next;
463 }
464 }
465
466 # last ditch: try to see if the plugins know what to do with it
4675015.68ms501167ms if ($conf->{main}->call_plugins("parse_config", {
# spent 167ms making 501 calls to Mail::SpamAssassin::call_plugins, avg 334µ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.
4765012.72ms 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
49716µ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
50018µs1123ms $self->set_default_scores();
501117µs1154ms $self->check_for_missing_descriptions();
502
503126µs delete $self->{scoresonly};
504}
505
506
# spent 211ms (142+68.6) within Mail::SpamAssassin::Conf::Parser::handle_conditional which was called 508 times, avg 415µs/call: # 360 times (87.7ms+42.3ms) by Mail::SpamAssassin::Conf::Parser::parse at line 349, avg 361µs/call # 148 times (54.4ms+26.3ms) by Mail::SpamAssassin::Conf::Parser::parse at line 355, avg 546µs/call
sub handle_conditional {
5075082.61ms my ($self, $key, $value, $if_stack_ref, $skip_parsing_ref) = @_;
5085081.31ms my $conf = $self->{conf};
509
510508894µs my $lexer = ARITH_EXPRESSION_LEXER;
51150820.0ms101610.3ms my @tokens = ($value =~ m/($lexer)/g);
# spent 7.34ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 14µs/call # spent 3.00ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 6µs/call
512
5135081.05ms my $eval = '';
514508894µs my $bad = 0;
5155082.19ms foreach my $token (@tokens) {
516216160.8ms265010.6ms if ($token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/) {
# spent 10.6ms 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.93ms116427.6ms my $u = untaint_var($token);
# spent 27.6ms making 1164 calls to Mail::SpamAssassin::Util::untaint_var, avg 24µs/call
51911642.70ms $eval .= $u . " ";
520 }
521 elsif ($token eq 'plugin') {
522 # replace with a method call
523434859µs $eval .= '$self->cond_clause_plugin_loaded';
524 }
525 elsif ($token eq 'can') {
526 # replace with a method call
52755131µs $eval .= '$self->cond_clause_can';
528 }
529 elsif ($token eq 'has') {
530 # replace with a method call
531 $eval .= '$self->cond_clause_has';
532 }
533 elsif ($token eq 'version') {
5341962µs $eval .= $Mail::SpamAssassin::VERSION." ";
535 }
536 elsif ($token eq 'perl_version') {
537 $eval .= $]." ";
538 }
539 elsif ($token =~ /^\w[\w\:]+$/) { # class name
5404893.34ms48911.0ms my $u = untaint_var($token);
# spent 11.0ms making 489 calls to Mail::SpamAssassin::Util::untaint_var, avg 22µs/call
5414891.30ms $eval .= '"' . $u . '" ';
542 }
543 else {
544 $bad++;
545 warn "config: unparseable chars in 'if $value': '$token'\n";
546 }
547 }
548
549508929µs if ($bad) {
550 $self->lint_warn("bad 'if' line, in \"$self->{currentfile}\"", undef);
551 return -1;
552 }
553
55410165.41ms push (@{$if_stack_ref}, {
555 type => 'if',
556 conditional => $value,
557 skip_parsing => $$skip_parsing_ref
558 });
559
56050841.7ms if (eval $eval) {
# spent 875µs executing statements in 72 string evals (merged) # spent 675µs executing statements in 59 string evals (merged) # spent 507µs executing statements in 41 string evals (merged) # spent 382µs executing statements in 26 string evals (merged) # spent 335µs executing statements in 25 string evals (merged) # spent 326µs executing statements in 20 string evals (merged) # spent 255µs executing statements in 21 string evals (merged) # spent 197µs executing statements in 14 string evals (merged) # spent 189µs executing statements in 15 string evals (merged) # spent 162µs executing statements in 13 string evals (merged) # spent 142µs executing statements in 12 string evals (merged) # spent 135µs executing statements in 11 string evals (merged) # spent 131µs executing statements in 11 string evals (merged) # spent 109µs executing statements in 6 string evals (merged) # spent 102µs executing statements in 7 string evals (merged) # spent 102µs executing statements in 8 string evals (merged) # spent 100µs executing statements in 6 string evals (merged) # spent 100µs executing statements in 7 string evals (merged) # spent 96µs executing statements in 7 string evals (merged) # spent 87µs executing statements in 7 string evals (merged) # spent 76µs executing statements in 5 string evals (merged) # spent 75µs executing statements in 7 string evals (merged) # spent 75µs executing statements in 7 string evals (merged) # spent 73µs executing statements in 5 string evals (merged) # spent 72µs executing statements in 6 string evals (merged) # spent 71µs executing statements in 12 string evals (merged) # spent 64µs executing statements in 5 string evals (merged) # spent 63µs executing statements in 5 string evals (merged) # spent 56µ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 49µs executing statements in 4 string evals (merged) # spent 48µs executing statements in 3 string evals (merged) # spent 43µs executing statements in 3 string evals (merged) # spent 42µs executing statements in 2 string evals (merged) # spent 41µs executing statements in 3 string evals (merged) # spent 41µs executing statements in 2 string evals (merged) # spent 40µs executing statements in 3 string evals (merged) # spent 32µ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 29µs executing statements in 2 string evals (merged) # spent 28µs executing statements in 2 string evals (merged) # spent 28µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 23µs executing statements in string eval # spent 23µs executing statements in string eval # spent 22µ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 17µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in 3 string evals (merged) # 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 12µ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 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 {
564127297µs warn "config: error in $key - $eval: $@" if $@ ne '';
565127269µs $$skip_parsing_ref = 1;
566 }
567}
568
569# functions supported in the "if" eval:
570
# spent 3.99ms within Mail::SpamAssassin::Conf::Parser::cond_clause_plugin_loaded which was called 434 times, avg 9µs/call: # 72 times (619µ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 (467µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 287)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 41 times (356µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 132)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 26 times (225µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 823)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 25 times (243µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 154)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 20 times (144µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 742)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call # 15 times (118µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 289)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call # 14 times (166µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 128)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call # 13 times (107µ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 (115µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 279)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 11 times (111µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 170)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 11 times (110µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 201)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 8 times (47µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 115)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call # 7 times (85µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 754)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call # 7 times (83µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 275)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call # 7 times (71µ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 278)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 7 times (49µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 276)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call # 6 times (69µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 523)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call # 6 times (56µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 285)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 5 times (64µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 296)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 13µs/call # 5 times (49µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 207)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 5 times (49µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 335)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 5 times (45µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 473)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call # 4 times (58µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 347)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 15µs/call # 4 times (51µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 284)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 13µs/call # 4 times (28µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 945)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call # 3 times (45µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 131)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 15µs/call # 3 times (18µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 304)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call # 2 times (34µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 129)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 17µ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 15µs/call # 2 times (30µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 348)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 15µs/call # 2 times (26µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 363)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 13µs/call # 2 times (25µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 133)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 13µs/call # 2 times (21µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 261)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call # 2 times (21µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 925)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call # 2 times (11µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1007)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 5µs/call # once (18µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 942)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (16µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 116)[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 (12µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 231)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (12µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 277)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (7µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 372)[Mail/SpamAssassin/Conf/Parser.pm:560]
sub cond_clause_plugin_loaded {
5714349.07ms return $_[0]->{conf}->{plugins_loaded}->{$_[1]};
572}
573
574
# spent 5.14ms (942µs+4.20) within Mail::SpamAssassin::Conf::Parser::cond_clause_can which was called 55 times, avg 93µs/call: # 21 times (346µs+1.42ms) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 634)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 84µs/call # 7 times (102µs+510µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 932)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 87µs/call # 6 times (108µs+506µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 718)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 102µs/call # 5 times (98µs+413µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 290)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 102µs/call # 3 times (54µs+236µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 947)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 97µs/call # 3 times (49µs+228µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 940)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 92µs/call # 2 times (27µs+180µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 531)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 103µs/call # 2 times (30µs+170µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 120)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 100µs/call # once (32µs+95µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 299)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (21µs+94µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 114)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (18µs+88µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 529)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (26µs+79µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1075)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (12µs+93µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 118)[Mail/SpamAssassin/Conf/Parser.pm:560] # once (19µs+82µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 117)[Mail/SpamAssassin/Conf/Parser.pm:560]
sub cond_clause_can {
57555128µs my ($self, $method) = @_;
576551.12ms554.20ms $self->cond_clause_can_or_has('can', $method);
# spent 4.20ms making 55 calls to Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has, avg 76µs/call
577}
578
579sub cond_clause_has {
580 my ($self, $method) = @_;
581 $self->cond_clause_can_or_has('has', $method);
582}
583
584
# spent 4.20ms (2.63+1.56) within Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has which was called 55 times, avg 76µs/call: # 55 times (2.63ms+1.56ms) by Mail::SpamAssassin::Conf::Parser::cond_clause_can at line 576, avg 76µs/call
sub cond_clause_can_or_has {
58555118µs my ($self, $fn_name, $method) = @_;
586
58755269µs local($1,$2);
58855963µs55461µs if (!defined $method) {
# spent 461µ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.8ms2154µs
# spent 95µs (37+59) within Mail::SpamAssassin::Conf::Parser::BEGIN@592 which was called: # once (37µs+59µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 592
no strict "refs";
# spent 95µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@592 # spent 59µs making 1 call to strict::unimport
59355256µs my($module, $meth) = ($1, $2);
594 return 1 if UNIVERSAL::can($module,$meth) &&
5951102.36ms1101.10ms ( $fn_name eq 'has' || &{$method}() );
# spent 570µs making 55 calls to UNIVERSAL::can, avg 10µs/call # spent 192µs making 24 calls to Mail::SpamAssassin::Conf::feature_bug6558_free, avg 8µs/call # spent 96µs making 10 calls to Mail::SpamAssassin::Plugin::BodyEval::has_check_body_length, avg 10µs/call # spent 88µs making 7 calls to Mail::SpamAssassin::Conf::perl_min_version_5010000, avg 13µs/call # spent 43µs making 5 calls to Mail::SpamAssassin::Plugin::SPF::has_check_for_spf_errors, avg 9µs/call # spent 29µs making 2 calls to Mail::SpamAssassin::Conf::feature_registryboundaries, avg 14µs/call # spent 24µs making 2 calls to Mail::SpamAssassin::Plugin::MIMEEval::has_check_abundant_unicode_ratio, avg 12µs/call # spent 18µs making 1 call to Mail::SpamAssassin::Conf::feature_dns_local_ports_permit_avoid # spent 15µs making 1 call to Mail::SpamAssassin::Conf::feature_originating_ip_headers # spent 10µs making 1 call to Mail::SpamAssassin::Plugin::MIMEEval::has_check_for_ascii_text_illegal # spent 9µs making 1 call to Mail::SpamAssassin::Conf::feature_yesno_takes_args # spent 8µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::has_tflags_domains_only
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 123ms (119+4.59) within Mail::SpamAssassin::Conf::Parser::set_default_scores which was called: # once (119ms+4.59ms) by Mail::SpamAssassin::Conf::Parser::parse at line 500
sub set_default_scores {
63412µs my ($self) = @_;
63513µs my $conf = $self->{conf};
636
637206933.4ms while ( my $k = each %{$conf->{tests}} ) {
63820676.13ms if ( ! exists $conf->{scores}->{$k} ) {
639 # T_ rules (in a testing probationary period) get low, low scores
640128410.1ms12842.48ms my $set_score = ($k =~/^T_/) ? 0.01 : 1.0;
# spent 2.48ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
641
642128423.2ms12842.10ms $set_score = -$set_score if ( ($conf->{tflags}->{$k}||'') =~ /\bnice\b/ );
# spent 2.10ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
64312844.89ms for my $index (0..3) {
644513645.6ms $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 154ms (63.0+91.0) within Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions which was called: # once (63.0ms+91.0ms) by Mail::SpamAssassin::Conf::Parser::parse at line 501
sub check_for_missing_descriptions {
65314µs my ($self) = @_;
65413µs my $conf = $self->{conf};
655
656206930.9ms while ( my $k = each %{$conf->{tests}} ) {
657206724.9ms20676.61ms if ($k !~ m/^(?:T_|__)/i) {
# spent 6.61ms making 2067 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
65881510.6ms81583.9ms if ( ! exists $conf->{descriptions}->{$k} ) {
# spent 83.9ms making 815 calls to Mail::SpamAssassin::Util::TieOneStringHash::EXISTS, avg 103µs/call
65969876µs69441µs dbg("config: warning: no description set for $k");
# spent 441µs making 69 calls to Mail::SpamAssassin::Logger::dbg, avg 6µs/call
660 }
661 }
662 }
663}
664
665###########################################################################
666
667
# spent 510µs within Mail::SpamAssassin::Conf::Parser::setup_default_code_cb which was called 21 times, avg 24µs/call: # 21 times (510µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 433, avg 24µs/call
sub setup_default_code_cb {
6682142µs my ($self, $cmd) = @_;
66921166µs my $type = $cmd->{type};
670
67121119µs if ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_STRING) {
67239µs $cmd->{code} = \&set_string_value;
673 }
674 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL) {
675411µs $cmd->{code} = \&set_bool_value;
676 }
677 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC) {
678418µ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) {
68429µs $cmd->{code} = \&set_addrlist_value;
685 }
686 elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_TEMPLATE) {
68727µ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 }
70521152µ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 394µs (209+186) within Mail::SpamAssassin::Conf::Parser::set_numeric_value which was called 4 times, avg 99µs/call: # 4 times (209µs+186µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 99µs/call
sub set_numeric_value {
717435µs my ($conf, $key, $value, $line) = @_;
718
719439µs411µs unless (defined $value && $value !~ /^$/) {
# spent 11µs making 4 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
720 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
721 }
722459µs431µs unless ($value =~ /^ [+-]? \d+ (?: \. \d* )? \z/sx) {
# spent 31µs making 4 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 8µ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
726477µs4144µs $conf->{$key} = untaint_var($value) + 0;
# spent 144µs making 4 calls to Mail::SpamAssassin::Util::untaint_var, avg 36µ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 255µs (242+14) within Mail::SpamAssassin::Conf::Parser::set_bool_value which was called 5 times, avg 51µs/call: # 5 times (242µs+14µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 51µs/call
sub set_bool_value {
747543µs my ($conf, $key, $value, $line) = @_;
748
749555µs514µs unless (defined $value && $value !~ /^$/) {
# spent 14µs making 5 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
750 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
751 }
752
753 # bug 4462: allow yes/1 and no/0 for boolean values
754515µs $value = lc $value;
755532µ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
765567µs $conf->{$key} = $value;
766}
767
768
# spent 94µs (78+16) within Mail::SpamAssassin::Conf::Parser::set_string_value which was called 3 times, avg 31µs/call: # 3 times (78µs+16µ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
771338µs316µs unless (defined $value && $value !~ /^$/) {
# spent 16µs making 3 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call
772 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
773 }
774
775337µ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 260ms (57.2+202) within Mail::SpamAssassin::Conf::Parser::set_hash_key_value which was called 1276 times, avg 203µs/call: # 1276 times (57.2ms+202ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 203µs/call
sub set_hash_key_value {
80212766.70ms my ($conf, $key, $value, $line) = @_;
80312768.54ms my($k,$v) = split(/\s+/, $value, 2);
804
80512762.71ms unless (defined $v && $v ne '') {
806 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
807 }
808
809127630.7ms1684202ms $conf->{$key}->{$k} = $v; # keep tainted
# spent 110ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::STORE, avg 130µs/call # spent 92.6ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::FETCH, avg 110µs/call
810}
811
812
# spent 4.60ms (885µs+3.72) within Mail::SpamAssassin::Conf::Parser::set_addrlist_value which was called 34 times, avg 135µs/call: # 34 times (885µs+3.72ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 135µs/call
sub set_addrlist_value {
81334166µs my ($conf, $key, $value, $line) = @_;
814
81534303µs3490µs unless (defined $value && $value !~ /^$/) {
# spent 90µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
816 return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
817 }
81834482µs343.63ms $conf->{parser}->add_to_addrlist ($key, split (' ', $value)); # keep tainted
# spent 3.63ms making 34 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist, avg 107µ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 542µs (494+48) within Mail::SpamAssassin::Conf::Parser::set_template_append which was called 17 times, avg 32µs/call: # 17 times (494µs+48µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 32µs/call
sub set_template_append {
83117200µs my ($conf, $key, $value, $line) = @_;
83218153µs1748µs if ( $value =~ /^"(.*?)"$/ ) { $value = $1; }
# spent 48µs making 17 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
83317193µs $conf->{$key} .= $value."\n"; # keep tainted
834}
835
836
# spent 52µs within Mail::SpamAssassin::Conf::Parser::set_template_clear which was called 2 times, avg 26µs/call: # 2 times (52µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 26µs/call
sub set_template_clear {
837219µs my ($conf, $key, $value, $line) = @_;
83825µs unless (!defined $value || $value eq '') {
839 return $Mail::SpamAssassin::Conf::INVALID_VALUE;
840 }
841221µs $conf->{$key} = '';
842}
843
844###########################################################################
845
846
# spent 6.01s (104ms+5.91) within Mail::SpamAssassin::Conf::Parser::finish_parsing which was called: # once (104ms+5.91s) 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.
85217µs if (!$isuserconf) {
853115µs1752µs $conf->{main}->call_plugins("finish_parsing_start", { conf => $conf });
# spent 752µs making 1 call to Mail::SpamAssassin::call_plugins
854 } else {
855 $conf->{main}->call_plugins("user_conf_parsing_start", { conf => $conf });
856 }
857
8581373µs15.49s $self->trace_meta_dependencies();
8591175µs1111ms $self->fix_priorities();
# spent 111ms making 1 call to Mail::SpamAssassin::Conf::Parser::fix_priorities
860
861 # don't do this if allow_user_rules is active, since it deletes entries
862 # from {tests}
863112µs if (!$conf->{allow_user_rules}) {
864113µs1116ms $self->find_dup_rules(); # must be after fix_priorities()
# spent 116ms making 1 call to Mail::SpamAssassin::Conf::Parser::find_dup_rules
865 }
866
86718µs18µs dbg("config: finish parsing");
# spent 8µs making 1 call to Mail::SpamAssassin::Logger::dbg
868
869205833.8ms while (my ($name, $text) = each %{$conf->{tests}}) {
87020564.10ms my $type = $conf->{test_types}->{$name};
87120565.16ms my $priority = $conf->{priority}->{$name} || 0;
87220563.74ms $conf->{priorities}->{$priority}++;
873
874 # eval type handling
87520566.52ms if (($type & 1) == 1) {
87637921.6ms3794.62ms if (my ($function, $args) = ($text =~ m/(.*?)\s*\((.*?)\)\s*$/)) {
# spent 4.62ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 12µs/call
8773792.99ms37947.1ms my ($packed, $argsref) =
# spent 47.1ms making 379 calls to Mail::SpamAssassin::Conf::Parser::pack_eval_method, avg 124µs/call
878 $self->pack_eval_method($function, $args, $name, $text);
879
8803792.18ms if (!$packed) {
881 # we've already warned about this
882 }
883 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS) {
8841871.62ms $conf->{body_evals}->{$priority}->{$name} = $packed;
885 }
886 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS) {
887101894µ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
89273872µs $conf->{rbl_evals}->{$name} = [ $function, @$argsref ];
893 }
894 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_EVALS) {
895766µs $conf->{rawbody_evals}->{$priority}->{$name} = $packed;
896 }
897 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_EVALS) {
8981194µ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.45ms if ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS) {
9145134.60ms $conf->{body_tests}->{$priority}->{$name} = $text;
915 }
916 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS) {
9175955.17ms $conf->{head_tests}->{$priority}->{$name} = $text;
918 }
919 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
9204634.11ms $conf->{meta_tests}->{$priority}->{$name} = $text;
921 }
922 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS) {
92369592µs $conf->{uri_tests}->{$priority}->{$name} = $text;
924 }
925 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS) {
92633298µs $conf->{rawbody_tests}->{$priority}->{$name} = $text;
927 }
928 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS) {
929219µ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µs120µs $self->lint_trusted_networks();
940
94115µs if (!$isuserconf) {
942115µs1134ms $conf->{main}->call_plugins("finish_parsing_end", { conf => $conf });
# spent 134ms making 1 call to Mail::SpamAssassin::call_plugins
943 } else {
944 $conf->{main}->call_plugins("user_conf_parsing_end", { conf => $conf });
945 }
946
947112µs124µs $conf->found_any_rules(); # before we might delete {tests}
# spent 24µs making 1 call to Mail::SpamAssassin::Conf::found_any_rules
948
949122µs if (!$conf->{allow_user_rules}) {
950 # free up stuff we no longer need
95111.82ms delete $conf->{tests};
9521526µs delete $conf->{priority};
953 #test_types are needed - see bug 5503
954 #delete $conf->{test_types};
955 }
956}
957
958
# spent 5.49s (31.3ms+5.46) within Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies which was called: # once (31.3ms+5.46s) 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.21ms foreach my $name (keys %{$conf->{tests}}) {
96420679.45ms next unless ($conf->{test_types}->{$name}
965 == $Mail::SpamAssassin::Conf::TYPE_META_TESTS);
966
967464982µs my $deps = [ ];
968464836µs my $alreadydone = { };
9694643.02ms4645.46s $self->_meta_deps_recurse($conf, $name, $name, $deps, $alreadydone);
# spent 5.46s making 464 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 11.8ms/call
97092813.2ms $conf->{meta_dependencies}->{$name} = join (' ', @{$deps});
971 }
972}
973
974
# spent 5.46s (4.00+1.46) within Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse which was called 13832 times, avg 395µs/call: # 13368 times (3.81s+-3.81s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 1000, avg 0s/call # 464 times (191ms+5.27s) by Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies at line 969, avg 11.8ms/call
sub _meta_deps_recurse {
9751383228.2ms my ($self, $conf, $toprule, $name, $deps, $alreadydone) = @_;
976
977 # Only do each rule once per top-level meta; avoid infinite recursion
9781383246.5ms return if $alreadydone->{$name};
9791132374.2ms $alreadydone->{$name} = 1;
980
981 # Obviously, don't trace empty or nonexistent rules
9821132352.3ms my $rule = $conf->{tests}->{$name};
9831132319.0ms return unless $rule;
984
985 # Lex the rule into tokens using a rather simple RE method ...
9861132118.5ms my $lexer = ARITH_EXPRESSION_LEXER;
98711321796ms22642519ms my @tokens = ($rule =~ m/$lexer/g);
# spent 479ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 42µs/call # spent 40.4ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 4µs/call
988
989 # Go through each token in the meta rule
9901132121.7ms my $conf_tests = $conf->{tests};
99111321586ms foreach my $token (@tokens) {
992 # has to be an alpha+numeric token
993 # next if $token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/;
9942694482.75s269448610ms next if $token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s; # faster
# spent 610ms making 269448 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call
995 # and has to be a rule name
996120401440ms next unless exists $conf_tests->{$token};
997
998 # add and recurse
99926736142ms13368335ms push(@{$deps}, untaint_var($token));
# spent 335ms making 13368 calls to Mail::SpamAssassin::Util::untaint_var, avg 25µs/call
100013368108ms133680s $self->_meta_deps_recurse($conf, $toprule, $token, $deps, $alreadydone);
# spent 11.0s making 13368 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 825µs/call, recursion: max depth 7, sum of overlapping time 11.0s
1001 }
1002}
1003
1004
# spent 111ms (91.0+20.1) within Mail::SpamAssassin::Conf::Parser::fix_priorities which was called: # once (91.0ms+20.1ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 859
sub fix_priorities {
100512µs my ($self) = @_;
100614µs my $conf = $self->{conf};
1007
100812µs die unless $conf->{meta_dependencies}; # order requirement
100913µs my $pri = $conf->{priority};
1010
1011 # sort into priority order, lowest first -- this way we ensure that if we
1012 # rearrange the pri of a rule early on, we cannot accidentally increase its
1013 # priority later.
101413.15ms120.1ms foreach my $rule (sort {
# spent 20.1ms making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:sort
1015978320.1ms $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
102020678.04ms my $deps = $conf->{meta_dependencies}->{$rule};
102120673.28ms next unless (defined $deps);
1022
10234641.03ms my $basepri = $pri->{$rule};
10244649.44ms foreach my $dep (split ' ', $deps) {
10251336825.0ms my $deppri = $pri->{$dep};
10261336841.1ms 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 116ms (112+3.45) within Mail::SpamAssassin::Conf::Parser::find_dup_rules which was called: # once (112ms+3.45ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 864
sub find_dup_rules {
103514µs my ($self) = @_;
103613µs my $conf = $self->{conf};
1037
103812µs my %names_for_text;
1039 my %dups;
1040206935.4ms while (my ($name, $text) = each %{$conf->{tests}}) {
104120674.30ms my $type = $conf->{test_types}->{$name};
1042
1043 # skip eval and empty tests
104420673.80ms next if ($type & 1) ||
1045 ($type eq $Mail::SpamAssassin::Conf::TYPE_EMPTY_TESTS);
1046
1047337238.9ms16863.24ms my $tf = ($conf->{tflags}->{$name}||''); $tf =~ s/\s+/ /gs;
# spent 3.24ms 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"
105016865.00ms $text = "$type\t$text\t$tf";
1051
105216867.32ms if (defined $names_for_text{$text}) {
10531190µs $names_for_text{$text} .= " ".$name;
10541140µs $dups{$text} = undef; # found (at least) one
1055 } else {
1056167518.9ms $names_for_text{$text} = $name;
1057 }
1058 }
1059
10601914µs foreach my $text (keys %dups) {
10611015µs my $first;
1062 my $first_pri;
106322257µ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
10641041µs foreach my $name (@names) {
106521184µs my $priority = $conf->{priority}->{$name} || 0;
1066
10672186µs if (!defined $first || $priority < $first_pri) {
10681015µs $first_pri = $priority;
10691023µs $first = $name;
1070 }
1071 }
1072 # $first is now the earliest-occurring rule. mark others as dups
1073
10741015µs my @dups;
10751046µs foreach my $name (@names) {
10762136µs next if $name eq $first;
10771146µs push @dups, $name;
107811108µs delete $conf->{tests}->{$name};
1079 }
1080
108110173µs10130µs dbg("rules: $first merged duplicates: ".join(' ', @dups));
# spent 130µs making 10 calls to Mail::SpamAssassin::Logger::dbg, avg 13µs/call
108210132µs $conf->{duplicate_rules}->{$first} = \@dups;
1083 }
1084}
1085
1086
# spent 47.1ms (39.4+7.66) within Mail::SpamAssassin::Conf::Parser::pack_eval_method which was called 379 times, avg 124µs/call: # 379 times (39.4ms+7.66ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 877, avg 124µs/call
sub pack_eval_method {
10873793.54ms my ($self, $function, $args, $name, $text) = @_;
1088
1089379583µs my @args;
10903791.29ms 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.51ms local($1,$2,$3);
10963797.27ms3793.08ms while ($args =~ s/^\s* (?: (['"]) (.*?) \1 | ( [\d\.:A-Za-z-]+? ) )
# spent 3.08ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 8µs/call
1097 \s* (?: , \s* | $ )//x) {
10984839.23ms4832.67ms if (defined $2) {
# spent 2.67ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 6µs/call
10994743.15ms push @args, $2;
1100 }
1101 else {
1102973µs push @args, $3;
1103 }
1104 }
1105 }
1106
1107379704µs if ($args ne '') {
1108 $self->lint_warn("syntax error (unparsable argument: $args) for eval function: $name: $text", $name);
1109 return;
1110 }
1111
1112379788µs my $argstr = $function;
11133794.05ms379898µs $argstr =~ s/\s+//gs;
# spent 898µs making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1114
11153791.52ms if (@args > 0) {
1116 $argstr .= ',' . join(', ',
1117170410.8ms4831.01ms map { my $s = $_; $s =~ s/\#/[HASH]/gs; 'q#' . $s . '#' } @args);
# spent 1.01ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1118 }
11193793.90ms return ($argstr, \@args);
1120}
1121
1122###########################################################################
1123
1124
# spent 20µs within Mail::SpamAssassin::Conf::Parser::lint_trusted_networks which was called: # once (20µ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 {
1141116µ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 726ms (207+519) within Mail::SpamAssassin::Conf::Parser::add_test which was called 2074 times, avg 350µs/call: # 548 times (70.6ms+118ms) 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 344µs/call # 513 times (43.4ms+144ms) 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 364µs/call # 465 times (50.0ms+225ms) 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 592µs/call # 142 times (10.4ms+909µ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 79µs/call # 102 times (7.66ms+641µ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 81µs/call # 73 times (5.20ms+447µ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 77µs/call # 71 times (6.13ms+21.9ms) 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 395µs/call # 58 times (4.93ms+717µ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 97µs/call # 46 times (3.49ms+318µ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 83µs/call # 33 times (3.45ms+7.01ms) 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 317µs/call # 11 times (884µs+78µ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 87µs/call # 7 times (495µs+79µ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 82µs/call # 2 times (190µs+314µ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 252µs/call # 2 times (121µs+13µ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 67µs/call # once (90µs+13µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3206] at line 3204 of Mail/SpamAssassin/Conf.pm
sub add_test {
117720749.88ms my ($self, $name, $text, $type) = @_;
117820744.45ms my $conf = $self->{conf};
1179
1180 # Don't allow invalid names ...
1181207429.5ms20747.72ms if ($name !~ /^\D\w*$/) {
# spent 7.72ms 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.81ms 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.96ms 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.37ms 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.26ms619169ms return unless $self->is_delimited_regexp_valid($name, $text);
# spent 169ms making 619 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 273µs/call
1211 }
121220745.90ms if ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS)
1213 {
1214 # RFC 5322 section 3.6.8, ftext printable US-ASCII chars not including ":"
1215 # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables...
12166066.90ms6061.83ms if ($text =~ /^!?defined\([!-9;-\176]+\)$/) {
# spent 1.83ms making 606 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
1217 # fine, implements 'exists:'
1218 } else {
121954820.3ms5487.66ms my ($pat) = ($text =~ /^\s*\S+\s*(?:\=|\!)\~\s*(\S.*?\S)\s*$/);
# spent 7.66ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 14µs/call
122010966.89ms5481.51ms if ($pat) { $pat =~ s/\s+\[if-unset:\s+(.+)\]\s*$//; }
# spent 1.51ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
12215483.94ms548104ms return unless $self->is_delimited_regexp_valid($name, $pat);
# spent 104ms making 548 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 190µs/call
1222 }
1223 }
1224 elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS)
1225 {
12264653.27ms465222ms return unless $self->is_meta_valid($name, $text);
# spent 222ms making 465 calls to Mail::SpamAssassin::Conf::Parser::is_meta_valid, avg 477µs/call
1227 }
1228
1229207426.8ms $conf->{tests}->{$name} = $text;
123020749.36ms $conf->{test_types}->{$name} = $type;
1231
1232207418.7ms20745.46ms if ($name =~ /AUTOLEARNTEST/i) {
# spent 5.46ms 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
123720747.18ms if ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
12384653.67ms $conf->{priority}->{$name} ||= 500;
1239 }
1240 else {
1241160912.0ms $conf->{priority}->{$name} ||= 0;
1242 }
124320744.63ms $conf->{priority}->{$name} ||= 0;
1244207418.8ms $conf->{source_file}->{$name} = $self->{currentfile};
1245
124620744.29ms if ($conf->{main}->{keep_config_parsing_metadata}) {
1247 $conf->{if_stack}->{$name} = $self->get_if_stack_as_string();
1248
1249 if ($self->{file_scoped_attrs}->{testrules}) {
1250 $conf->{testrules}->{$name} = 1; # used in build/mkupdates/listpromotable
1251 }
1252 }
1253
1254 # if we found this rule in a user_prefs file, it's a user rule -- note that
1255 # we may need to recompile the rule code for this type (if they've already
1256 # been compiled, e.g. in spamd).
1257 #
1258 # Note: the want_rebuild_for_type 'flag' is actually a counter; it is decremented
1259 # after each scan. This ensures that we always recompile at least once more;
1260 # once to *define* the rule, and once afterwards to *undefine* the rule in the
1261 # compiled ruleset again.
1262 #
1263 # If two consecutive scans use user rules, that's ok -- the second one will
1264 # reset the counter, and we'll still recompile just once afterwards to undefine
1265 # the rule again.
1266 #
1267207425.8ms if ($self->{scoresonly}) {
1268 $conf->{want_rebuild_for_type}->{$type} = 2;
1269 $conf->{user_defined_rules}->{$name} = 1;
1270 }
1271}
1272
1273sub add_regression_test {
1274 my ($self, $name, $ok_or_fail, $string) = @_;
1275 my $conf = $self->{conf};
1276
1277 if ($conf->{regression_tests}->{$name}) {
1278 push @{$conf->{regression_tests}->{$name}}, [$ok_or_fail, $string];
1279 }
1280 else {
1281 # initialize the array, and create one element
1282 $conf->{regression_tests}->{$name} = [ [$ok_or_fail, $string] ];
1283 }
1284}
1285
1286
# spent 222ms (169+53.3) within Mail::SpamAssassin::Conf::Parser::is_meta_valid which was called 465 times, avg 477µs/call: # 465 times (169ms+53.3ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1226, avg 477µs/call
sub is_meta_valid {
12874652.29ms my ($self, $name, $rule) = @_;
1288
1289465997µs my $meta = '';
12904653.56ms46512.7ms $rule = untaint_var($rule); # must be careful below
# spent 12.7ms making 465 calls to Mail::SpamAssassin::Util::untaint_var, avg 27µs/call
1291
1292 # Lex the rule into tokens using a rather simple RE method ...
1293465961µs my $lexer = ARITH_EXPRESSION_LEXER;
129446528.2ms93018.8ms 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.27ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 5µs/call
12954651.29ms 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.85ms foreach my $token (@tokens) {
1302 # Numbers can't be rule names
13037210113ms721021.8ms if ($token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s) {
# spent 21.8ms making 7210 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call
130441127.84ms $meta .= "$token ";
1305 }
1306 # Zero will probably cause more errors
1307 else {
130830985.59ms $meta .= "0 ";
1309 }
1310 }
1311
13124651.30ms my $evalstr = 'my $x = ' . $meta . '; 1;';
131346529.8ms if (eval $evalstr) {
# spent 502µs executing statements in 42 string evals (merged) # spent 413µs executing statements in 37 string evals (merged) # spent 304µs executing statements in 2 string evals (merged) # spent 299µs executing statements in 24 string evals (merged) # spent 284µs executing statements in 26 string evals (merged) # spent 197µs executing statements in 17 string evals (merged) # spent 185µs executing statements in 20 string evals (merged) # spent 172µs executing statements in 14 string evals (merged) # spent 134µs executing statements in 12 string evals (merged) # spent 116µs executing statements in 8 string evals (merged) # spent 104µs executing statements in 8 string evals (merged) # spent 96µs executing statements in 6 string evals (merged) # spent 85µs executing statements in 6 string evals (merged) # spent 82µs executing statements in 5 string evals (merged) # spent 80µs executing statements in 8 string evals (merged) # spent 78µs executing statements in 8 string evals (merged) # spent 74µs executing statements in 5 string evals (merged) # spent 72µs executing statements in 7 string evals (merged) # spent 72µs executing statements in 7 string evals (merged) # spent 71µs executing statements in 5 string evals (merged) # spent 70µs executing statements in 6 string evals (merged) # spent 66µs executing statements in 5 string evals (merged) # spent 57µs executing statements in 6 string evals (merged) # spent 57µs executing statements in 4 string evals (merged) # spent 49µs executing statements in 3 string evals (merged) # spent 45µs executing statements in 4 string evals (merged) # spent 43µs executing statements in 3 string evals (merged) # spent 40µs executing statements in 3 string evals (merged) # spent 39µs executing statements in 3 string evals (merged) # spent 38µs executing statements in 3 string evals (merged) # spent 37µ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 33µs executing statements in 2 string evals (merged) # spent 31µs executing statements in 2 string evals (merged) # spent 31µs executing statements in 2 string evals (merged) # spent 30µs executing statements in 2 string evals (merged) # spent 29µs executing statements in 3 string evals (merged) # spent 29µs executing statements in 2 string evals (merged) # spent 28µs executing statements in 2 string evals (merged) # spent 28µ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 26µs executing statements in 2 string evals (merged) # spent 25µs executing statements in string eval # spent 25µs executing statements in string eval # spent 25µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 24µs executing statements in 2 string evals (merged) # spent 23µs executing statements in 2 string evals (merged) # spent 23µs executing statements in 2 string evals (merged) # spent 23µs executing statements in 3 string evals (merged) # spent 23µs executing statements in string eval # spent 22µ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 string eval # spent 20µs executing statements in string eval # spent 20µs executing statements in 2 string evals (merged) # spent 20µs executing statements in string eval # spent 18µs executing statements in 2 string evals (merged) # spent 17µs executing statements in 2 string evals (merged) # spent 17µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 16µs executing statements in string eval # spent 15µs executing statements in string eval # spent 15µs executing statements in string eval # spent 15µs executing statements in string eval # spent 15µs executing statements in string eval # 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 string eval # spent 15µs executing statements in 2 string evals (merged) # spent 14µs executing statements in string eval # spent 14µs executing statements in string eval # 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 14µs executing statements in string eval # 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 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 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 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 10µs executing statements in string eval # spent 10µs executing statements in string eval # spent 10µs executing statements in string eval # spent 10µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 9µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 8µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval # spent 7µs executing statements in string eval
13144656.33ms 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 285ms (46.2+238) within Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid which was called 1228 times, avg 232µs/call: # 619 times (31.3ms+138ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1210, avg 273µs/call # 548 times (13.4ms+90.7ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1221, avg 190µs/call # 46 times (1.12ms+7.47ms) 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 187µs/call # 15 times (380µs+2.63ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2701] at line 2685 of Mail/SpamAssassin/Conf.pm, avg 201µs/call
sub is_delimited_regexp_valid {
132412286.15ms my ($self, $name, $re) = @_;
1325
1326122823.3ms12287.36ms if (!$re || $re !~ /^\s*m?(\W).*(?:\1|>|}|\)|\])[a-z]*\s*$/) {
# spent 7.36ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 6µs/call
1327 $re ||= '';
1328 $self->lint_warn("config: invalid regexp for rule $name: $re: missing or invalid delimiters\n", $name);
1329 return 0;
1330 }
1331122815.1ms1228231ms return $self->is_regexp_valid($name, $re);
# spent 231ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::is_regexp_valid, avg 188µs/call
1332}
1333
1334
# spent 231ms (123+108) within Mail::SpamAssassin::Conf::Parser::is_regexp_valid which was called 1228 times, avg 188µs/call: # 1228 times (123ms+108ms) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1331, avg 188µs/call
sub is_regexp_valid {
133512285.97ms 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.83ms my $origre = $re;
134112282.77ms my $safere = $re;
134212282.34ms my $mods = '';
134312284.45ms local ($1,$2);
1344122863.1ms603419.4ms if ($re =~ s/^m\{//) {
# spent 19.4ms making 6034 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
134528269µs14113µs $re =~ s/\}([a-z]*)\z//; $mods = $1;
# spent 113µs making 14 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 8µ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.20ms1001.19ms $re =~ s/\Q$1\E([a-z]*)\z//; $mods = $1;
# spent 780µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 16µs/call # spent 413µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 8µs/call
1355 }
1356 elsif ($re =~ s{^/(.*)/([a-z]*)\z}{$1}) {
135711643.62ms $mods = $2;
1358 }
1359 else {
1360 $safere = "m#".$re."#";
1361 }
1362
136312283.18ms 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) {
13807883.55ms $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...
13886140145ms245687.1ms if (eval { ("" =~ m{$re}); 1; }) { return 1 }
# spent 84.7ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 69µs/call # spent 2.35ms 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 3.63ms (2.73+896µs) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist which was called 34 times, avg 107µs/call: # 34 times (2.73ms+896µs) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 818, avg 107µs/call
sub add_to_addrlist {
141734148µs my ($self, $singlelist, @addrs) = @_;
14183467µs my $conf = $self->{conf};
1419
142034323µs foreach my $addr (@addrs) {
142134102µs $addr = lc $addr;
14223471µs my $re = $addr;
142334290µs3484µs $re =~ s/[\000\\\(]/_/gs; # paranoia
# spent 84µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1424341.54ms152574µs $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
# spent 424µs making 118 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 4µs/call # spent 150µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
142534103µs $re =~ tr/?/./; # "?" -> "."
142634507µs34239µs $re =~ s/\*+/\.\*/g; # "*" -> "any string"
# spent 239µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µs/call
142734537µs $conf->{$singlelist}->{$addr} = "^${re}\$";
1428 }
1429}
1430
1431
# spent 10.4ms (7.71+2.64) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd which was called 102 times, avg 101µs/call: # 83 times (6.12ms+2.15ms) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim at line 1470, avg 100µs/call # 19 times (1.59ms+483µ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 109µs/call
sub add_to_addrlist_rcvd {
1432102379µs my ($self, $listname, $addr, $domain) = @_;
1433102194µs my $conf = $self->{conf};
1434
1435102231µs $domain = lc $domain;
1436102229µs $addr = lc $addr;
1437102964µs if ($conf->{$listname}->{$addr}) {
14381043µs push @{$conf->{$listname}->{$addr}{domain}}, $domain;
1439 }
1440 else {
144197202µs my $re = $addr;
144297789µs97235µs $re =~ s/[\000\\\(]/_/gs; # paranoia
# spent 235µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
1443974.00ms4581.67ms $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars
# spent 1.25ms making 361 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 3µs/call # spent 418µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call
144497269µs $re =~ tr/?/./; # "?" -> "."
1445971.34ms97736µs $re =~ s/\*+/\.\*/g; # "*" -> "any string"
# spent 736µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 8µs/call
1446971.41ms $conf->{$listname}->{$addr}{re} = "^${re}\$";
144797532µs $conf->{$listname}->{$addr}{domain} = [ $domain ];
1448 }
1449}
1450
1451sub remove_from_addrlist {
1452 my ($self, $singlelist, @addrs) = @_;
1453 my $conf = $self->{conf};
1454
1455 foreach my $addr (@addrs) {
1456 delete($conf->{$singlelist}->{lc $addr});
1457 }
1458}
1459
1460sub remove_from_addrlist_rcvd {
1461 my ($self, $listname, @addrs) = @_;
1462 my $conf = $self->{conf};
1463
1464 foreach my $addr (@addrs) {
1465 delete($conf->{$listname}->{lc $addr});
1466 }
1467}
1468
1469
# spent 9.26ms (980µs+8.28) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim which was called 83 times, avg 112µs/call: # 83 times (980µs+8.28ms) by Mail::SpamAssassin::Plugin::DKIM::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/DKIM.pm:420] at line 418 of Mail/SpamAssassin/Plugin/DKIM.pm, avg 112µs/call
sub add_to_addrlist_dkim {
1470837.90ms838.28ms add_to_addrlist_rcvd(@_);
# spent 8.28ms making 83 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd, avg 100µs/call
1471}
1472
1473sub remove_from_addrlist_dkim {
1474 my ($self, $listname, $addr, $domain) = @_;
1475 my $conf = $self->{conf};
1476 my $conf_lname = $conf->{$listname};
1477
1478 $addr = lc $addr;
1479 if ($conf_lname->{$addr}) {
1480 $domain = lc $domain;
1481 my $domains_listref = $conf_lname->{$addr}{domain};
1482 # removing $domain from the list
1483 my @replacement = grep { lc $_ ne $domain } @$domains_listref;
1484 if (!@replacement) { # nothing left, remove the entire addr entry
1485 delete($conf_lname->{$addr});
1486 } elsif (@replacement != @$domains_listref) { # anything changed?
1487 $conf_lname->{$addr}{domain} = \@replacement;
1488 }
1489 }
1490}
1491
1492
1493###########################################################################
1494
1495
# spent 23.2ms (4.67+18.6) within Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file which was called 58 times, avg 400µs/call: # 58 times (4.67ms+18.6ms) by Mail::SpamAssassin::Conf::Parser::parse at line 342, avg 400µs/call
sub fix_path_relative_to_current_file {
149658246µs my ($self, $path) = @_;
1497
1498 # the path may be specified as "~/foo", so deal with that
149958663µs5813.1ms $path = $self->{conf}->{main}->sed_path($path);
# spent 13.1ms making 58 calls to Mail::SpamAssassin::sed_path, avg 225µs/call
1500
150158982µs581.05ms if (!File::Spec->file_name_is_absolute ($path)) {
# spent 1.05ms making 58 calls to File::Spec::Unix::file_name_is_absolute, avg 18µs/call
150258680µs582.59ms my ($vol, $dirs, $file) = File::Spec->splitpath ($self->{currentfile});
# spent 2.59ms making 58 calls to File::Spec::Unix::splitpath, avg 45µs/call
150358588µs581.21ms $path = File::Spec->catpath ($vol, $dirs, $path);
# spent 1.21ms making 58 calls to File::Spec::Unix::catpath, avg 21µs/call
150458636µs58633µs dbg("config: fixed relative path: $path");
# spent 633µs making 58 calls to Mail::SpamAssassin::Logger::dbg, avg 11µs/call
1505 }
150658563µ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
1546112µs1;
 
# spent 1.24s within Mail::SpamAssassin::Conf::Parser::CORE:match which was called 322611 times, avg 4µs/call: # 269448 times (610ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 994, avg 2µs/call # 16436 times (44.9ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 273, avg 3µs/call # 11321 times (479ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 42µs/call # 7210 times (21.8ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1303, avg 3µs/call # 2650 times (10.6ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 516, avg 4µs/call # 2074 times (7.72ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1181, avg 4µs/call # 2074 times (5.46ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1232, avg 3µs/call # 2067 times (6.61ms+0s) by Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions at line 657, avg 3µs/call # 1474 times (3.60ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 2µs/call # 1284 times (2.48ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 640, avg 2µs/call # 1284 times (2.10ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 642, avg 2µs/call # 1228 times (7.36ms+0s) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1326, avg 6µs/call # 1228 times (2.35ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 2µs/call # 606 times (1.83ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1216, avg 3µs/call # 548 times (7.66ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1219, avg 14µs/call # 508 times (7.34ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 14µ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.62ms+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 876, avg 12µs/call # 136 times (734µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 302, avg 5µs/call # 68 times (382µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 308, avg 6µs/call # 55 times (461µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 588, avg 8µs/call # 34 times (90µs+0s) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 815, avg 3µs/call # 17 times (48µs+0s) by Mail::SpamAssassin::Conf::Parser::set_template_append at line 832, avg 3µs/call # 5 times (14µs+0s) by Mail::SpamAssassin::Conf::Parser::set_bool_value at line 749, avg 3µs/call # 4 times (31µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 722, avg 8µs/call # 4 times (11µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 719, avg 3µs/call # 3 times (16µs+0s) by Mail::SpamAssassin::Conf::Parser::set_string_value at line 771, avg 5µs/call # once (8µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 240
sub Mail::SpamAssassin::Conf::Parser::CORE:match; # opcode
# spent 137ms within Mail::SpamAssassin::Conf::Parser::CORE:regcomp which was called 15046 times, avg 9µs/call: # 11321 times (40.4ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 4µs/call # 1474 times (6.07ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 4µs/call # 1228 times (84.7ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 69µs/call # 508 times (3.00ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 6µs/call # 465 times (2.27ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 5µs/call # 50 times (780µ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 20.1ms within Mail::SpamAssassin::Conf::Parser::CORE:sort which was called 11 times, avg 1.83ms/call: # 10 times (78µs+0s) by Mail::SpamAssassin::Conf::Parser::find_dup_rules at line 1063, avg 8µs/call # once (20.1ms+0s) by Mail::SpamAssassin::Conf::Parser::fix_priorities at line 1014
sub Mail::SpamAssassin::Conf::Parser::CORE:sort; # opcode
# spent 265ms within Mail::SpamAssassin::Conf::Parser::CORE:subst which was called 92819 times, avg 3µs/call: # 16436 times (64.6ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 279, avg 4µs/call # 16436 times (54.7ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 282, avg 3µs/call # 16436 times (39.5ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 281, avg 2µs/call # 16436 times (32.7ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 280, avg 2µs/call # 9050 times (22.0ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 2µs/call # 7576 times (17.2ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 291, avg 2µs/call # 6034 times (19.4ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1344, avg 3µs/call # 1686 times (3.24ms+0s) by Mail::SpamAssassin::Conf::Parser::find_dup_rules at line 1047, avg 2µs/call # 548 times (1.51ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1220, avg 3µs/call # 483 times (2.67ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1098, avg 6µs/call # 483 times (1.01ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1117, avg 2µs/call # 379 times (3.08ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1096, avg 8µs/call # 379 times (898µs+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1113, avg 2µs/call # 97 times (736µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1445, avg 8µs/call # 97 times (418µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 4µs/call # 97 times (235µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1442, avg 2µs/call # 50 times (413µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 8µs/call # 34 times (239µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1426, avg 7µs/call # 34 times (150µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 4µs/call # 34 times (84µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1423, avg 2µs/call # 14 times (113µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1345, avg 8µs/call
sub Mail::SpamAssassin::Conf::Parser::CORE:subst; # opcode
# spent 1.67ms within Mail::SpamAssassin::Conf::Parser::CORE:substcont which was called 479 times, avg 3µs/call: # 361 times (1.25ms+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 3µs/call # 118 times (424µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 4µs/call
sub Mail::SpamAssassin::Conf::Parser::CORE:substcont; # opcode