Filename | /usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf/Parser.pm |
Statements | Executed 1032653 statements in 10.4s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
13832 | 2 | 1 | 5.47s | 7.09s | _meta_deps_recurse (recurses: max depth 7, inclusive time 14.6s) | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 1.83s | 5.03s | parse | Mail::SpamAssassin::Conf::Parser::
322611 | 28 | 1 | 1.32s | 1.32s | CORE:match (opcode) | Mail::SpamAssassin::Conf::Parser::
92819 | 21 | 1 | 272ms | 272ms | CORE:subst (opcode) | Mail::SpamAssassin::Conf::Parser::
2074 | 15 | 3 | 226ms | 785ms | add_test | Mail::SpamAssassin::Conf::Parser::
465 | 1 | 1 | 198ms | 252ms | is_meta_valid | Mail::SpamAssassin::Conf::Parser::
15046 | 6 | 1 | 157ms | 157ms | CORE:regcomp (opcode) | Mail::SpamAssassin::Conf::Parser::
508 | 2 | 1 | 142ms | 240ms | handle_conditional | Mail::SpamAssassin::Conf::Parser::
1228 | 1 | 1 | 132ms | 238ms | is_regexp_valid | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 120ms | 125ms | set_default_scores | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 114ms | 137ms | fix_priorities | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 101ms | 105ms | find_dup_rules | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 88.7ms | 7.67s | finish_parsing | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 75.2ms | 171ms | check_for_missing_descriptions | Mail::SpamAssassin::Conf::Parser::
1276 | 1 | 1 | 57.0ms | 273ms | set_hash_key_value | Mail::SpamAssassin::Conf::Parser::
379 | 1 | 1 | 51.1ms | 58.2ms | pack_eval_method | Mail::SpamAssassin::Conf::Parser::
1228 | 4 | 3 | 44.6ms | 291ms | is_delimited_regexp_valid | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 33.1ms | 7.12s | trace_meta_dependencies | Mail::SpamAssassin::Conf::Parser::
11 | 2 | 1 | 22.5ms | 22.5ms | CORE:sort (opcode) | Mail::SpamAssassin::Conf::Parser::
58 | 1 | 1 | 11.5ms | 41.2ms | fix_path_relative_to_current_file | Mail::SpamAssassin::Conf::Parser::
102 | 2 | 2 | 10.2ms | 13.3ms | add_to_addrlist_rcvd | Mail::SpamAssassin::Conf::Parser::
83 | 1 | 1 | 9.77ms | 20.5ms | add_to_addrlist_dkim | Mail::SpamAssassin::Conf::Parser::
434 | 43 | 43 | 3.80ms | 3.80ms | cond_clause_plugin_loaded | Mail::SpamAssassin::Conf::Parser::
16 | 1 | 1 | 2.98ms | 2.98ms | build_command_luts | Mail::SpamAssassin::Conf::Parser::
34 | 1 | 1 | 2.91ms | 4.09ms | add_to_addrlist | Mail::SpamAssassin::Conf::Parser::
55 | 1 | 1 | 2.90ms | 4.59ms | cond_clause_can_or_has | Mail::SpamAssassin::Conf::Parser::
479 | 2 | 1 | 2.18ms | 2.18ms | CORE:substcont (opcode) | Mail::SpamAssassin::Conf::Parser::
16 | 1 | 1 | 1.48ms | 1.48ms | set_defaults_from_command_list | Mail::SpamAssassin::Conf::Parser::
34 | 1 | 1 | 987µs | 5.24ms | set_addrlist_value | Mail::SpamAssassin::Conf::Parser::
55 | 14 | 14 | 960µs | 5.55ms | cond_clause_can | Mail::SpamAssassin::Conf::Parser::
16 | 16 | 16 | 791µs | 5.25ms | register_commands | Mail::SpamAssassin::Conf::Parser::
21 | 1 | 1 | 427µs | 427µs | setup_default_code_cb | Mail::SpamAssassin::Conf::Parser::
17 | 1 | 1 | 324µs | 368µs | set_template_append | Mail::SpamAssassin::Conf::Parser::
5 | 1 | 1 | 164µs | 184µs | set_bool_value | Mail::SpamAssassin::Conf::Parser::
4 | 1 | 1 | 158µs | 302µs | set_numeric_value | Mail::SpamAssassin::Conf::Parser::
3 | 1 | 1 | 83µs | 92µs | set_string_value | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 42µs | 42µs | BEGIN@137 | Mail::SpamAssassin::Conf::Parser::
2 | 1 | 1 | 35µs | 35µs | set_template_clear | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 30µs | 87µs | BEGIN@592 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 30µs | 30µs | new | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 24µs | 155µs | BEGIN@139 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 23µs | 239µs | BEGIN@140 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 21µs | 21µs | lint_trusted_networks | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 20µs | 27µs | BEGIN@145 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 20µs | 60µs | BEGIN@144 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 20µs | 91µs | BEGIN@146 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 19µs | 530µs | BEGIN@138 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 19µs | 30µs | BEGIN@143 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 18µs | 81µs | BEGIN@148 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 13µs | 13µs | lint_check | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 11µs | 11µs | BEGIN@141 | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | add_regression_test | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | cond_clause_has | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | get_if_stack_as_string | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | is_always_matching_regexp | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | lint_warn | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | remove_addrlist_value | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | remove_from_addrlist | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | remove_from_addrlist_dkim | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | remove_from_addrlist_rcvd | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | set_duration_value | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | set_ipaddr_list | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | set_no_value | Mail::SpamAssassin::Conf::Parser::
0 | 0 | 0 | 0s | 0s | set_string_list | Mail::SpamAssassin::Conf::Parser::
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 | |||||
20 | Mail::SpamAssassin::Conf::Parser - parse SpamAssassin configuration | ||||
21 | |||||
22 | =head1 SYNOPSIS | ||||
23 | |||||
24 | (see Mail::SpamAssassin) | ||||
25 | |||||
26 | =head1 DESCRIPTION | ||||
27 | |||||
28 | Mail::SpamAssassin is a module to identify spam using text analysis and | ||||
29 | several internet-based realtime blacklists. | ||||
30 | |||||
31 | This class is used internally by SpamAssassin to parse its configuration files. | ||||
32 | Please refer to the C<Mail::SpamAssassin> documentation for public interfaces. | ||||
33 | |||||
34 | =head1 STRUCTURE OF A CONFIG BLOCK | ||||
35 | |||||
36 | This is the structure of a config-setting block. Each is a hashref which may | ||||
37 | contain these keys: | ||||
38 | |||||
39 | =over 4 | ||||
40 | |||||
41 | =item setting | ||||
42 | |||||
43 | the name of the setting it modifies, e.g. "required_score". this also doubles | ||||
44 | as the default for 'command' (below). THIS IS REQUIRED. | ||||
45 | |||||
46 | =item command | ||||
47 | |||||
48 | The 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 | |||||
53 | An [aryref] of other aliases for the same command. optional. | ||||
54 | |||||
55 | =item type | ||||
56 | |||||
57 | The 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 | |||||
72 | If this is set, and a 'code' block does not already exist, a 'code' block is | ||||
73 | assigned based on the type. | ||||
74 | |||||
75 | In addition, the SpamAssassin test suite will validate that the settings | ||||
76 | do not 'leak' between users. | ||||
77 | |||||
78 | Note that C<$CONF_TYPE_HASH_KEY_VALUE>-type settings require that the | ||||
79 | value be non-empty, otherwise they'll produce a warning message. | ||||
80 | |||||
81 | =item code | ||||
82 | |||||
83 | A subroutine to deal with the setting. ONE OF B<code> OR B<type> IS REQUIRED. | ||||
84 | The arguments passed to the function are C<($self, $key, $value, $line)>, | ||||
85 | where $key is the setting (*not* the command), $value is the value string, | ||||
86 | and $line is the entire line. | ||||
87 | |||||
88 | There are two special return values that the B<code> subroutine may return | ||||
89 | to signal that there is an error in the configuration: | ||||
90 | |||||
91 | C<$Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE> -- this setting requires | ||||
92 | that a value be set, but one was not provided. | ||||
93 | |||||
94 | C<$Mail::SpamAssassin::Conf::INVALID_VALUE> -- this setting requires a value | ||||
95 | from a set of 'valid' values, but the user provided an invalid one. | ||||
96 | |||||
97 | C<$Mail::SpamAssassin::Conf::INVALID_HEADER_FIELD_NAME> -- this setting | ||||
98 | requires a syntactically valid header field name, but the user provided | ||||
99 | an invalid one. | ||||
100 | |||||
101 | Any other values -- including C<undef> -- returned from the subroutine are | ||||
102 | considered to mean 'success'. | ||||
103 | |||||
104 | It is good practice to set a 'type', if possible, describing how your settings | ||||
105 | are stored on the Conf object; this allows the SpamAssassin test suite to | ||||
106 | validate that the settings do not 'leak' between users. | ||||
107 | |||||
108 | =item default | ||||
109 | |||||
110 | The default value for the setting. may be omitted if the default value is a | ||||
111 | non-scalar type, which should be set in the Conf ctor. note for path types: | ||||
112 | using "__userstate__" is recommended for defaults, as it allows | ||||
113 | Mail::SpamAssassin module users who set that configuration setting, to receive | ||||
114 | the correct values. | ||||
115 | |||||
116 | =item is_priv | ||||
117 | |||||
118 | Set to 1 if this setting requires 'allow_user_rules' when run from spamd. | ||||
119 | |||||
120 | =item is_admin | ||||
121 | |||||
122 | Set to 1 if this setting can only be set in the system-wide config when run | ||||
123 | from spamd. (All settings can be used by local programs run directly by the | ||||
124 | user.) | ||||
125 | |||||
126 | =item is_frequent | ||||
127 | |||||
128 | Set to 1 if this value occurs frequently in the config. this means it's looked | ||||
129 | up first for speed. | ||||
130 | |||||
131 | =back | ||||
132 | |||||
133 | =cut | ||||
134 | |||||
135 | package Mail::SpamAssassin::Conf::Parser; | ||||
136 | |||||
137 | 2 | 71µs | 1 | 42µs | # spent 42µs within Mail::SpamAssassin::Conf::Parser::BEGIN@137 which was called:
# once (42µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 137 # spent 42µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@137 |
138 | 2 | 63µs | 2 | 1.04ms | # spent 530µs (19+511) within Mail::SpamAssassin::Conf::Parser::BEGIN@138 which was called:
# once (19µs+511µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 138 # spent 530µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@138
# spent 511µs making 1 call to Exporter::import |
139 | 2 | 62µs | 2 | 286µs | # spent 155µs (24+131) within Mail::SpamAssassin::Conf::Parser::BEGIN@139 which was called:
# once (24µs+131µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 139 # spent 155µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@139
# spent 131µs making 1 call to Exporter::import |
140 | 2 | 62µs | 2 | 455µs | # spent 239µs (23+216) within Mail::SpamAssassin::Conf::Parser::BEGIN@140 which was called:
# once (23µs+216µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 140 # spent 239µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@140
# spent 216µs making 1 call to Exporter::import |
141 | 2 | 48µs | 1 | 11µs | # spent 11µs within Mail::SpamAssassin::Conf::Parser::BEGIN@141 which was called:
# once (11µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 141 # spent 11µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@141 |
142 | |||||
143 | 2 | 50µs | 2 | 41µs | # spent 30µs (19+11) within Mail::SpamAssassin::Conf::Parser::BEGIN@143 which was called:
# once (19µs+11µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 143 # spent 30µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@143
# spent 11µs making 1 call to strict::import |
144 | 2 | 54µs | 2 | 99µs | # spent 60µs (20+40) within Mail::SpamAssassin::Conf::Parser::BEGIN@144 which was called:
# once (20µs+40µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 144 # spent 60µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@144
# spent 40µs making 1 call to warnings::import |
145 | 2 | 54µs | 2 | 34µs | # spent 27µs (20+7) within Mail::SpamAssassin::Conf::Parser::BEGIN@145 which was called:
# once (20µs+7µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 145 # spent 27µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@145
# spent 7µs making 1 call to bytes::import |
146 | 2 | 60µs | 2 | 162µs | # spent 91µs (20+71) within Mail::SpamAssassin::Conf::Parser::BEGIN@146 which was called:
# once (20µs+71µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 146 # spent 91µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@146
# spent 71µs making 1 call to re::import |
147 | |||||
148 | 1 | 2µs | # spent 81µs (18+62) within Mail::SpamAssassin::Conf::Parser::BEGIN@148 which was called:
# once (18µs+62µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 150 | ||
149 | @ISA | ||||
150 | 1 | 4.15ms | 2 | 143µs | }; # spent 81µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@148
# spent 62µs making 1 call to vars::import |
151 | |||||
152 | 1 | 14µ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 | ||||
157 | 1 | 2µs | my $class = shift; | ||
158 | 1 | 3µs | $class = ref($class) || $class; | ||
159 | 1 | 2µs | my ($conf) = @_; | ||
160 | |||||
161 | 1 | 3µs | my $self = { | ||
162 | 'conf' => $conf | ||||
163 | }; | ||||
164 | |||||
165 | 1 | 3µs | $self->{command_luts} = { }; | ||
166 | 1 | 4µs | $self->{command_luts}->{frequent} = { }; | ||
167 | 1 | 4µs | $self->{command_luts}->{remaining} = { }; | ||
168 | |||||
169 | 1 | 2µs | bless ($self, $class); | ||
170 | 1 | 10µs | $self; | ||
171 | } | ||||
172 | |||||
173 | ########################################################################### | ||||
174 | |||||
175 | # spent 5.25ms (791µs+4.46) within Mail::SpamAssassin::Conf::Parser::register_commands which was called 16 times, avg 328µs/call:
# once (104µs+2.17ms) by Mail::SpamAssassin::Conf::new at line 4516 of Mail/SpamAssassin/Conf.pm
# once (49µs+601µs) by Mail::SpamAssassin::Plugin::TxRep::set_config at line 1067 of Mail/SpamAssassin/Plugin/TxRep.pm
# once (54µs+267µs) by Mail::SpamAssassin::Plugin::URIDNSBL::set_config at line 813 of Mail/SpamAssassin/Plugin/URIDNSBL.pm
# once (44µs+174µs) by Mail::SpamAssassin::Plugin::SPF::set_config at line 228 of Mail/SpamAssassin/Plugin/SPF.pm
# once (45µs+163µs) by Mail::SpamAssassin::Plugin::Hashcash::set_config at line 158 of Mail/SpamAssassin/Plugin/Hashcash.pm
# once (47µs+157µs) by Mail::SpamAssassin::Plugin::DKIM::set_config at line 502 of Mail/SpamAssassin/Plugin/DKIM.pm
# once (49µs+152µs) by Mail::SpamAssassin::Plugin::FreeMail::set_config at line 213 of Mail/SpamAssassin/Plugin/FreeMail.pm
# once (37µs+154µs) by Mail::SpamAssassin::Plugin::ReplaceTags::set_config at line 292 of Mail/SpamAssassin/Plugin/ReplaceTags.pm
# once (53µs+110µs) by Mail::SpamAssassin::Plugin::SpamCop::set_config at line 157 of Mail/SpamAssassin/Plugin/SpamCop.pm
# once (45µs+105µs) by Mail::SpamAssassin::Plugin::Razor2::set_config at line 134 of Mail/SpamAssassin/Plugin/Razor2.pm
# once (52µs+95µs) by Mail::SpamAssassin::Plugin::AutoLearnThreshold::set_config at line 146 of Mail/SpamAssassin/Plugin/AutoLearnThreshold.pm
# once (48µs+66µs) by Mail::SpamAssassin::Plugin::AskDNS::set_config at line 359 of Mail/SpamAssassin/Plugin/AskDNS.pm
# once (36µs+73µs) by Mail::SpamAssassin::Plugin::WhiteListSubject::set_config at line 109 of Mail/SpamAssassin/Plugin/WhiteListSubject.pm
# once (45µs+61µs) by Mail::SpamAssassin::Plugin::VBounce::set_config at line 90 of Mail/SpamAssassin/Plugin/VBounce.pm
# once (46µs+59µs) by Mail::SpamAssassin::Plugin::URIDetail::set_config at line 150 of Mail/SpamAssassin/Plugin/URIDetail.pm
# once (37µs+50µs) by Mail::SpamAssassin::Plugin::MIMEHeader::set_config at line 163 of Mail/SpamAssassin/Plugin/MIMEHeader.pm | ||||
176 | 16 | 36µs | my($self, $arrref) = @_; | ||
177 | 16 | 66µs | my $conf = $self->{conf}; | ||
178 | |||||
179 | 16 | 134µs | 16 | 1.48ms | $self->set_defaults_from_command_list($arrref); # spent 1.48ms making 16 calls to Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list, avg 93µs/call |
180 | 16 | 133µs | 16 | 2.98ms | $self->build_command_luts($arrref); # spent 2.98ms making 16 calls to Mail::SpamAssassin::Conf::Parser::build_command_luts, avg 186µs/call |
181 | 48 | 365µs | push(@{$conf->{registered_commands}}, @{$arrref}); | ||
182 | } | ||||
183 | |||||
184 | # spent 1.48ms within Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list which was called 16 times, avg 93µs/call:
# 16 times (1.48ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 179, avg 93µs/call | ||||
185 | 16 | 33µs | my ($self, $arrref) = @_; | ||
186 | 16 | 44µs | my $conf = $self->{conf}; | ||
187 | 32 | 259µs | foreach my $cmd (@{$arrref}) { | ||
188 | # note! exists, not defined -- we want to be able to set | ||||
189 | # "undef" default values. | ||||
190 | 203 | 860µs | if (exists($cmd->{default})) { | ||
191 | 110 | 342µs | $conf->{$cmd->{setting}} = $cmd->{default}; | ||
192 | } | ||||
193 | } | ||||
194 | } | ||||
195 | |||||
196 | # spent 2.98ms within Mail::SpamAssassin::Conf::Parser::build_command_luts which was called 16 times, avg 186µs/call:
# 16 times (2.98ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 180, avg 186µs/call | ||||
197 | 16 | 32µs | my ($self, $arrref) = @_; | ||
198 | |||||
199 | 16 | 45µs | my $conf = $self->{conf}; | ||
200 | |||||
201 | 16 | 30µs | my $set; | ||
202 | 32 | 242µs | foreach my $cmd (@{$arrref}) { | ||
203 | # first off, decide what set this is in. | ||||
204 | 210 | 660µs | if ($cmd->{is_frequent}) { $set = 'frequent'; } | ||
205 | 196 | 339µs | else { $set = 'remaining'; } | ||
206 | |||||
207 | # next, its priority (used to ensure frequently-used params | ||||
208 | # are parsed first) | ||||
209 | 203 | 401µs | my $cmdname = $cmd->{command} || $cmd->{setting}; | ||
210 | 203 | 570µs | $self->{command_luts}->{$set}->{$cmdname} = $cmd; | ||
211 | |||||
212 | 205 | 686µs | if ($cmd->{aliases} && scalar @{$cmd->{aliases}} > 0) { | ||
213 | 4 | 15µs | foreach my $name (@{$cmd->{aliases}}) { | ||
214 | 2 | 10µs | $self->{command_luts}->{$set}->{$name} = $cmd; | ||
215 | } | ||||
216 | } | ||||
217 | } | ||||
218 | } | ||||
219 | |||||
220 | ########################################################################### | ||||
221 | |||||
222 | # spent 5.03s (1.83+3.20) within Mail::SpamAssassin::Conf::Parser::parse which was called:
# once (1.83s+3.20s) by Mail::SpamAssassin::Conf::parse_rules at line 4623 of Mail/SpamAssassin/Conf.pm | ||||
223 | 1 | 5µs | my ($self, undef, $scoresonly) = @_; # leave $rules in $_[1] | ||
224 | |||||
225 | 1 | 3µs | my $conf = $self->{conf}; | ||
226 | 1 | 3µ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 | ||||
231 | 1 | 3µs | my $lang = $ENV{'LANGUAGE'}; # LANGUAGE has the highest precedence but has a | ||
232 | 1 | 2µ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) | ||||
235 | 1 | 3µs | $lang ||= $ENV{'LC_ALL'}; | ||
236 | 1 | 2µs | $lang ||= $ENV{'LC_MESSAGES'}; | ||
237 | 1 | 2µs | $lang ||= $ENV{'LANG'}; | ||
238 | 1 | 3µs | $lang ||= 'C'; # Nothing set means C/POSIX | ||
239 | |||||
240 | 1 | 22µs | 1 | 8µs | if ($lang =~ /^(C|POSIX)$/) { # spent 8µs making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:match |
241 | 1 | 3µ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 | ||||
247 | 1 | 3µs | my $lut_frequent = $self->{command_luts}->{frequent}; | ||
248 | 1 | 3µs | my $lut_remaining = $self->{command_luts}->{remaining}; | ||
249 | 2 | 13µs | my %migrated_keys = map { $_ => 1 } | ||
250 | @Mail::SpamAssassin::Conf::MIGRATED_SETTINGS; | ||||
251 | |||||
252 | 1 | 4µs | $self->{currentfile} = '(no file)'; | ||
253 | 1 | 2µs | my $skip_parsing = 0; | ||
254 | 1 | 2µs | my @curfile_stack; | ||
255 | my @if_stack; | ||||
256 | 1 | 461µs | my @conf_lines = split (/\n/, $_[1]); | ||
257 | 1 | 2µs | my $line; | ||
258 | 1 | 5µs | $self->{if_stack} = \@if_stack; | ||
259 | 1 | 4µs | $self->{file_scoped_attrs} = { }; | ||
260 | |||||
261 | 1 | 4µs | my $keepmetadata = $conf->{main}->{keep_config_parsing_metadata}; | ||
262 | |||||
263 | 1 | 89.8ms | while (defined ($line = shift @conf_lines)) { | ||
264 | 16436 | 51.8ms | local ($1); # bug 3838: prevent random taint flagging of $1 | ||
265 | |||||
266 | # bug 5545: used to support testing rules in the ruleqa system | ||||
267 | 16436 | 25.3ms | if ($keepmetadata && $line =~ /^\#testrules/) { | ||
268 | $self->{file_scoped_attrs}->{testrules}++; | ||||
269 | next; | ||||
270 | } | ||||
271 | |||||
272 | # bug 6800: let X-Spam-Checker-Version also show what sa-update we are at | ||||
273 | 16436 | 227ms | 16436 | 46.1ms | if ($line =~ /^\# UPDATE version (\d+)$/) { # spent 46.1ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
274 | 1 | 5µs | for ($self->{currentfile}) { # just aliasing, not a loop | ||
275 | 1 | 10µs | $conf->{update_version}{$_} = $1 if defined $_ && $_ ne '(no file)'; | ||
276 | } | ||||
277 | } | ||||
278 | |||||
279 | 16436 | 227ms | 16436 | 65.2ms | $line =~ s/(?<!\\)#.*$//; # remove comments # spent 65.2ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call |
280 | 16436 | 192ms | 16436 | 33.2ms | $line =~ s/\\#/#/g; # hash chars are escaped, so unescape them # spent 33.2ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
281 | 16436 | 208ms | 16436 | 41.3ms | $line =~ s/^\s+//; # remove leading whitespace # spent 41.3ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
282 | 16436 | 272ms | 16436 | 55.1ms | $line =~ s/\s+$//; # remove tailing whitespace # spent 55.1ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
283 | 16436 | 37.7ms | next unless($line); # skip empty lines | ||
284 | |||||
285 | # handle i18n | ||||
286 | 10524 | 161ms | 11998 | 33.8ms | if ($line =~ s/^lang\s+(\S+)\s+//) { next if ($lang !~ /^$1/i); } # spent 23.4ms making 9050 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call
# spent 6.59ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 4µs/call
# spent 3.81ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
287 | |||||
288 | 7576 | 62.6ms | my($key, $value) = split(/\s+/, $line, 2); | ||
289 | 7576 | 18.9ms | $key = lc $key; | ||
290 | # convert all dashes in setting name to underscores. | ||||
291 | 7576 | 141ms | 7576 | 19.1ms | $key =~ s/-/_/g; # spent 19.1ms making 7576 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
292 | 7576 | 13.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 | |||||
298 | 7576 | 12.0ms | my $parse_error; # undef by default, may be overridden | ||
299 | |||||
300 | # File/line number assertions | ||||
301 | 7576 | 15.3ms | if ($key eq 'file') { | ||
302 | 136 | 1.70ms | 136 | 711µs | if ($value =~ /^start\s+(.+)$/) { # spent 711µs making 136 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call |
303 | 68 | 291µs | push (@curfile_stack, $self->{currentfile}); | ||
304 | 68 | 276µs | $self->{currentfile} = $1; | ||
305 | 68 | 322µs | next; | ||
306 | } | ||||
307 | |||||
308 | 68 | 884µs | 68 | 340µs | if ($value =~ /^end\s/) { # spent 340µs making 68 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call |
309 | 68 | 300µs | $self->{file_scoped_attrs} = { }; | ||
310 | |||||
311 | 68 | 178µ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 | } | ||||
328 | 68 | 147µs | $skip_parsing = 0; | ||
329 | |||||
330 | 68 | 294µs | my $curfile = pop @curfile_stack; | ||
331 | 68 | 248µs | if (defined $curfile) { | ||
332 | 68 | 230µs | $self->{currentfile} = $curfile; | ||
333 | } else { | ||||
334 | $self->{currentfile} = '(no file)'; | ||||
335 | } | ||||
336 | 68 | 295µs | next; | ||
337 | } | ||||
338 | } | ||||
339 | |||||
340 | # now handle the commands. | ||||
341 | 7440 | 13.3ms | if ($key eq 'include') { | ||
342 | 58 | 659µs | 58 | 41.2ms | $value = $self->fix_path_relative_to_current_file($value); # spent 41.2ms making 58 calls to Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file, avg 711µs/call |
343 | 58 | 742µs | 58 | 30.2ms | my $text = $conf->{main}->read_cf($value, 'included file'); # spent 30.2ms making 58 calls to Mail::SpamAssassin::read_cf, avg 520µs/call |
344 | 58 | 31.1ms | unshift (@conf_lines, split (/\n/, $text)); | ||
345 | 58 | 858µs | next; | ||
346 | } | ||||
347 | |||||
348 | 7382 | 12.9ms | if ($key eq 'ifplugin') { | ||
349 | 360 | 5.99ms | 360 | 160ms | $self->handle_conditional ($key, "plugin ($value)", # spent 160ms making 360 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 446µs/call |
350 | \@if_stack, \$skip_parsing); | ||||
351 | 360 | 1.63ms | next; | ||
352 | } | ||||
353 | |||||
354 | 7022 | 12.3ms | if ($key eq 'if') { | ||
355 | 148 | 1.78ms | 148 | 79.4ms | $self->handle_conditional ($key, $value, # spent 79.4ms making 148 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 537µs/call |
356 | \@if_stack, \$skip_parsing); | ||||
357 | 148 | 762µs | next; | ||
358 | } | ||||
359 | |||||
360 | 6874 | 11.6ms | if ($key eq 'else') { | ||
361 | # TODO: if/else/else won't get flagged here :( | ||||
362 | 2 | 5µs | if (!@if_stack) { | ||
363 | $parse_error = "config: found else without matching conditional"; | ||||
364 | goto failed_line; | ||||
365 | } | ||||
366 | |||||
367 | 2 | 6µs | $skip_parsing = !$skip_parsing; | ||
368 | 2 | 7µs | next; | ||
369 | } | ||||
370 | |||||
371 | # and the endif statement: | ||||
372 | 6872 | 12.3ms | if ($key eq 'endif') { | ||
373 | 508 | 1.45ms | my $lastcond = pop @if_stack; | ||
374 | 508 | 943µs | if (!defined $lastcond) { | ||
375 | $parse_error = "config: found endif without matching conditional"; | ||||
376 | goto failed_line; | ||||
377 | } | ||||
378 | |||||
379 | 508 | 1.42ms | $skip_parsing = $lastcond->{skip_parsing}; | ||
380 | 508 | 3.43ms | next; | ||
381 | } | ||||
382 | |||||
383 | # preprocessing? skip all other commands | ||||
384 | 6364 | 10.5ms | next if $skip_parsing; | ||
385 | |||||
386 | 6184 | 10.4ms | if ($key eq 'require_version') { | ||
387 | # if it wasn't replaced during install, assume current version ... | ||||
388 | 17 | 36µs | next if ($value eq "\@\@VERSION\@\@"); | ||
389 | |||||
390 | 17 | 50µ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 | |||||
400 | 17 | 41µ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 | } | ||||
410 | 17 | 68µs | next; | ||
411 | } | ||||
412 | |||||
413 | 6167 | 18.3ms | my $cmd = $lut_frequent->{$key}; # check the frequent command set | ||
414 | 6167 | 13.8ms | if (!$cmd) { | ||
415 | 2208 | 5.47ms | $cmd = $lut_remaining->{$key}; # no? try the rest | ||
416 | } | ||||
417 | |||||
418 | # we've either fallen through with no match, in which case this | ||||
419 | # if() will fail, or we have a match. | ||||
420 | 6167 | 11.2ms | if ($cmd) { | ||
421 | 5666 | 10.8ms | if ($self->{scoresonly}) { # reading user config from spamd | ||
422 | if ($cmd->{is_priv} && !$conf->{allow_user_rules}) { | ||||
423 | info("config: not parsing, 'allow_user_rules' is 0: $line"); | ||||
424 | goto failed_line; | ||||
425 | } | ||||
426 | if ($cmd->{is_admin}) { | ||||
427 | info("config: not parsing, administrator setting: $line"); | ||||
428 | goto failed_line; | ||||
429 | } | ||||
430 | } | ||||
431 | |||||
432 | 5666 | 12.7ms | if (!$cmd->{code}) { | ||
433 | 21 | 158µs | 21 | 427µs | if (! $self->setup_default_code_cb($cmd)) { # spent 427µs making 21 calls to Mail::SpamAssassin::Conf::Parser::setup_default_code_cb, avg 20µs/call |
434 | goto failed_line; | ||||
435 | } | ||||
436 | } | ||||
437 | |||||
438 | 11332 | 67.1ms | 5666 | 2.14s | my $ret = &{$cmd->{code}} ($conf, $cmd->{setting}, $value, $line); # spent 510ms making 27 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:4145], avg 18.9ms/call
# spent 324ms making 781 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2981], avg 415µs/call
# spent 322ms making 465 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3174], avg 693µs/call
# spent 273ms making 1276 calls to Mail::SpamAssassin::Conf::Parser::set_hash_key_value, avg 214µs/call
# spent 233ms making 655 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3020], avg 356µs/call
# spent 189ms making 811 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:280], avg 233µs/call
# spent 87.4ms making 30 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1685], avg 2.91ms/call
# spent 41.1ms making 46 calls to Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[Mail/SpamAssassin/Plugin/MIMEHeader.pm:160], avg 893µs/call
# spent 30.0ms making 83 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:420], avg 362µs/call
# spent 28.2ms making 459 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3750], avg 61µs/call
# spent 24.1ms making 71 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3052], avg 340µs/call
# spent 15.9ms making 128 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3557], avg 124µs/call
# spent 13.9ms making 40 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3088], avg 347µs/call
# spent 6.48ms making 85 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:468], avg 76µs/call
# spent 5.85ms making 270 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2044], avg 22µs/call
# spent 5.28ms making 15 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2701], avg 352µs/call
# spent 5.24ms making 34 calls to Mail::SpamAssassin::Conf::Parser::set_addrlist_value, avg 154µs/call
# spent 3.87ms making 63 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:783], avg 61µs/call
# spent 3.76ms making 21 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:662], avg 179µs/call
# spent 3.75ms making 19 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:433], avg 198µs/call
# spent 3.15ms making 64 calls to Mail::SpamAssassin::Plugin::ReplaceTags::__ANON__[Mail/SpamAssassin/Plugin/ReplaceTags.pm:266], avg 49µs/call
# spent 2.70ms making 77 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3206], avg 35µs/call
# spent 2.33ms making 13 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3122], avg 179µs/call
# spent 1.91ms making 48 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3781], avg 40µs/call
# spent 1.20ms making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3804]
# spent 865µs making 5 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:935], avg 173µs/call
# spent 630µs making 2 calls to Mail::SpamAssassin::Plugin::AskDNS::__ANON__[Mail/SpamAssassin/Plugin/AskDNS.pm:356], avg 315µs/call
# spent 368µs making 17 calls to Mail::SpamAssassin::Conf::Parser::set_template_append, avg 22µs/call
# spent 310µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:609]
# spent 302µs making 4 calls to Mail::SpamAssassin::Conf::Parser::set_numeric_value, avg 76µs/call
# spent 215µs making 36 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3402], avg 6µs/call
# spent 184µs making 5 calls to Mail::SpamAssassin::Conf::Parser::set_bool_value, avg 37µs/call
# spent 132µs making 2 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1419], avg 66µs/call
# spent 132µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3835]
# spent 92µs making 3 calls to Mail::SpamAssassin::Conf::Parser::set_string_value, avg 31µs/call
# spent 90µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:581]
# spent 88µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3858]
# spent 51µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1007]
# spent 41µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1054]
# spent 35µs making 2 calls to Mail::SpamAssassin::Conf::Parser::set_template_clear, avg 18µs/call
# spent 22µs making 1 call to Mail::SpamAssassin::Plugin::TxRep::__ANON__[Mail/SpamAssassin/Plugin/TxRep.pm:495]
# spent 17µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1437] |
439 | |||||
440 | 5666 | 12.5ms | if ($ret && $ret eq $Mail::SpamAssassin::Conf::INVALID_VALUE) | ||
441 | { | ||||
442 | $parse_error = "config: SpamAssassin failed to parse line, ". | ||||
443 | "\"$value\" is not valid for \"$key\", ". | ||||
444 | "skipping: $line"; | ||||
445 | goto failed_line; | ||||
446 | } | ||||
447 | elsif ($ret && $ret eq $Mail::SpamAssassin::Conf::INVALID_HEADER_FIELD_NAME) | ||||
448 | { | ||||
449 | $parse_error = "config: SpamAssassin failed to parse line, ". | ||||
450 | "it does not specify a valid header field name, ". | ||||
451 | "skipping: $line"; | ||||
452 | goto failed_line; | ||||
453 | } | ||||
454 | elsif ($ret && $ret eq $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE) | ||||
455 | { | ||||
456 | $parse_error = "config: SpamAssassin failed to parse line, ". | ||||
457 | "no value provided for \"$key\", ". | ||||
458 | "skipping: $line"; | ||||
459 | goto failed_line; | ||||
460 | } | ||||
461 | else { | ||||
462 | 5666 | 27.0ms | next; | ||
463 | } | ||||
464 | } | ||||
465 | |||||
466 | # last ditch: try to see if the plugins know what to do with it | ||||
467 | 501 | 6.95ms | 501 | 153ms | if ($conf->{main}->call_plugins("parse_config", { # spent 153ms making 501 calls to Mail::SpamAssassin::call_plugins, avg 305µs/call |
468 | key => $key, | ||||
469 | value => $value, | ||||
470 | line => $line, | ||||
471 | conf => $conf, | ||||
472 | user_config => $self->{scoresonly} | ||||
473 | })) | ||||
474 | { | ||||
475 | # a plugin dealt with it successfully. | ||||
476 | 501 | 3.68ms | next; | ||
477 | } | ||||
478 | |||||
479 | failed_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 | |||||
497 | 1 | 5µs | delete $self->{if_stack}; | ||
498 | |||||
499 | 1 | 9µs | 1 | 13µs | $self->lint_check(); # spent 13µs making 1 call to Mail::SpamAssassin::Conf::Parser::lint_check |
500 | 1 | 9µs | 1 | 125ms | $self->set_default_scores(); # spent 125ms making 1 call to Mail::SpamAssassin::Conf::Parser::set_default_scores |
501 | 1 | 16µs | 1 | 171ms | $self->check_for_missing_descriptions(); # spent 171ms making 1 call to Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions |
502 | |||||
503 | 1 | 23µs | delete $self->{scoresonly}; | ||
504 | } | ||||
505 | |||||
506 | # spent 240ms (142+97.7) within Mail::SpamAssassin::Conf::Parser::handle_conditional which was called 508 times, avg 472µs/call:
# 360 times (100ms+60.1ms) by Mail::SpamAssassin::Conf::Parser::parse at line 349, avg 446µs/call
# 148 times (41.9ms+37.6ms) by Mail::SpamAssassin::Conf::Parser::parse at line 355, avg 537µs/call | ||||
507 | 508 | 2.82ms | my ($self, $key, $value, $if_stack_ref, $skip_parsing_ref) = @_; | ||
508 | 508 | 1.44ms | my $conf = $self->{conf}; | ||
509 | |||||
510 | 508 | 976µs | my $lexer = ARITH_EXPRESSION_LEXER; | ||
511 | 508 | 23.2ms | 1016 | 10.9ms | my @tokens = ($value =~ m/($lexer)/g); # spent 7.60ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 15µs/call
# spent 3.31ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 7µs/call |
512 | |||||
513 | 508 | 1.21ms | my $eval = ''; | ||
514 | 508 | 956µs | my $bad = 0; | ||
515 | 508 | 2.12ms | foreach my $token (@tokens) { | ||
516 | 2161 | 46.3ms | 2650 | 11.9ms | if ($token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/) { # spent 11.9ms making 2650 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 4µs/call |
517 | # using tainted subr. argument may taint the whole expression, avoid | ||||
518 | 1164 | 7.99ms | 1164 | 43.7ms | my $u = untaint_var($token); # spent 43.7ms making 1164 calls to Mail::SpamAssassin::Util::untaint_var, avg 38µs/call |
519 | 1164 | 2.65ms | $eval .= $u . " "; | ||
520 | } | ||||
521 | elsif ($token eq 'plugin') { | ||||
522 | # replace with a method call | ||||
523 | 434 | 835µs | $eval .= '$self->cond_clause_plugin_loaded'; | ||
524 | } | ||||
525 | elsif ($token eq 'can') { | ||||
526 | # replace with a method call | ||||
527 | 55 | 118µ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') { | ||||
534 | 19 | 52µs | $eval .= $Mail::SpamAssassin::VERSION." "; | ||
535 | } | ||||
536 | elsif ($token eq 'perl_version') { | ||||
537 | $eval .= $]." "; | ||||
538 | } | ||||
539 | elsif ($token =~ /^\w[\w\:]+$/) { # class name | ||||
540 | 489 | 3.34ms | 489 | 21.8ms | my $u = untaint_var($token); # spent 21.8ms making 489 calls to Mail::SpamAssassin::Util::untaint_var, avg 45µs/call |
541 | 489 | 1.35ms | $eval .= '"' . $u . '" '; | ||
542 | } | ||||
543 | else { | ||||
544 | $bad++; | ||||
545 | warn "config: unparseable chars in 'if $value': '$token'\n"; | ||||
546 | } | ||||
547 | } | ||||
548 | |||||
549 | 508 | 904µs | if ($bad) { | ||
550 | $self->lint_warn("bad 'if' line, in \"$self->{currentfile}\"", undef); | ||||
551 | return -1; | ||||
552 | } | ||||
553 | |||||
554 | 1016 | 6.27ms | push (@{$if_stack_ref}, { | ||
555 | type => 'if', | ||||
556 | conditional => $value, | ||||
557 | skip_parsing => $$skip_parsing_ref | ||||
558 | }); | ||||
559 | |||||
560 | 508 | 37.0ms | if (eval $eval) { # spent 879µs executing statements in 72 string evals (merged)
# spent 705µs executing statements in 59 string evals (merged)
# spent 490µs executing statements in 41 string evals (merged)
# spent 322µs executing statements in 26 string evals (merged)
# spent 289µs executing statements in 25 string evals (merged)
# spent 275µs executing statements in 21 string evals (merged)
# spent 268µs executing statements in 20 string evals (merged)
# spent 208µs executing statements in 15 string evals (merged)
# spent 170µs executing statements in 14 string evals (merged)
# spent 155µs executing statements in 13 string evals (merged)
# spent 140µs executing statements in 12 string evals (merged)
# spent 138µs executing statements in 11 string evals (merged)
# spent 133µs executing statements in 11 string evals (merged)
# spent 101µs executing statements in 7 string evals (merged)
# spent 95µs executing statements in 8 string evals (merged)
# spent 92µs executing statements in 7 string evals (merged)
# spent 90µs executing statements in 7 string evals (merged)
# spent 90µs executing statements in 7 string evals (merged)
# spent 83µs executing statements in 6 string evals (merged)
# spent 81µs executing statements in 7 string evals (merged)
# spent 76µs executing statements in 7 string evals (merged)
# spent 76µs executing statements in 6 string evals (merged)
# spent 70µs executing statements in 6 string evals (merged)
# spent 70µs executing statements in 5 string evals (merged)
# spent 68µs executing statements in 12 string evals (merged)
# spent 67µs executing statements in 5 string evals (merged)
# spent 64µs executing statements in 5 string evals (merged)
# spent 62µs executing statements in 5 string evals (merged)
# spent 60µs executing statements in 5 string evals (merged)
# spent 50µs executing statements in 4 string evals (merged)
# spent 49µs executing statements in 4 string evals (merged)
# spent 46µs executing statements in 4 string evals (merged)
# spent 37µs executing statements in 3 string evals (merged)
# spent 37µs executing statements in 3 string evals (merged)
# spent 36µs executing statements in 3 string evals (merged)
# spent 35µs executing statements in 2 string evals (merged)
# spent 34µs executing statements in 3 string evals (merged)
# spent 33µs executing statements in 2 string evals (merged)
# spent 30µs executing statements in 2 string evals (merged)
# spent 30µs executing statements in 2 string evals (merged)
# spent 28µs executing statements in 2 string evals (merged)
# spent 27µs executing statements in 2 string evals (merged)
# spent 27µs executing statements in 2 string evals (merged)
# spent 25µs executing statements in 2 string evals (merged)
# spent 25µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 20µs executing statements in string eval
# spent 17µs executing statements in string eval
# spent 16µs executing statements in 3 string evals (merged)
# spent 16µs executing statements in string eval
# spent 15µs executing statements in string eval
# spent 14µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in 2 string evals (merged)
# spent 11µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 6µs executing statements in string eval | ||
561 | # leave $skip_parsing as-is; we may not be parsing anyway in this block. | ||||
562 | # in other words, support nested 'if's and 'require_version's | ||||
563 | } else { | ||||
564 | 127 | 322µs | warn "config: error in $key - $eval: $@" if $@ ne ''; | ||
565 | 127 | 305µs | $$skip_parsing_ref = 1; | ||
566 | } | ||||
567 | } | ||||
568 | |||||
569 | # functions supported in the "if" eval: | ||||
570 | # spent 3.80ms within Mail::SpamAssassin::Conf::Parser::cond_clause_plugin_loaded which was called 434 times, avg 9µs/call:
# 72 times (626µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 119)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 59 times (442µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 287)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call
# 41 times (317µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 132)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 26 times (194µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 823)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call
# 25 times (210µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 154)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 20 times (180µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 742)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 15 times (135µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 289)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 14 times (140µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 128)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 13 times (110µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 126)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 12 times (110µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 279)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 11 times (117µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 170)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call
# 11 times (102µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 201)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 8 times (74µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 115)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 7 times (73µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 274)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 7 times (65µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 275)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 7 times (55µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 278)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 7 times (54µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 276)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 7 times (52µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 754)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call
# 6 times (68µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 523)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call
# 6 times (59µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 285)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 5 times (51µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 296)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 5 times (50µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 473)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 5 times (47µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 207)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 5 times (45µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 335)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 4 times (41µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 347)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 4 times (40µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 284)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 4 times (35µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 945)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 3 times (28µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 131)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 3 times (20µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 304)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call
# 2 times (31µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 286)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 16µs/call
# 2 times (27µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 348)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 14µs/call
# 2 times (27µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 925)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 14µs/call
# 2 times (23µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 129)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call
# 2 times (23µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 363)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call
# 2 times (22µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 261)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call
# 2 times (21µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1007)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call
# 2 times (19µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 133)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# once (15µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 942)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (15µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1062)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (11µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 231)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (9µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 277)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (8µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 372)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (7µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 116)[Mail/SpamAssassin/Conf/Parser.pm:560] | ||||
571 | 434 | 8.21ms | return $_[0]->{conf}->{plugins_loaded}->{$_[1]}; | ||
572 | } | ||||
573 | |||||
574 | # spent 5.55ms (960µs+4.59) within Mail::SpamAssassin::Conf::Parser::cond_clause_can which was called 55 times, avg 101µs/call:
# 21 times (362µs+1.85ms) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 634)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 106µs/call
# 7 times (106µs+531µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 932)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 91µs/call
# 6 times (126µs+466µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 718)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 99µs/call
# 5 times (80µs+388µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 290)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 93µs/call
# 3 times (63µs+282µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 940)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 115µs/call
# 3 times (50µs+240µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 947)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 96µs/call
# 2 times (37µs+183µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 531)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 110µs/call
# 2 times (33µs+163µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 120)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 98µs/call
# once (21µs+88µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 299)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (20µs+89µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 114)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (18µs+83µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 529)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (16µs+80µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 117)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (16µs+76µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1075)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (12µs+64µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 118)[Mail/SpamAssassin/Conf/Parser.pm:560] | ||||
575 | 55 | 138µs | my ($self, $method) = @_; | ||
576 | 55 | 1.01ms | 55 | 4.59ms | $self->cond_clause_can_or_has('can', $method); # spent 4.59ms making 55 calls to Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has, avg 83µs/call |
577 | } | ||||
578 | |||||
579 | sub cond_clause_has { | ||||
580 | my ($self, $method) = @_; | ||||
581 | $self->cond_clause_can_or_has('has', $method); | ||||
582 | } | ||||
583 | |||||
584 | # spent 4.59ms (2.90+1.68) within Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has which was called 55 times, avg 83µs/call:
# 55 times (2.90ms+1.68ms) by Mail::SpamAssassin::Conf::Parser::cond_clause_can at line 576, avg 83µs/call | ||||
585 | 55 | 130µs | my ($self, $fn_name, $method) = @_; | ||
586 | |||||
587 | 55 | 394µs | local($1,$2); | ||
588 | 55 | 1.02ms | 55 | 440µs | if (!defined $method) { # spent 440µs making 55 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 8µs/call |
589 | $self->lint_warn("bad 'if' line, no argument to $fn_name(), ". | ||||
590 | "in \"$self->{currentfile}\"", undef); | ||||
591 | } elsif ($method =~ /^(.*)::([^:]+)$/) { | ||||
592 | 2 | 10.1ms | 2 | 143µs | # spent 87µs (30+56) within Mail::SpamAssassin::Conf::Parser::BEGIN@592 which was called:
# once (30µs+56µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 592 # spent 87µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@592
# spent 56µs making 1 call to strict::unimport |
593 | 55 | 229µs | my($module, $meth) = ($1, $2); | ||
594 | return 1 if UNIVERSAL::can($module,$meth) && | ||||
595 | 110 | 2.51ms | 110 | 1.24ms | ( $fn_name eq 'has' || &{$method}() ); # spent 618µs making 55 calls to UNIVERSAL::can, avg 11µs/call
# spent 301µs making 24 calls to Mail::SpamAssassin::Conf::feature_bug6558_free, avg 13µs/call
# spent 101µs making 10 calls to Mail::SpamAssassin::Plugin::BodyEval::has_check_body_length, avg 10µs/call
# spent 70µs making 7 calls to Mail::SpamAssassin::Conf::perl_min_version_5010000, avg 10µs/call
# spent 59µs making 5 calls to Mail::SpamAssassin::Plugin::SPF::has_check_for_spf_errors, avg 12µs/call
# spent 21µs making 2 calls to Mail::SpamAssassin::Plugin::MIMEEval::has_check_abundant_unicode_ratio, avg 11µs/call
# spent 19µs making 2 calls to Mail::SpamAssassin::Conf::feature_registryboundaries, avg 10µs/call
# spent 15µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::has_tflags_domains_only
# spent 10µs making 1 call to Mail::SpamAssassin::Plugin::MIMEEval::has_check_for_ascii_text_illegal
# spent 10µs making 1 call to Mail::SpamAssassin::Conf::feature_originating_ip_headers
# spent 9µs making 1 call to Mail::SpamAssassin::Conf::feature_yesno_takes_args
# spent 8µs making 1 call to Mail::SpamAssassin::Conf::feature_dns_local_ports_permit_avoid |
596 | } else { | ||||
597 | $self->lint_warn("bad 'if' line, cannot find '::' in $fn_name($method), ". | ||||
598 | "in \"$self->{currentfile}\"", undef); | ||||
599 | } | ||||
600 | return; | ||||
601 | } | ||||
602 | |||||
603 | # Let's do some linting here ... | ||||
604 | # This is called from _parse(), BTW, so we can check for $conf->{tests} | ||||
605 | # easily before finish_parsing() is called and deletes it. | ||||
606 | # | ||||
607 | # spent 13µs within Mail::SpamAssassin::Conf::Parser::lint_check which was called:
# once (13µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 499 | ||||
608 | 1 | 2µs | my ($self) = @_; | ||
609 | 1 | 3µs | my $conf = $self->{conf}; | ||
610 | |||||
611 | 1 | 12µs | if ($conf->{lint_rules}) { | ||
612 | # Check for description and score issues in lint fashion | ||||
613 | while ( my $k = each %{$conf->{descriptions}} ) { | ||||
614 | if (!exists $conf->{tests}->{$k}) { | ||||
615 | $self->lint_warn("config: warning: description exists for non-existent rule $k\n", $k); | ||||
616 | } | ||||
617 | } | ||||
618 | |||||
619 | while ( my($sk) = each %{$conf->{scores}} ) { | ||||
620 | if (!exists $conf->{tests}->{$sk}) { | ||||
621 | # bug 5514: not a lint warning any more | ||||
622 | dbg("config: warning: score set for non-existent rule $sk"); | ||||
623 | } | ||||
624 | } | ||||
625 | } | ||||
626 | } | ||||
627 | |||||
628 | # we should set a default score for all valid rules... Do this here | ||||
629 | # instead of add_test because mostly 'score' occurs after the rule is | ||||
630 | # specified, so why set the scores to default, then set them again at | ||||
631 | # 'score'? | ||||
632 | # | ||||
633 | # spent 125ms (120+4.91) within Mail::SpamAssassin::Conf::Parser::set_default_scores which was called:
# once (120ms+4.91ms) by Mail::SpamAssassin::Conf::Parser::parse at line 500 | ||||
634 | 1 | 2µs | my ($self) = @_; | ||
635 | 1 | 2µs | my $conf = $self->{conf}; | ||
636 | |||||
637 | 2069 | 32.0ms | while ( my $k = each %{$conf->{tests}} ) { | ||
638 | 2067 | 5.95ms | if ( ! exists $conf->{scores}->{$k} ) { | ||
639 | # T_ rules (in a testing probationary period) get low, low scores | ||||
640 | 1284 | 15.7ms | 1284 | 2.76ms | my $set_score = ($k =~/^T_/) ? 0.01 : 1.0; # spent 2.76ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
641 | |||||
642 | 1284 | 26.0ms | 1284 | 2.15ms | $set_score = -$set_score if ( ($conf->{tflags}->{$k}||'') =~ /\bnice\b/ ); # spent 2.15ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
643 | 1284 | 8.57ms | for my $index (0..3) { | ||
644 | 5136 | 36.3ms | $conf->{scoreset}->[$index]->{$k} = $set_score; | ||
645 | } | ||||
646 | } | ||||
647 | } | ||||
648 | } | ||||
649 | |||||
650 | # loop through all the tests and if we are missing a description with debug | ||||
651 | # set, throw a warning except for testing T_ or meta __ rules. | ||||
652 | # spent 171ms (75.2+96.3) within Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions which was called:
# once (75.2ms+96.3ms) by Mail::SpamAssassin::Conf::Parser::parse at line 501 | ||||
653 | 1 | 4µs | my ($self) = @_; | ||
654 | 1 | 4µs | my $conf = $self->{conf}; | ||
655 | |||||
656 | 2069 | 30.4ms | while ( my $k = each %{$conf->{tests}} ) { | ||
657 | 2067 | 37.3ms | 2067 | 5.73ms | if ($k !~ m/^(?:T_|__)/i) { # spent 5.73ms making 2067 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
658 | 815 | 7.06ms | 815 | 90.0ms | if ( ! exists $conf->{descriptions}->{$k} ) { # spent 90.0ms making 815 calls to Mail::SpamAssassin::Util::TieOneStringHash::EXISTS, avg 110µs/call |
659 | 69 | 649µs | 69 | 551µs | dbg("config: warning: no description set for $k"); # spent 551µs making 69 calls to Mail::SpamAssassin::Logger::dbg, avg 8µs/call |
660 | } | ||||
661 | } | ||||
662 | } | ||||
663 | } | ||||
664 | |||||
665 | ########################################################################### | ||||
666 | |||||
667 | # spent 427µs within Mail::SpamAssassin::Conf::Parser::setup_default_code_cb which was called 21 times, avg 20µs/call:
# 21 times (427µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 433, avg 20µs/call | ||||
668 | 21 | 42µs | my ($self, $cmd) = @_; | ||
669 | 21 | 89µs | my $type = $cmd->{type}; | ||
670 | |||||
671 | 21 | 109µs | if ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_STRING) { | ||
672 | 3 | 10µs | $cmd->{code} = \&set_string_value; | ||
673 | } | ||||
674 | elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL) { | ||||
675 | 4 | 12µs | $cmd->{code} = \&set_bool_value; | ||
676 | } | ||||
677 | elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC) { | ||||
678 | 4 | 12µs | $cmd->{code} = \&set_numeric_value; | ||
679 | } | ||||
680 | elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_HASH_KEY_VALUE) { | ||||
681 | 6 | 20µs | $cmd->{code} = \&set_hash_key_value; | ||
682 | } | ||||
683 | elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_ADDRLIST) { | ||||
684 | 2 | 8µs | $cmd->{code} = \&set_addrlist_value; | ||
685 | } | ||||
686 | elsif ($type == $Mail::SpamAssassin::Conf::CONF_TYPE_TEMPLATE) { | ||||
687 | 2 | 6µ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 | } | ||||
705 | 21 | 148µs | return 1; | ||
706 | } | ||||
707 | |||||
708 | sub set_no_value { | ||||
709 | my ($conf, $key, $value, $line) = @_; | ||||
710 | |||||
711 | unless (!defined $value || $value eq '') { | ||||
712 | return $Mail::SpamAssassin::Conf::INVALID_VALUE; | ||||
713 | } | ||||
714 | } | ||||
715 | |||||
716 | # spent 302µs (158+144) within Mail::SpamAssassin::Conf::Parser::set_numeric_value which was called 4 times, avg 76µs/call:
# 4 times (158µs+144µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 76µs/call | ||||
717 | 4 | 23µs | my ($conf, $key, $value, $line) = @_; | ||
718 | |||||
719 | 4 | 40µs | 4 | 12µs | unless (defined $value && $value !~ /^$/) { # spent 12µs making 4 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
720 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
721 | } | ||||
722 | 4 | 50µs | 4 | 22µs | unless ($value =~ /^ [+-]? \d+ (?: \. \d* )? \z/sx) { # spent 22µs making 4 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 6µs/call |
723 | return $Mail::SpamAssassin::Conf::INVALID_VALUE; | ||||
724 | } | ||||
725 | # it is safe to untaint now that we know the syntax is a valid number | ||||
726 | 4 | 76µs | 4 | 110µs | $conf->{$key} = untaint_var($value) + 0; # spent 110µs making 4 calls to Mail::SpamAssassin::Util::untaint_var, avg 27µs/call |
727 | } | ||||
728 | |||||
729 | sub set_duration_value { | ||||
730 | my ($conf, $key, $value, $line) = @_; | ||||
731 | |||||
732 | local ($1,$2); | ||||
733 | unless (defined $value && $value !~ /^$/) { | ||||
734 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
735 | } | ||||
736 | unless ($value =~ /^( \+? \d+ (?: \. \d* )? ) (?: \s* ([smhdw]))? \z/sxi) { | ||||
737 | return $Mail::SpamAssassin::Conf::INVALID_VALUE; | ||||
738 | } | ||||
739 | $value = $1; | ||||
740 | $value *= { s => 1, m => 60, h => 3600, | ||||
741 | d => 24*3600, w => 7*24*3600 }->{lc $2} if defined $2; | ||||
742 | # it is safe to untaint now that we know the syntax is a valid time interval | ||||
743 | $conf->{$key} = untaint_var($value) + 0; | ||||
744 | } | ||||
745 | |||||
746 | # spent 184µs (164+20) within Mail::SpamAssassin::Conf::Parser::set_bool_value which was called 5 times, avg 37µs/call:
# 5 times (164µs+20µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 37µs/call | ||||
747 | 5 | 30µs | my ($conf, $key, $value, $line) = @_; | ||
748 | |||||
749 | 5 | 54µs | 5 | 20µs | unless (defined $value && $value !~ /^$/) { # spent 20µs making 5 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 4µs/call |
750 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
751 | } | ||||
752 | |||||
753 | # bug 4462: allow yes/1 and no/0 for boolean values | ||||
754 | 5 | 14µs | $value = lc $value; | ||
755 | 5 | 29µs | if ($value eq 'yes' || $value eq '1') { | ||
756 | 4 | 8µs | $value = 1; | ||
757 | } | ||||
758 | elsif ($value eq 'no' || $value eq '0') { | ||||
759 | 1 | 2µs | $value = 0; | ||
760 | } | ||||
761 | else { | ||||
762 | return $Mail::SpamAssassin::Conf::INVALID_VALUE; | ||||
763 | } | ||||
764 | |||||
765 | 5 | 50µs | $conf->{$key} = $value; | ||
766 | } | ||||
767 | |||||
768 | # spent 92µs (83+10) within Mail::SpamAssassin::Conf::Parser::set_string_value which was called 3 times, avg 31µs/call:
# 3 times (83µs+10µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 31µs/call | ||||
769 | 3 | 17µs | my ($conf, $key, $value, $line) = @_; | ||
770 | |||||
771 | 3 | 33µs | 3 | 10µs | unless (defined $value && $value !~ /^$/) { # spent 10µs making 3 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
772 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
773 | } | ||||
774 | |||||
775 | 3 | 38µs | $conf->{$key} = $value; # keep tainted | ||
776 | } | ||||
777 | |||||
778 | sub 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 | |||||
788 | sub set_ipaddr_list { | ||||
789 | my ($conf, $key, $value, $line) = @_; | ||||
790 | |||||
791 | unless (defined $value && $value !~ /^$/) { | ||||
792 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
793 | } | ||||
794 | |||||
795 | foreach my $net (split(' ', $value)) { | ||||
796 | $conf->{$key}->add_cidr($net); | ||||
797 | } | ||||
798 | $conf->{$key.'_configured'} = 1; | ||||
799 | } | ||||
800 | |||||
801 | # spent 273ms (57.0+216) within Mail::SpamAssassin::Conf::Parser::set_hash_key_value which was called 1276 times, avg 214µs/call:
# 1276 times (57.0ms+216ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 214µs/call | ||||
802 | 1276 | 7.73ms | my ($conf, $key, $value, $line) = @_; | ||
803 | 1276 | 9.44ms | my($k,$v) = split(/\s+/, $value, 2); | ||
804 | |||||
805 | 1276 | 2.65ms | unless (defined $v && $v ne '') { | ||
806 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
807 | } | ||||
808 | |||||
809 | 1276 | 34.5ms | 1684 | 216ms | $conf->{$key}->{$k} = $v; # keep tainted # spent 121ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::STORE, avg 144µs/call
# spent 94.7ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::FETCH, avg 112µs/call |
810 | } | ||||
811 | |||||
812 | # spent 5.24ms (987µs+4.26) within Mail::SpamAssassin::Conf::Parser::set_addrlist_value which was called 34 times, avg 154µs/call:
# 34 times (987µs+4.26ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 154µs/call | ||||
813 | 34 | 158µs | my ($conf, $key, $value, $line) = @_; | ||
814 | |||||
815 | 34 | 438µs | 34 | 167µs | unless (defined $value && $value !~ /^$/) { # spent 167µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call |
816 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
817 | } | ||||
818 | 34 | 543µs | 34 | 4.09ms | $conf->{parser}->add_to_addrlist ($key, split (' ', $value)); # keep tainted # spent 4.09ms making 34 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist, avg 120µs/call |
819 | } | ||||
820 | |||||
821 | sub remove_addrlist_value { | ||||
822 | my ($conf, $key, $value, $line) = @_; | ||||
823 | |||||
824 | unless (defined $value && $value !~ /^$/) { | ||||
825 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
826 | } | ||||
827 | $conf->{parser}->remove_from_addrlist ($key, split (' ', $value)); | ||||
828 | } | ||||
829 | |||||
830 | # spent 368µs (324+44) within Mail::SpamAssassin::Conf::Parser::set_template_append which was called 17 times, avg 22µs/call:
# 17 times (324µs+44µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 22µs/call | ||||
831 | 17 | 81µs | my ($conf, $key, $value, $line) = @_; | ||
832 | 18 | 146µs | 17 | 44µs | if ( $value =~ /^"(.*?)"$/ ) { $value = $1; } # spent 44µs making 17 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
833 | 17 | 158µs | $conf->{$key} .= $value."\n"; # keep tainted | ||
834 | } | ||||
835 | |||||
836 | # spent 35µs within Mail::SpamAssassin::Conf::Parser::set_template_clear which was called 2 times, avg 18µs/call:
# 2 times (35µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 18µs/call | ||||
837 | 2 | 11µs | my ($conf, $key, $value, $line) = @_; | ||
838 | 2 | 6µs | unless (!defined $value || $value eq '') { | ||
839 | return $Mail::SpamAssassin::Conf::INVALID_VALUE; | ||||
840 | } | ||||
841 | 2 | 22µs | $conf->{$key} = ''; | ||
842 | } | ||||
843 | |||||
844 | ########################################################################### | ||||
845 | |||||
846 | # spent 7.67s (88.7ms+7.58) within Mail::SpamAssassin::Conf::Parser::finish_parsing which was called:
# once (88.7ms+7.58s) by Mail::SpamAssassin::Conf::finish_parsing at line 4860 of Mail/SpamAssassin/Conf.pm | ||||
847 | 1 | 2µs | my ($self, $isuserconf) = @_; | ||
848 | 1 | 3µ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. | ||||
852 | 1 | 6µs | if (!$isuserconf) { | ||
853 | 1 | 13µs | 1 | 685µs | $conf->{main}->call_plugins("finish_parsing_start", { conf => $conf }); # spent 685µs making 1 call to Mail::SpamAssassin::call_plugins |
854 | } else { | ||||
855 | $conf->{main}->call_plugins("user_conf_parsing_start", { conf => $conf }); | ||||
856 | } | ||||
857 | |||||
858 | 1 | 474µs | 1 | 7.12s | $self->trace_meta_dependencies(); # spent 7.12s making 1 call to Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies |
859 | 1 | 478µs | 1 | 137ms | $self->fix_priorities(); # spent 137ms making 1 call to Mail::SpamAssassin::Conf::Parser::fix_priorities |
860 | |||||
861 | # don't do this if allow_user_rules is active, since it deletes entries | ||||
862 | # from {tests} | ||||
863 | 1 | 11µs | if (!$conf->{allow_user_rules}) { | ||
864 | 1 | 20µs | 1 | 105ms | $self->find_dup_rules(); # must be after fix_priorities() # spent 105ms making 1 call to Mail::SpamAssassin::Conf::Parser::find_dup_rules |
865 | } | ||||
866 | |||||
867 | 1 | 8µs | 1 | 7µs | dbg("config: finish parsing"); # spent 7µs making 1 call to Mail::SpamAssassin::Logger::dbg |
868 | |||||
869 | 2058 | 30.9ms | while (my ($name, $text) = each %{$conf->{tests}}) { | ||
870 | 2056 | 4.14ms | my $type = $conf->{test_types}->{$name}; | ||
871 | 2056 | 5.50ms | my $priority = $conf->{priority}->{$name} || 0; | ||
872 | 2056 | 3.79ms | $conf->{priorities}->{$priority}++; | ||
873 | |||||
874 | # eval type handling | ||||
875 | 2056 | 6.73ms | if (($type & 1) == 1) { | ||
876 | 379 | 9.55ms | 379 | 4.41ms | if (my ($function, $args) = ($text =~ m/(.*?)\s*\((.*?)\)\s*$/)) { # spent 4.41ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 12µs/call |
877 | 379 | 3.07ms | 379 | 58.2ms | my ($packed, $argsref) = # spent 58.2ms making 379 calls to Mail::SpamAssassin::Conf::Parser::pack_eval_method, avg 154µs/call |
878 | $self->pack_eval_method($function, $args, $name, $text); | ||||
879 | |||||
880 | 379 | 1.79ms | if (!$packed) { | ||
881 | # we've already warned about this | ||||
882 | } | ||||
883 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_EVALS) { | ||||
884 | 187 | 1.49ms | $conf->{body_evals}->{$priority}->{$name} = $packed; | ||
885 | } | ||||
886 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS) { | ||||
887 | 101 | 749µ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 | ||||
892 | 73 | 831µs | $conf->{rbl_evals}->{$name} = [ $function, @$argsref ]; | ||
893 | } | ||||
894 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_EVALS) { | ||||
895 | 7 | 53µs | $conf->{rawbody_evals}->{$priority}->{$name} = $packed; | ||
896 | } | ||||
897 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_EVALS) { | ||||
898 | 11 | 110µ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 { | ||||
913 | 1677 | 5.52ms | if ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS) { | ||
914 | 513 | 4.14ms | $conf->{body_tests}->{$priority}->{$name} = $text; | ||
915 | } | ||||
916 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS) { | ||||
917 | 595 | 4.81ms | $conf->{head_tests}->{$priority}->{$name} = $text; | ||
918 | } | ||||
919 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) { | ||||
920 | 463 | 3.51ms | $conf->{meta_tests}->{$priority}->{$name} = $text; | ||
921 | } | ||||
922 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS) { | ||||
923 | 69 | 573µs | $conf->{uri_tests}->{$priority}->{$name} = $text; | ||
924 | } | ||||
925 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS) { | ||||
926 | 33 | 242µs | $conf->{rawbody_tests}->{$priority}->{$name} = $text; | ||
927 | } | ||||
928 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS) { | ||||
929 | 2 | 11µ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 | |||||
939 | 1 | 9µs | 1 | 21µs | $self->lint_trusted_networks(); # spent 21µs making 1 call to Mail::SpamAssassin::Conf::Parser::lint_trusted_networks |
940 | |||||
941 | 1 | 6µs | if (!$isuserconf) { | ||
942 | 1 | 14µs | 1 | 155ms | $conf->{main}->call_plugins("finish_parsing_end", { conf => $conf }); # spent 155ms making 1 call to Mail::SpamAssassin::call_plugins |
943 | } else { | ||||
944 | $conf->{main}->call_plugins("user_conf_parsing_end", { conf => $conf }); | ||||
945 | } | ||||
946 | |||||
947 | 1 | 13µs | 1 | 28µs | $conf->found_any_rules(); # before we might delete {tests} # spent 28µs making 1 call to Mail::SpamAssassin::Conf::found_any_rules |
948 | |||||
949 | 1 | 27µs | if (!$conf->{allow_user_rules}) { | ||
950 | # free up stuff we no longer need | ||||
951 | 1 | 2.33ms | delete $conf->{tests}; | ||
952 | 1 | 590µs | delete $conf->{priority}; | ||
953 | #test_types are needed - see bug 5503 | ||||
954 | #delete $conf->{test_types}; | ||||
955 | } | ||||
956 | } | ||||
957 | |||||
958 | # spent 7.12s (33.1ms+7.09) within Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies which was called:
# once (33.1ms+7.09s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 858 | ||||
959 | 1 | 2µs | my ($self) = @_; | ||
960 | 1 | 3µs | my $conf = $self->{conf}; | ||
961 | 1 | 4µs | $conf->{meta_dependencies} = { }; | ||
962 | |||||
963 | 2 | 3.50ms | foreach my $name (keys %{$conf->{tests}}) { | ||
964 | 2067 | 7.97ms | next unless ($conf->{test_types}->{$name} | ||
965 | == $Mail::SpamAssassin::Conf::TYPE_META_TESTS); | ||||
966 | |||||
967 | 464 | 1.15ms | my $deps = [ ]; | ||
968 | 464 | 893µs | my $alreadydone = { }; | ||
969 | 464 | 3.38ms | 464 | 7.09s | $self->_meta_deps_recurse($conf, $name, $name, $deps, $alreadydone); # spent 7.09s making 464 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 15.3ms/call |
970 | 928 | 14.7ms | $conf->{meta_dependencies}->{$name} = join (' ', @{$deps}); | ||
971 | } | ||||
972 | } | ||||
973 | |||||
974 | # spent 7.09s (5.47+1.62) within Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse which was called 13832 times, avg 513µs/call:
# 13368 times (5.26s+-5.26s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 1000, avg 0s/call
# 464 times (219ms+6.87s) by Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies at line 969, avg 15.3ms/call | ||||
975 | 13832 | 29.9ms | my ($self, $conf, $toprule, $name, $deps, $alreadydone) = @_; | ||
976 | |||||
977 | # Only do each rule once per top-level meta; avoid infinite recursion | ||||
978 | 13832 | 59.7ms | return if $alreadydone->{$name}; | ||
979 | 11323 | 76.1ms | $alreadydone->{$name} = 1; | ||
980 | |||||
981 | # Obviously, don't trace empty or nonexistent rules | ||||
982 | 11323 | 45.0ms | my $rule = $conf->{tests}->{$name}; | ||
983 | 11323 | 19.2ms | return unless $rule; | ||
984 | |||||
985 | # Lex the rule into tokens using a rather simple RE method ... | ||||
986 | 11321 | 19.7ms | my $lexer = ARITH_EXPRESSION_LEXER; | ||
987 | 11321 | 940ms | 22642 | 560ms | my @tokens = ($rule =~ m/$lexer/g); # spent 498ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 44µs/call
# spent 61.9ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 5µs/call |
988 | |||||
989 | # Go through each token in the meta rule | ||||
990 | 11321 | 24.9ms | my $conf_tests = $conf->{tests}; | ||
991 | 11321 | 688ms | foreach my $token (@tokens) { | ||
992 | # has to be an alpha+numeric token | ||||
993 | # next if $token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/; | ||||
994 | 269448 | 4.02s | 269448 | 659ms | next if $token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s; # faster # spent 659ms making 269448 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
995 | # and has to be a rule name | ||||
996 | 120401 | 431ms | next unless exists $conf_tests->{$token}; | ||
997 | |||||
998 | # add and recurse | ||||
999 | 26736 | 144ms | 13368 | 396ms | push(@{$deps}, untaint_var($token)); # spent 396ms making 13368 calls to Mail::SpamAssassin::Util::untaint_var, avg 30µs/call |
1000 | 13368 | 129ms | 13368 | 0s | $self->_meta_deps_recurse($conf, $toprule, $token, $deps, $alreadydone); # spent 14.6s making 13368 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 1.09ms/call, recursion: max depth 7, sum of overlapping time 14.6s |
1001 | } | ||||
1002 | } | ||||
1003 | |||||
1004 | # spent 137ms (114+22.4) within Mail::SpamAssassin::Conf::Parser::fix_priorities which was called:
# once (114ms+22.4ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 859 | ||||
1005 | 1 | 2µs | my ($self) = @_; | ||
1006 | 1 | 3µs | my $conf = $self->{conf}; | ||
1007 | |||||
1008 | 1 | 2µs | die unless $conf->{meta_dependencies}; # order requirement | ||
1009 | 1 | 3µ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. | ||||
1014 | 1 | 6.18ms | 1 | 22.4ms | foreach my $rule (sort { # spent 22.4ms making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:sort |
1015 | 9735 | 22.4ms | $pri->{$a} <=> $pri->{$b} | ||
1016 | 1 | 2µ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 | ||||
1020 | 2067 | 6.81ms | my $deps = $conf->{meta_dependencies}->{$rule}; | ||
1021 | 2067 | 3.29ms | next unless (defined $deps); | ||
1022 | |||||
1023 | 464 | 1.34ms | my $basepri = $pri->{$rule}; | ||
1024 | 464 | 11.8ms | foreach my $dep (split ' ', $deps) { | ||
1025 | 13368 | 38.6ms | my $deppri = $pri->{$dep}; | ||
1026 | 13368 | 46.2ms | if ($deppri > $basepri) { | ||
1027 | dbg("rules: $rule (pri $basepri) requires $dep (pri $deppri): fixed"); | ||||
1028 | $pri->{$dep} = $basepri; | ||||
1029 | } | ||||
1030 | } | ||||
1031 | } | ||||
1032 | } | ||||
1033 | |||||
1034 | # spent 105ms (101+3.69) within Mail::SpamAssassin::Conf::Parser::find_dup_rules which was called:
# once (101ms+3.69ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 864 | ||||
1035 | 1 | 5µs | my ($self) = @_; | ||
1036 | 1 | 4µs | my $conf = $self->{conf}; | ||
1037 | |||||
1038 | 1 | 2µs | my %names_for_text; | ||
1039 | my %dups; | ||||
1040 | 2069 | 28.7ms | while (my ($name, $text) = each %{$conf->{tests}}) { | ||
1041 | 2067 | 4.28ms | my $type = $conf->{test_types}->{$name}; | ||
1042 | |||||
1043 | # skip eval and empty tests | ||||
1044 | 2067 | 4.02ms | next if ($type & 1) || | ||
1045 | ($type eq $Mail::SpamAssassin::Conf::TYPE_EMPTY_TESTS); | ||||
1046 | |||||
1047 | 3372 | 39.7ms | 1686 | 3.47ms | my $tf = ($conf->{tflags}->{$name}||''); $tf =~ s/\s+/ /gs; # spent 3.47ms making 1686 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
1048 | # ensure similar, but differently-typed, rules are not marked as dups; | ||||
1049 | # take tflags into account too due to "tflags multiple" | ||||
1050 | 1686 | 4.92ms | $text = "$type\t$text\t$tf"; | ||
1051 | |||||
1052 | 1686 | 9.44ms | if (defined $names_for_text{$text}) { | ||
1053 | 11 | 72µs | $names_for_text{$text} .= " ".$name; | ||
1054 | 11 | 46µs | $dups{$text} = undef; # found (at least) one | ||
1055 | } else { | ||||
1056 | 1675 | 11.5ms | $names_for_text{$text} = $name; | ||
1057 | } | ||||
1058 | } | ||||
1059 | |||||
1060 | 1 | 839µs | foreach my $text (keys %dups) { | ||
1061 | 10 | 15µs | my $first; | ||
1062 | my $first_pri; | ||||
1063 | 22 | 276µs | 10 | 78µ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 |
1064 | 10 | 33µs | foreach my $name (@names) { | ||
1065 | 21 | 154µs | my $priority = $conf->{priority}->{$name} || 0; | ||
1066 | |||||
1067 | 21 | 87µs | if (!defined $first || $priority < $first_pri) { | ||
1068 | 10 | 17µs | $first_pri = $priority; | ||
1069 | 10 | 22µs | $first = $name; | ||
1070 | } | ||||
1071 | } | ||||
1072 | # $first is now the earliest-occurring rule. mark others as dups | ||||
1073 | |||||
1074 | 10 | 26µs | my @dups; | ||
1075 | 10 | 47µs | foreach my $name (@names) { | ||
1076 | 21 | 37µs | next if $name eq $first; | ||
1077 | 11 | 59µs | push @dups, $name; | ||
1078 | 11 | 111µs | delete $conf->{tests}->{$name}; | ||
1079 | } | ||||
1080 | |||||
1081 | 10 | 171µs | 10 | 144µs | dbg("rules: $first merged duplicates: ".join(' ', @dups)); # spent 144µs making 10 calls to Mail::SpamAssassin::Logger::dbg, avg 14µs/call |
1082 | 10 | 113µs | $conf->{duplicate_rules}->{$first} = \@dups; | ||
1083 | } | ||||
1084 | } | ||||
1085 | |||||
1086 | # spent 58.2ms (51.1+7.09) within Mail::SpamAssassin::Conf::Parser::pack_eval_method which was called 379 times, avg 154µs/call:
# 379 times (51.1ms+7.09ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 877, avg 154µs/call | ||||
1087 | 379 | 3.50ms | my ($self, $function, $args, $name, $text) = @_; | ||
1088 | |||||
1089 | 379 | 603µs | my @args; | ||
1090 | 379 | 1.28ms | if (defined $args) { | ||
1091 | # bug 4419: Parse quoted strings, unquoted alphanumerics/floats, | ||||
1092 | # unquoted IPv4 and IPv6 addresses, and unquoted common domain names. | ||||
1093 | # s// is used so that we can determine whether or not we successfully | ||||
1094 | # parsed ALL arguments. | ||||
1095 | 379 | 1.58ms | local($1,$2,$3); | ||
1096 | 379 | 19.0ms | 379 | 2.79ms | while ($args =~ s/^\s* (?: (['"]) (.*?) \1 | ( [\d\.:A-Za-z-]+? ) ) # spent 2.79ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µs/call |
1097 | \s* (?: , \s* | $ )//x) { | ||||
1098 | 483 | 8.78ms | 483 | 2.35ms | if (defined $2) { # spent 2.35ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 5µs/call |
1099 | 474 | 2.60ms | push @args, $2; | ||
1100 | } | ||||
1101 | else { | ||||
1102 | 9 | 67µs | push @args, $3; | ||
1103 | } | ||||
1104 | } | ||||
1105 | } | ||||
1106 | |||||
1107 | 379 | 695µs | if ($args ne '') { | ||
1108 | $self->lint_warn("syntax error (unparsable argument: $args) for eval function: $name: $text", $name); | ||||
1109 | return; | ||||
1110 | } | ||||
1111 | |||||
1112 | 379 | 824µs | my $argstr = $function; | ||
1113 | 379 | 4.23ms | 379 | 907µs | $argstr =~ s/\s+//gs; # spent 907µs making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
1114 | |||||
1115 | 379 | 1.33ms | if (@args > 0) { | ||
1116 | $argstr .= ',' . join(', ', | ||||
1117 | 1704 | 11.1ms | 483 | 1.04ms | map { my $s = $_; $s =~ s/\#/[HASH]/gs; 'q#' . $s . '#' } @args); # spent 1.04ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
1118 | } | ||||
1119 | 379 | 4.23ms | return ($argstr, \@args); | ||
1120 | } | ||||
1121 | |||||
1122 | ########################################################################### | ||||
1123 | |||||
1124 | # spent 21µs within Mail::SpamAssassin::Conf::Parser::lint_trusted_networks which was called:
# once (21µs+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 939 | ||||
1125 | 1 | 2µs | my ($self) = @_; | ||
1126 | 1 | 4µ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 | |||||
1133 | 1 | 2µs | my ($nt, $matching_against); | ||
1134 | 1 | 4µ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 { | ||||
1141 | 1 | 15µs | return; | ||
1142 | } | ||||
1143 | |||||
1144 | foreach my $net_type ('internal_networks', 'msa_networks') { | ||||
1145 | next unless $conf->{"${net_type}_configured"}; | ||||
1146 | next if $net_type eq $matching_against; | ||||
1147 | |||||
1148 | my $replace_nets; | ||||
1149 | my @valid_net_list; | ||||
1150 | my $net_list = $conf->{$net_type}; | ||||
1151 | |||||
1152 | foreach my $net (@{$net_list->{nets}}) { | ||||
1153 | # don't check to see if an excluded network is included - that's senseless | ||||
1154 | if (!$net->{exclude} && !$nt->contains_net($net)) { | ||||
1155 | my $msg = "$matching_against doesn't contain $net_type entry '". | ||||
1156 | ($net->{as_string})."'"; | ||||
1157 | |||||
1158 | $self->lint_warn($msg, undef); # complain | ||||
1159 | $replace_nets = 1; # and omit it from the new internal set | ||||
1160 | } | ||||
1161 | else { | ||||
1162 | push @valid_net_list, $net; | ||||
1163 | } | ||||
1164 | } | ||||
1165 | |||||
1166 | if ($replace_nets) { | ||||
1167 | # something was invalid. replace the old nets list with a fixed version | ||||
1168 | # (which may be empty) | ||||
1169 | $net_list->{nets} = \@valid_net_list; | ||||
1170 | } | ||||
1171 | } | ||||
1172 | } | ||||
1173 | |||||
1174 | ########################################################################### | ||||
1175 | |||||
1176 | # spent 785ms (226+559) within Mail::SpamAssassin::Conf::Parser::add_test which was called 2074 times, avg 379µs/call:
# 548 times (83.6ms+145ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2979 of Mail/SpamAssassin/Conf.pm, avg 417µs/call
# 513 times (49.0ms+131ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3020] at line 3018 of Mail/SpamAssassin/Conf.pm, avg 351µs/call
# 465 times (43.5ms+256ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3174] at line 3173 of Mail/SpamAssassin/Conf.pm, avg 643µs/call
# 142 times (18.5ms+978µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3020] at line 3011 of Mail/SpamAssassin/Conf.pm, avg 137µs/call
# 102 times (6.93ms+651µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2958 of Mail/SpamAssassin/Conf.pm, avg 74µs/call
# 73 times (5.54ms+504µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2955 of Mail/SpamAssassin/Conf.pm, avg 83µs/call
# 71 times (5.95ms+15.8ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3052] at line 3051 of Mail/SpamAssassin/Conf.pm, avg 306µs/call
# 58 times (4.52ms+769µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2970 of Mail/SpamAssassin/Conf.pm, avg 91µs/call
# 46 times (3.51ms+377µs) by Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/MIMEHeader.pm:160] at line 140 of Mail/SpamAssassin/Plugin/MIMEHeader.pm, avg 85µs/call
# 33 times (3.49ms+7.77ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3088] at line 3086 of Mail/SpamAssassin/Conf.pm, avg 341µs/call
# 11 times (977µs+71µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3122] at line 3114 of Mail/SpamAssassin/Conf.pm, avg 95µs/call
# 7 times (357µs+44µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3088] at line 3080 of Mail/SpamAssassin/Conf.pm, avg 57µs/call
# 2 times (206µs+358µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3122] at line 3120 of Mail/SpamAssassin/Conf.pm, avg 282µs/call
# 2 times (98µs+12µs) by Mail::SpamAssassin::Plugin::AskDNS::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/AskDNS.pm:356] at line 353 of Mail/SpamAssassin/Plugin/AskDNS.pm, avg 55µs/call
# once (67µs+9µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3206] at line 3204 of Mail/SpamAssassin/Conf.pm | ||||
1177 | 2074 | 11.3ms | my ($self, $name, $text, $type) = @_; | ||
1178 | 2074 | 4.38ms | my $conf = $self->{conf}; | ||
1179 | |||||
1180 | # Don't allow invalid names ... | ||||
1181 | 2074 | 41.9ms | 2074 | 9.18ms | if ($name !~ /^\D\w*$/) { # spent 9.18ms making 2074 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 4µs/call |
1182 | $self->lint_warn("config: error: rule '$name' has invalid characters ". | ||||
1183 | "(not Alphanumeric + Underscore + starting with a non-digit)\n", $name); | ||||
1184 | return; | ||||
1185 | } | ||||
1186 | |||||
1187 | # Also set a hard limit for ALL rules (rule names longer than 242 | ||||
1188 | # characters throw warnings). Check this separately from the above | ||||
1189 | # pattern to avoid vague error messages. | ||||
1190 | 2074 | 4.83ms | if (length $name > 200) { | ||
1191 | $self->lint_warn("config: error: rule '$name' is way too long ". | ||||
1192 | "(recommended maximum length is 22 characters)\n", $name); | ||||
1193 | return; | ||||
1194 | } | ||||
1195 | |||||
1196 | # Warn about, but use, long rule names during --lint | ||||
1197 | 2074 | 3.97ms | if ($conf->{lint_rules}) { | ||
1198 | if (length($name) > 50 && $name !~ /^__/ && $name !~ /^T_/) { | ||||
1199 | $self->lint_warn("config: warning: rule name '$name' is over 50 chars ". | ||||
1200 | "(recommended maximum length is 22 characters)\n", $name); | ||||
1201 | } | ||||
1202 | } | ||||
1203 | |||||
1204 | # all of these rule types are regexps | ||||
1205 | 2074 | 5.89ms | if ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS || | ||
1206 | $type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS || | ||||
1207 | $type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS || | ||||
1208 | $type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS) | ||||
1209 | { | ||||
1210 | 619 | 4.24ms | 619 | 151ms | return unless $self->is_delimited_regexp_valid($name, $text); # spent 151ms making 619 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 244µs/call |
1211 | } | ||||
1212 | 2074 | 6.02ms | if ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS) | ||
1213 | { | ||||
1214 | # RFC 5322 section 3.6.8, ftext printable US-ASCII chars not including ":" | ||||
1215 | # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables... | ||||
1216 | 606 | 9.36ms | 606 | 3.10ms | if ($text =~ /^!?defined\([!-9;-\176]+\)$/) { # spent 3.10ms making 606 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call |
1217 | # fine, implements 'exists:' | ||||
1218 | } else { | ||||
1219 | 548 | 14.5ms | 548 | 9.11ms | my ($pat) = ($text =~ /^\s*\S+\s*(?:\=|\!)\~\s*(\S.*?\S)\s*$/); # spent 9.11ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 17µs/call |
1220 | 1096 | 8.48ms | 548 | 1.73ms | if ($pat) { $pat =~ s/\s+\[if-unset:\s+(.+)\]\s*$//; } # spent 1.73ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
1221 | 548 | 4.19ms | 548 | 127ms | return unless $self->is_delimited_regexp_valid($name, $pat); # spent 127ms making 548 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 232µs/call |
1222 | } | ||||
1223 | } | ||||
1224 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) | ||||
1225 | { | ||||
1226 | 465 | 3.53ms | 465 | 252ms | return unless $self->is_meta_valid($name, $text); # spent 252ms making 465 calls to Mail::SpamAssassin::Conf::Parser::is_meta_valid, avg 543µs/call |
1227 | } | ||||
1228 | |||||
1229 | 2074 | 21.1ms | $conf->{tests}->{$name} = $text; | ||
1230 | 2074 | 7.99ms | $conf->{test_types}->{$name} = $type; | ||
1231 | |||||
1232 | 2074 | 29.0ms | 2074 | 5.87ms | if ($name =~ /AUTOLEARNTEST/i) { # spent 5.87ms making 2074 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
1233 | dbg("config: auto-learn: $name has type $type = $conf->{test_types}->{$name} during add_test\n"); | ||||
1234 | } | ||||
1235 | |||||
1236 | |||||
1237 | 2074 | 6.89ms | if ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) { | ||
1238 | 465 | 2.94ms | $conf->{priority}->{$name} ||= 500; | ||
1239 | } | ||||
1240 | else { | ||||
1241 | 1609 | 9.41ms | $conf->{priority}->{$name} ||= 0; | ||
1242 | } | ||||
1243 | 2074 | 4.67ms | $conf->{priority}->{$name} ||= 0; | ||
1244 | 2074 | 16.3ms | $conf->{source_file}->{$name} = $self->{currentfile}; | ||
1245 | |||||
1246 | 2074 | 4.23ms | if ($conf->{main}->{keep_config_parsing_metadata}) { | ||
1247 | $conf->{if_stack}->{$name} = $self->get_if_stack_as_string(); | ||||
1248 | |||||
1249 | if ($self->{file_scoped_attrs}->{testrules}) { | ||||
1250 | $conf->{testrules}->{$name} = 1; # used in build/mkupdates/listpromotable | ||||
1251 | } | ||||
1252 | } | ||||
1253 | |||||
1254 | # if we found this rule in a user_prefs file, it's a user rule -- note that | ||||
1255 | # we may need to recompile the rule code for this type (if they've already | ||||
1256 | # been compiled, e.g. in spamd). | ||||
1257 | # | ||||
1258 | # Note: the want_rebuild_for_type 'flag' is actually a counter; it is decremented | ||||
1259 | # after each scan. This ensures that we always recompile at least once more; | ||||
1260 | # once to *define* the rule, and once afterwards to *undefine* the rule in the | ||||
1261 | # compiled ruleset again. | ||||
1262 | # | ||||
1263 | # If two consecutive scans use user rules, that's ok -- the second one will | ||||
1264 | # reset the counter, and we'll still recompile just once afterwards to undefine | ||||
1265 | # the rule again. | ||||
1266 | # | ||||
1267 | 2074 | 24.8ms | if ($self->{scoresonly}) { | ||
1268 | $conf->{want_rebuild_for_type}->{$type} = 2; | ||||
1269 | $conf->{user_defined_rules}->{$name} = 1; | ||||
1270 | } | ||||
1271 | } | ||||
1272 | |||||
1273 | sub add_regression_test { | ||||
1274 | my ($self, $name, $ok_or_fail, $string) = @_; | ||||
1275 | my $conf = $self->{conf}; | ||||
1276 | |||||
1277 | if ($conf->{regression_tests}->{$name}) { | ||||
1278 | push @{$conf->{regression_tests}->{$name}}, [$ok_or_fail, $string]; | ||||
1279 | } | ||||
1280 | else { | ||||
1281 | # initialize the array, and create one element | ||||
1282 | $conf->{regression_tests}->{$name} = [ [$ok_or_fail, $string] ]; | ||||
1283 | } | ||||
1284 | } | ||||
1285 | |||||
1286 | # spent 252ms (198+54.1) within Mail::SpamAssassin::Conf::Parser::is_meta_valid which was called 465 times, avg 543µs/call:
# 465 times (198ms+54.1ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1226, avg 543µs/call | ||||
1287 | 465 | 2.21ms | my ($self, $name, $rule) = @_; | ||
1288 | |||||
1289 | 465 | 1.02ms | my $meta = ''; | ||
1290 | 465 | 3.51ms | 465 | 13.5ms | $rule = untaint_var($rule); # must be careful below # spent 13.5ms making 465 calls to Mail::SpamAssassin::Util::untaint_var, avg 29µs/call |
1291 | |||||
1292 | # Lex the rule into tokens using a rather simple RE method ... | ||||
1293 | 465 | 1.00ms | my $lexer = ARITH_EXPRESSION_LEXER; | ||
1294 | 465 | 30.1ms | 930 | 19.1ms | my @tokens = ($rule =~ m/$lexer/g); # spent 16.5ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 35µs/call
# spent 2.69ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 6µs/call |
1295 | 465 | 1.27ms | if (length($name) == 1) { | ||
1296 | for (@tokens) { | ||||
1297 | print "$name $_\n " or die "Error writing token: $!"; | ||||
1298 | } | ||||
1299 | } | ||||
1300 | # Go through each token in the meta rule | ||||
1301 | 465 | 1.89ms | foreach my $token (@tokens) { | ||
1302 | # Numbers can't be rule names | ||||
1303 | 7210 | 142ms | 7210 | 21.5ms | if ($token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s) { # spent 21.5ms making 7210 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
1304 | 4112 | 7.74ms | $meta .= "$token "; | ||
1305 | } | ||||
1306 | # Zero will probably cause more errors | ||||
1307 | else { | ||||
1308 | 3098 | 5.36ms | $meta .= "0 "; | ||
1309 | } | ||||
1310 | } | ||||
1311 | |||||
1312 | 465 | 1.76ms | my $evalstr = 'my $x = ' . $meta . '; 1;'; | ||
1313 | 465 | 30.1ms | if (eval $evalstr) { # spent 350µs executing statements in 42 string evals (merged)
# spent 347µs executing statements in 37 string evals (merged)
# spent 243µs executing statements in 26 string evals (merged)
# spent 219µs executing statements in 24 string evals (merged)
# spent 181µs executing statements in 20 string evals (merged)
# spent 148µs executing statements in 17 string evals (merged)
# spent 105µs executing statements in 14 string evals (merged)
# spent 97µs executing statements in 12 string evals (merged)
# spent 77µs executing statements in 8 string evals (merged)
# spent 72µs executing statements in 8 string evals (merged)
# spent 70µs executing statements in 8 string evals (merged)
# spent 69µs executing statements in 7 string evals (merged)
# spent 64µs executing statements in 8 string evals (merged)
# spent 63µs executing statements in 7 string evals (merged)
# spent 56µs executing statements in 6 string evals (merged)
# spent 53µs executing statements in 6 string evals (merged)
# spent 50µs executing statements in 6 string evals (merged)
# spent 46µs executing statements in 6 string evals (merged)
# spent 45µs executing statements in 4 string evals (merged)
# spent 45µs executing statements in 5 string evals (merged)
# spent 45µs executing statements in 5 string evals (merged)
# spent 43µs executing statements in 5 string evals (merged)
# spent 40µs executing statements in 5 string evals (merged)
# spent 35µs executing statements in 4 string evals (merged)
# spent 32µs executing statements in string eval
# spent 32µs executing statements in 3 string evals (merged)
# spent 31µs executing statements in 4 string evals (merged)
# spent 31µs executing statements in 3 string evals (merged)
# spent 30µs executing statements in 3 string evals (merged)
# spent 30µs executing statements in 3 string evals (merged)
# spent 29µs executing statements in 3 string evals (merged)
# spent 26µs executing statements in 2 string evals (merged)
# spent 25µs executing statements in 2 string evals (merged)
# spent 25µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 3 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 3 string evals (merged)
# spent 24µs executing statements in 3 string evals (merged)
# spent 23µs executing statements in 2 string evals (merged)
# spent 23µs executing statements in string eval
# spent 22µs executing statements in 3 string evals (merged)
# spent 21µs executing statements in 2 string evals (merged)
# spent 21µs executing statements in 2 string evals (merged)
# spent 21µs executing statements in 2 string evals (merged)
# spent 20µs executing statements in 2 string evals (merged)
# spent 20µs executing statements in 2 string evals (merged)
# spent 20µs executing statements in 2 string evals (merged)
# spent 19µs executing statements in 2 string evals (merged)
# spent 19µs executing statements in 2 string evals (merged)
# spent 18µs executing statements in 2 string evals (merged)
# spent 17µs executing statements in string eval
# spent 17µs executing statements in 2 string evals (merged)
# spent 16µs executing statements in 2 string evals (merged)
# spent 16µs executing statements in 2 string evals (merged)
# spent 16µs executing statements in 2 string evals (merged)
# spent 15µs executing statements in 2 string evals (merged)
# spent 15µs executing statements in 2 string evals (merged)
# spent 15µs executing statements in string eval
# spent 15µs executing statements in 2 string evals (merged)
# spent 15µs executing statements in string eval
# spent 15µs executing statements in 2 string evals (merged)
# spent 15µs executing statements in string eval
# spent 14µs executing statements in string eval
# spent 14µs executing statements in 2 string evals (merged)
# spent 14µs executing statements in 2 string evals (merged)
# spent 14µs executing statements in string eval
# spent 14µs executing statements in string eval
# spent 14µs executing statements in 2 string evals (merged)
# spent 14µs executing statements in string eval
# spent 14µs executing statements in string eval
# spent 14µs executing statements in string eval
# spent 13µs executing statements in string eval
# spent 13µs executing statements in string eval
# spent 13µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval | ||
1314 | 465 | 8.06ms | return 1; | ||
1315 | } | ||||
1316 | my $err = $@ ne '' ? $@ : "errno=$!"; chomp $err; | ||||
1317 | $err =~ s/\s+(?:at|near)\b.*//s; | ||||
1318 | $err =~ s/Illegal division by zero/division by zero possible/i; | ||||
1319 | $self->lint_warn("config: invalid expression for rule $name: \"$rule\": $err\n", $name); | ||||
1320 | return 0; | ||||
1321 | } | ||||
1322 | |||||
1323 | # spent 291ms (44.6+246) within Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid which was called 1228 times, avg 237µs/call:
# 619 times (17.7ms+133ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1210, avg 244µs/call
# 548 times (24.9ms+102ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1221, avg 232µs/call
# 46 times (1.51ms+8.14ms) by Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/MIMEHeader.pm:160] at line 116 of Mail/SpamAssassin/Plugin/MIMEHeader.pm, avg 210µs/call
# 15 times (460µs+2.90ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2701] at line 2685 of Mail/SpamAssassin/Conf.pm, avg 224µs/call | ||||
1324 | 1228 | 6.29ms | my ($self, $name, $re) = @_; | ||
1325 | |||||
1326 | 1228 | 27.7ms | 1228 | 8.32ms | if (!$re || $re !~ /^\s*m?(\W).*(?:\1|>|}|\)|\])[a-z]*\s*$/) { # spent 8.32ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 7µs/call |
1327 | $re ||= ''; | ||||
1328 | $self->lint_warn("config: invalid regexp for rule $name: $re: missing or invalid delimiters\n", $name); | ||||
1329 | return 0; | ||||
1330 | } | ||||
1331 | 1228 | 27.7ms | 1228 | 238ms | return $self->is_regexp_valid($name, $re); # spent 238ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::is_regexp_valid, avg 194µs/call |
1332 | } | ||||
1333 | |||||
1334 | # spent 238ms (132+105) within Mail::SpamAssassin::Conf::Parser::is_regexp_valid which was called 1228 times, avg 194µs/call:
# 1228 times (132ms+105ms) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1331, avg 194µs/call | ||||
1335 | 1228 | 6.60ms | my ($self, $name, $re) = @_; | ||
1336 | |||||
1337 | # OK, try to remove any normal perl-style regexp delimiters at | ||||
1338 | # the start and end, and modifiers at the end if present, | ||||
1339 | # so we can validate those too. | ||||
1340 | 1228 | 2.96ms | my $origre = $re; | ||
1341 | 1228 | 2.93ms | my $safere = $re; | ||
1342 | 1228 | 2.37ms | my $mods = ''; | ||
1343 | 1228 | 5.02ms | local ($1,$2); | ||
1344 | 1228 | 76.2ms | 6034 | 20.2ms | if ($re =~ s/^m\{//) { # spent 20.2ms making 6034 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
1345 | 28 | 228µs | 14 | 93µs | $re =~ s/\}([a-z]*)\z//; $mods = $1; # spent 93µs making 14 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µs/call |
1346 | } | ||||
1347 | elsif ($re =~ s/^m\(//) { | ||||
1348 | $re =~ s/\)([a-z]*)\z//; $mods = $1; | ||||
1349 | } | ||||
1350 | elsif ($re =~ s/^m<//) { | ||||
1351 | $re =~ s/>([a-z]*)\z//; $mods = $1; | ||||
1352 | } | ||||
1353 | elsif ($re =~ s/^m(\W)//) { | ||||
1354 | 100 | 2.37ms | 100 | 1.26ms | $re =~ s/\Q$1\E([a-z]*)\z//; $mods = $1; # spent 815µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 16µs/call
# spent 448µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 9µs/call |
1355 | } | ||||
1356 | elsif ($re =~ s{^/(.*)/([a-z]*)\z}{$1}) { | ||||
1357 | 1164 | 3.68ms | $mods = $2; | ||
1358 | } | ||||
1359 | else { | ||||
1360 | $safere = "m#".$re."#"; | ||||
1361 | } | ||||
1362 | |||||
1363 | 1228 | 3.32ms | if ($self->{conf}->{lint_rules} || | ||
1364 | $self->{conf}->{ignore_always_matching_regexps}) | ||||
1365 | { | ||||
1366 | my $msg = $self->is_always_matching_regexp($name, $re); | ||||
1367 | |||||
1368 | if (defined $msg) { | ||||
1369 | if ($self->{conf}->{lint_rules}) { | ||||
1370 | $self->lint_warn($msg, $name); | ||||
1371 | } else { | ||||
1372 | warn $msg; | ||||
1373 | return 0; | ||||
1374 | } | ||||
1375 | } | ||||
1376 | } | ||||
1377 | |||||
1378 | # now prepend the modifiers, in order to check if they're valid | ||||
1379 | 1228 | 3.53ms | if ($mods) { | ||
1380 | 788 | 4.23ms | $re = "(?" . $mods . ")" . $re; | ||
1381 | } | ||||
1382 | |||||
1383 | # note: this MUST use m/...${re}.../ in some form or another, ie. | ||||
1384 | # interpolation of the $re variable into a code regexp, in order to test the | ||||
1385 | # security of the regexp. simply using ("" =~ $re) will NOT do that, and | ||||
1386 | # will therefore open a hole! | ||||
1387 | { # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables... | ||||
1388 | 6140 | 131ms | 2456 | 83.9ms | if (eval { ("" =~ m{$re}); 1; }) { return 1 } # spent 81.7ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 67µs/call
# spent 2.26ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
1389 | } | ||||
1390 | my $err = $@ ne '' ? $@ : "errno=$!"; chomp $err; | ||||
1391 | $err =~ s/ at .*? line \d.*$//; | ||||
1392 | $self->lint_warn("config: invalid regexp for rule $name: $origre: $err\n", $name); | ||||
1393 | return 0; | ||||
1394 | } | ||||
1395 | |||||
1396 | # check the pattern for some basic errors, and warn if found | ||||
1397 | sub is_always_matching_regexp { | ||||
1398 | my ($self, $name, $re) = @_; | ||||
1399 | |||||
1400 | if ($re =~ /(?<!\\)\|\|/) { | ||||
1401 | return "config: regexp for rule $name always matches due to '||'"; | ||||
1402 | } | ||||
1403 | elsif ($re =~ /^\|/) { | ||||
1404 | return "config: regexp for rule $name always matches due to " . | ||||
1405 | "pattern starting with '|'"; | ||||
1406 | } | ||||
1407 | elsif ($re =~ /\|(?<!\\\|)$/) { | ||||
1408 | return "config: regexp for rule $name always matches due to " . | ||||
1409 | "pattern ending with '|'"; | ||||
1410 | } | ||||
1411 | return; | ||||
1412 | } | ||||
1413 | |||||
1414 | ########################################################################### | ||||
1415 | |||||
1416 | # spent 4.09ms (2.91+1.18) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist which was called 34 times, avg 120µs/call:
# 34 times (2.91ms+1.18ms) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 818, avg 120µs/call | ||||
1417 | 34 | 140µs | my ($self, $singlelist, @addrs) = @_; | ||
1418 | 34 | 75µs | my $conf = $self->{conf}; | ||
1419 | |||||
1420 | 34 | 447µs | foreach my $addr (@addrs) { | ||
1421 | 34 | 100µs | $addr = lc $addr; | ||
1422 | 34 | 73µs | my $re = $addr; | ||
1423 | 34 | 447µs | 34 | 93µs | $re =~ s/[\000\\\(]/_/gs; # paranoia # spent 93µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
1424 | 34 | 1.78ms | 152 | 682µs | $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars # spent 540µs making 118 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 5µs/call
# spent 142µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call |
1425 | 34 | 94µs | $re =~ tr/?/./; # "?" -> "." | ||
1426 | 34 | 634µs | 34 | 408µs | $re =~ s/\*+/\.\*/g; # "*" -> "any string" # spent 408µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 12µs/call |
1427 | 34 | 443µs | $conf->{$singlelist}->{$addr} = "^${re}\$"; | ||
1428 | } | ||||
1429 | } | ||||
1430 | |||||
1431 | # spent 13.3ms (10.2+3.13) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd which was called 102 times, avg 131µs/call:
# 83 times (8.29ms+2.42ms) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim at line 1470, avg 129µs/call
# 19 times (1.92ms+710µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:433] at line 431 of Mail/SpamAssassin/Conf.pm, avg 138µs/call | ||||
1432 | 102 | 422µs | my ($self, $listname, $addr, $domain) = @_; | ||
1433 | 102 | 203µs | my $conf = $self->{conf}; | ||
1434 | |||||
1435 | 102 | 228µs | $domain = lc $domain; | ||
1436 | 102 | 315µs | $addr = lc $addr; | ||
1437 | 102 | 9.89ms | if ($conf->{$listname}->{$addr}) { | ||
1438 | 10 | 68µs | push @{$conf->{$listname}->{$addr}{domain}}, $domain; | ||
1439 | } | ||||
1440 | else { | ||||
1441 | 97 | 211µs | my $re = $addr; | ||
1442 | 97 | 1.39ms | 97 | 315µs | $re =~ s/[\000\\\(]/_/gs; # paranoia # spent 315µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
1443 | 97 | 5.85ms | 458 | 2.14ms | $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars # spent 1.64ms making 361 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 5µs/call
# spent 498µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 5µs/call |
1444 | 97 | 401µs | $re =~ tr/?/./; # "?" -> "." | ||
1445 | 97 | 1.79ms | 97 | 674µs | $re =~ s/\*+/\.\*/g; # "*" -> "any string" # spent 674µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µs/call |
1446 | 97 | 1.01ms | $conf->{$listname}->{$addr}{re} = "^${re}\$"; | ||
1447 | 97 | 528µs | $conf->{$listname}->{$addr}{domain} = [ $domain ]; | ||
1448 | } | ||||
1449 | } | ||||
1450 | |||||
1451 | sub 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 | |||||
1460 | sub remove_from_addrlist_rcvd { | ||||
1461 | my ($self, $listname, @addrs) = @_; | ||||
1462 | my $conf = $self->{conf}; | ||||
1463 | |||||
1464 | foreach my $addr (@addrs) { | ||||
1465 | delete($conf->{$listname}->{lc $addr}); | ||||
1466 | } | ||||
1467 | } | ||||
1468 | |||||
1469 | # spent 20.5ms (9.77+10.7) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim which was called 83 times, avg 247µs/call:
# 83 times (9.77ms+10.7ms) by Mail::SpamAssassin::Plugin::DKIM::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/DKIM.pm:420] at line 418 of Mail/SpamAssassin/Plugin/DKIM.pm, avg 247µs/call | ||||
1470 | 83 | 1.29ms | 83 | 10.7ms | add_to_addrlist_rcvd(@_); # spent 10.7ms making 83 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd, avg 129µs/call |
1471 | } | ||||
1472 | |||||
1473 | sub remove_from_addrlist_dkim { | ||||
1474 | my ($self, $listname, $addr, $domain) = @_; | ||||
1475 | my $conf = $self->{conf}; | ||||
1476 | my $conf_lname = $conf->{$listname}; | ||||
1477 | |||||
1478 | $addr = lc $addr; | ||||
1479 | if ($conf_lname->{$addr}) { | ||||
1480 | $domain = lc $domain; | ||||
1481 | my $domains_listref = $conf_lname->{$addr}{domain}; | ||||
1482 | # removing $domain from the list | ||||
1483 | my @replacement = grep { lc $_ ne $domain } @$domains_listref; | ||||
1484 | if (!@replacement) { # nothing left, remove the entire addr entry | ||||
1485 | delete($conf_lname->{$addr}); | ||||
1486 | } elsif (@replacement != @$domains_listref) { # anything changed? | ||||
1487 | $conf_lname->{$addr}{domain} = \@replacement; | ||||
1488 | } | ||||
1489 | } | ||||
1490 | } | ||||
1491 | |||||
1492 | |||||
1493 | ########################################################################### | ||||
1494 | |||||
1495 | # spent 41.2ms (11.5+29.8) within Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file which was called 58 times, avg 711µs/call:
# 58 times (11.5ms+29.8ms) by Mail::SpamAssassin::Conf::Parser::parse at line 342, avg 711µs/call | ||||
1496 | 58 | 279µs | my ($self, $path) = @_; | ||
1497 | |||||
1498 | # the path may be specified as "~/foo", so deal with that | ||||
1499 | 58 | 672µs | 58 | 22.5ms | $path = $self->{conf}->{main}->sed_path($path); # spent 22.5ms making 58 calls to Mail::SpamAssassin::sed_path, avg 388µs/call |
1500 | |||||
1501 | 58 | 996µs | 58 | 1.23ms | if (!File::Spec->file_name_is_absolute ($path)) { # spent 1.23ms making 58 calls to File::Spec::Unix::file_name_is_absolute, avg 21µs/call |
1502 | 58 | 632µs | 58 | 4.10ms | my ($vol, $dirs, $file) = File::Spec->splitpath ($self->{currentfile}); # spent 4.10ms making 58 calls to File::Spec::Unix::splitpath, avg 71µs/call |
1503 | 58 | 565µs | 58 | 1.32ms | $path = File::Spec->catpath ($vol, $dirs, $path); # spent 1.32ms making 58 calls to File::Spec::Unix::catpath, avg 23µs/call |
1504 | 58 | 655µs | 58 | 601µs | dbg("config: fixed relative path: $path"); # spent 601µs making 58 calls to Mail::SpamAssassin::Logger::dbg, avg 10µs/call |
1505 | } | ||||
1506 | 58 | 624µs | return $path; | ||
1507 | } | ||||
1508 | |||||
1509 | ########################################################################### | ||||
1510 | |||||
1511 | sub 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 | |||||
1537 | sub get_if_stack_as_string { | ||||
1538 | my ($self) = @_; | ||||
1539 | return join ' ', map { | ||||
1540 | $_->{conditional} | ||||
1541 | } @{$self->{if_stack}}; | ||||
1542 | } | ||||
1543 | |||||
1544 | ########################################################################### | ||||
1545 | |||||
1546 | 1 | 11µs | 1; | ||
# spent 1.32s within Mail::SpamAssassin::Conf::Parser::CORE:match which was called 322611 times, avg 4µs/call:
# 269448 times (659ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 994, avg 2µs/call
# 16436 times (46.1ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 273, avg 3µs/call
# 11321 times (498ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 44µs/call
# 7210 times (21.5ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1303, avg 3µs/call
# 2650 times (11.9ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 516, avg 4µs/call
# 2074 times (9.18ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1181, avg 4µs/call
# 2074 times (5.87ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1232, avg 3µs/call
# 2067 times (5.73ms+0s) by Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions at line 657, avg 3µs/call
# 1474 times (3.81ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 3µs/call
# 1284 times (2.76ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 640, avg 2µs/call
# 1284 times (2.15ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 642, avg 2µs/call
# 1228 times (8.32ms+0s) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1326, avg 7µs/call
# 1228 times (2.26ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 2µs/call
# 606 times (3.10ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1216, avg 5µs/call
# 548 times (9.11ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1219, avg 17µs/call
# 508 times (7.60ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 15µs/call
# 465 times (16.5ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 35µs/call
# 379 times (4.41ms+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 876, avg 12µs/call
# 136 times (711µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 302, avg 5µs/call
# 68 times (340µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 308, avg 5µs/call
# 55 times (440µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 588, avg 8µs/call
# 34 times (167µs+0s) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 815, avg 5µs/call
# 17 times (44µs+0s) by Mail::SpamAssassin::Conf::Parser::set_template_append at line 832, avg 3µs/call
# 5 times (20µs+0s) by Mail::SpamAssassin::Conf::Parser::set_bool_value at line 749, avg 4µs/call
# 4 times (22µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 722, avg 6µs/call
# 4 times (12µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 719, avg 3µs/call
# 3 times (10µs+0s) by Mail::SpamAssassin::Conf::Parser::set_string_value at line 771, avg 3µs/call
# once (8µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 240 | |||||
# spent 157ms within Mail::SpamAssassin::Conf::Parser::CORE:regcomp which was called 15046 times, avg 10µs/call:
# 11321 times (61.9ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 5µs/call
# 1474 times (6.59ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 4µs/call
# 1228 times (81.7ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 67µs/call
# 508 times (3.31ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 7µs/call
# 465 times (2.69ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 6µs/call
# 50 times (815µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 16µs/call | |||||
sub Mail::SpamAssassin::Conf::Parser::CORE:sort; # opcode | |||||
# spent 272ms within Mail::SpamAssassin::Conf::Parser::CORE:subst which was called 92819 times, avg 3µs/call:
# 16436 times (65.2ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 279, avg 4µs/call
# 16436 times (55.1ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 282, avg 3µs/call
# 16436 times (41.3ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 281, avg 3µs/call
# 16436 times (33.2ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 280, avg 2µs/call
# 9050 times (23.4ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 3µs/call
# 7576 times (19.1ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 291, avg 3µs/call
# 6034 times (20.2ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1344, avg 3µs/call
# 1686 times (3.47ms+0s) by Mail::SpamAssassin::Conf::Parser::find_dup_rules at line 1047, avg 2µs/call
# 548 times (1.73ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1220, avg 3µs/call
# 483 times (2.35ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1098, avg 5µs/call
# 483 times (1.04ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1117, avg 2µs/call
# 379 times (2.79ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1096, avg 7µs/call
# 379 times (907µs+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1113, avg 2µs/call
# 97 times (674µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1445, avg 7µs/call
# 97 times (498µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 5µs/call
# 97 times (315µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1442, avg 3µs/call
# 50 times (448µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 9µs/call
# 34 times (408µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1426, avg 12µs/call
# 34 times (142µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 4µs/call
# 34 times (93µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1423, avg 3µs/call
# 14 times (93µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1345, avg 7µs/call | |||||
# spent 2.18ms within Mail::SpamAssassin::Conf::Parser::CORE:substcont which was called 479 times, avg 5µs/call:
# 361 times (1.64ms+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 5µs/call
# 118 times (540µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 5µs/call |