Filename | /usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf/Parser.pm |
Statements | Executed 1032660 statements in 8.40s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
13832 | 2 | 1 | 4.04s | 5.51s | _meta_deps_recurse (recurses: max depth 7, inclusive time 11.1s) | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 1.51s | 4.55s | parse | Mail::SpamAssassin::Conf::Parser::
322611 | 28 | 1 | 1.23s | 1.23s | CORE:match (opcode) | Mail::SpamAssassin::Conf::Parser::
92819 | 21 | 1 | 277ms | 277ms | CORE:subst (opcode) | Mail::SpamAssassin::Conf::Parser::
2074 | 15 | 3 | 191ms | 703ms | add_test | Mail::SpamAssassin::Conf::Parser::
465 | 1 | 1 | 181ms | 240ms | is_meta_valid | Mail::SpamAssassin::Conf::Parser::
508 | 2 | 1 | 148ms | 215ms | handle_conditional | Mail::SpamAssassin::Conf::Parser::
15046 | 6 | 1 | 137ms | 137ms | CORE:regcomp (opcode) | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 116ms | 121ms | set_default_scores | Mail::SpamAssassin::Conf::Parser::
1228 | 1 | 1 | 108ms | 214ms | is_regexp_valid | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 105ms | 125ms | fix_priorities | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 95.7ms | 6.05s | finish_parsing | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 94.5ms | 98.0ms | find_dup_rules | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 59.5ms | 139ms | check_for_missing_descriptions | Mail::SpamAssassin::Conf::Parser::
1276 | 1 | 1 | 48.8ms | 262ms | set_hash_key_value | Mail::SpamAssassin::Conf::Parser::
1228 | 4 | 3 | 37.0ms | 258ms | is_delimited_regexp_valid | Mail::SpamAssassin::Conf::Parser::
379 | 1 | 1 | 35.5ms | 42.2ms | pack_eval_method | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 30.7ms | 5.54s | trace_meta_dependencies | Mail::SpamAssassin::Conf::Parser::
11 | 2 | 1 | 20.1ms | 20.1ms | CORE:sort (opcode) | Mail::SpamAssassin::Conf::Parser::
34 | 1 | 1 | 9.29ms | 10.1ms | add_to_addrlist | Mail::SpamAssassin::Conf::Parser::
102 | 2 | 2 | 7.89ms | 10.3ms | add_to_addrlist_rcvd | Mail::SpamAssassin::Conf::Parser::
58 | 1 | 1 | 4.63ms | 30.0ms | fix_path_relative_to_current_file | Mail::SpamAssassin::Conf::Parser::
434 | 43 | 43 | 3.93ms | 3.93ms | cond_clause_plugin_loaded | Mail::SpamAssassin::Conf::Parser::
16 | 1 | 1 | 3.89ms | 3.89ms | build_command_luts | Mail::SpamAssassin::Conf::Parser::
55 | 1 | 1 | 2.61ms | 4.18ms | cond_clause_can_or_has | Mail::SpamAssassin::Conf::Parser::
16 | 1 | 1 | 2.08ms | 2.08ms | set_defaults_from_command_list | Mail::SpamAssassin::Conf::Parser::
479 | 2 | 1 | 1.67ms | 1.67ms | CORE:substcont (opcode) | Mail::SpamAssassin::Conf::Parser::
83 | 1 | 1 | 968µs | 9.28ms | add_to_addrlist_dkim | Mail::SpamAssassin::Conf::Parser::
34 | 1 | 1 | 912µs | 11.1ms | set_addrlist_value | Mail::SpamAssassin::Conf::Parser::
16 | 16 | 16 | 889µs | 6.86ms | register_commands | Mail::SpamAssassin::Conf::Parser::
55 | 14 | 14 | 829µs | 5.01ms | cond_clause_can | Mail::SpamAssassin::Conf::Parser::
17 | 1 | 1 | 512µs | 559µs | set_template_append | Mail::SpamAssassin::Conf::Parser::
21 | 1 | 1 | 492µs | 492µs | setup_default_code_cb | Mail::SpamAssassin::Conf::Parser::
5 | 1 | 1 | 217µs | 231µs | set_bool_value | Mail::SpamAssassin::Conf::Parser::
4 | 1 | 1 | 202µs | 425µs | set_numeric_value | Mail::SpamAssassin::Conf::Parser::
3 | 1 | 1 | 80µs | 89µs | set_string_value | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 50µs | 50µs | BEGIN@137 | Mail::SpamAssassin::Conf::Parser::
2 | 1 | 1 | 45µs | 45µs | set_template_clear | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 42µs | 98µs | BEGIN@592 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 41µs | 374µs | BEGIN@140 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 30µs | 30µs | new | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 26µs | 243µs | BEGIN@139 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 26µs | 88µs | BEGIN@146 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 21µs | 21µs | lint_trusted_networks | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 20µs | 30µs | BEGIN@143 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 20µs | 53µs | BEGIN@144 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 19µs | 26µs | BEGIN@145 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 19µs | 700µs | BEGIN@138 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 17µs | 111µs | BEGIN@148 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 14µs | 14µs | BEGIN@141 | Mail::SpamAssassin::Conf::Parser::
1 | 1 | 1 | 12µs | 12µs | lint_check | 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 | 68µs | 1 | 50µs | # spent 50µs within Mail::SpamAssassin::Conf::Parser::BEGIN@137 which was called:
# once (50µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 137 # spent 50µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@137 |
138 | 2 | 71µs | 2 | 1.38ms | # spent 700µs (19+680) within Mail::SpamAssassin::Conf::Parser::BEGIN@138 which was called:
# once (19µs+680µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 138 # spent 700µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@138
# spent 680µs making 1 call to Exporter::import |
139 | 2 | 71µs | 2 | 460µs | # spent 243µs (26+217) within Mail::SpamAssassin::Conf::Parser::BEGIN@139 which was called:
# once (26µs+217µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 139 # spent 243µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@139
# spent 217µs making 1 call to Exporter::import |
140 | 2 | 88µs | 2 | 707µs | # spent 374µs (41+333) within Mail::SpamAssassin::Conf::Parser::BEGIN@140 which was called:
# once (41µs+333µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 140 # spent 374µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@140
# spent 333µs making 1 call to Exporter::import |
141 | 2 | 52µs | 1 | 14µs | # spent 14µs within Mail::SpamAssassin::Conf::Parser::BEGIN@141 which was called:
# once (14µs+0s) by Mail::SpamAssassin::Conf::BEGIN@88 at line 141 # spent 14µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@141 |
142 | |||||
143 | 2 | 63µs | 2 | 40µs | # spent 30µs (20+10) within Mail::SpamAssassin::Conf::Parser::BEGIN@143 which was called:
# once (20µs+10µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 143 # spent 30µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@143
# spent 10µs making 1 call to strict::import |
144 | 2 | 63µs | 2 | 86µs | # spent 53µs (20+33) within Mail::SpamAssassin::Conf::Parser::BEGIN@144 which was called:
# once (20µs+33µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 144 # spent 53µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@144
# spent 33µs making 1 call to warnings::import |
145 | 2 | 68µs | 2 | 32µs | # spent 26µs (19+6) within Mail::SpamAssassin::Conf::Parser::BEGIN@145 which was called:
# once (19µs+6µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 145 # spent 26µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@145
# spent 6µs making 1 call to bytes::import |
146 | 2 | 77µs | 2 | 149µs | # spent 88µs (26+62) within Mail::SpamAssassin::Conf::Parser::BEGIN@146 which was called:
# once (26µs+62µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 146 # spent 88µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@146
# spent 62µs making 1 call to re::import |
147 | |||||
148 | 1 | 2µs | # spent 111µs (17+94) within Mail::SpamAssassin::Conf::Parser::BEGIN@148 which was called:
# once (17µs+94µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 150 | ||
149 | @ISA | ||||
150 | 1 | 4.35ms | 2 | 205µs | }; # spent 111µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@148
# spent 94µ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 | 2µ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 | 4µs | $self->{command_luts} = { }; | ||
166 | 1 | 4µs | $self->{command_luts}->{frequent} = { }; | ||
167 | 1 | 3µs | $self->{command_luts}->{remaining} = { }; | ||
168 | |||||
169 | 1 | 2µs | bless ($self, $class); | ||
170 | 1 | 9µs | $self; | ||
171 | } | ||||
172 | |||||
173 | ########################################################################### | ||||
174 | |||||
175 | # spent 6.86ms (889µs+5.97) within Mail::SpamAssassin::Conf::Parser::register_commands which was called 16 times, avg 429µs/call:
# once (87µs+3.02ms) by Mail::SpamAssassin::Conf::new at line 4516 of Mail/SpamAssassin/Conf.pm
# once (48µs+778µs) by Mail::SpamAssassin::Plugin::TxRep::set_config at line 1067 of Mail/SpamAssassin/Plugin/TxRep.pm
# once (50µs+360µs) by Mail::SpamAssassin::Plugin::URIDNSBL::set_config at line 813 of Mail/SpamAssassin/Plugin/URIDNSBL.pm
# once (72µs+205µs) by Mail::SpamAssassin::Plugin::ReplaceTags::set_config at line 292 of Mail/SpamAssassin/Plugin/ReplaceTags.pm
# once (56µs+211µs) by Mail::SpamAssassin::Plugin::SPF::set_config at line 228 of Mail/SpamAssassin/Plugin/SPF.pm
# once (48µs+212µs) by Mail::SpamAssassin::Plugin::DKIM::set_config at line 502 of Mail/SpamAssassin/Plugin/DKIM.pm
# once (55µs+202µs) by Mail::SpamAssassin::Plugin::FreeMail::set_config at line 213 of Mail/SpamAssassin/Plugin/FreeMail.pm
# once (45µs+187µs) by Mail::SpamAssassin::Plugin::Hashcash::set_config at line 158 of Mail/SpamAssassin/Plugin/Hashcash.pm
# once (68µs+156µs) by Mail::SpamAssassin::Plugin::AutoLearnThreshold::set_config at line 146 of Mail/SpamAssassin/Plugin/AutoLearnThreshold.pm
# once (47µs+149µs) by Mail::SpamAssassin::Plugin::Razor2::set_config at line 134 of Mail/SpamAssassin/Plugin/Razor2.pm
# once (71µs+107µs) by Mail::SpamAssassin::Plugin::WhiteListSubject::set_config at line 109 of Mail/SpamAssassin/Plugin/WhiteListSubject.pm
# once (45µs+119µs) by Mail::SpamAssassin::Plugin::SpamCop::set_config at line 157 of Mail/SpamAssassin/Plugin/SpamCop.pm
# once (70µs+82µs) by Mail::SpamAssassin::Plugin::MIMEHeader::set_config at line 163 of Mail/SpamAssassin/Plugin/MIMEHeader.pm
# once (44µs+66µs) by Mail::SpamAssassin::Plugin::URIDetail::set_config at line 150 of Mail/SpamAssassin/Plugin/URIDetail.pm
# once (42µs+60µs) by Mail::SpamAssassin::Plugin::VBounce::set_config at line 90 of Mail/SpamAssassin/Plugin/VBounce.pm
# once (42µs+54µs) by Mail::SpamAssassin::Plugin::AskDNS::set_config at line 359 of Mail/SpamAssassin/Plugin/AskDNS.pm | ||||
176 | 16 | 33µs | my($self, $arrref) = @_; | ||
177 | 16 | 54µs | my $conf = $self->{conf}; | ||
178 | |||||
179 | 16 | 160µs | 16 | 2.08ms | $self->set_defaults_from_command_list($arrref); # spent 2.08ms making 16 calls to Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list, avg 130µs/call |
180 | 16 | 126µs | 16 | 3.89ms | $self->build_command_luts($arrref); # spent 3.89ms making 16 calls to Mail::SpamAssassin::Conf::Parser::build_command_luts, avg 243µs/call |
181 | 48 | 414µs | push(@{$conf->{registered_commands}}, @{$arrref}); | ||
182 | } | ||||
183 | |||||
184 | # spent 2.08ms within Mail::SpamAssassin::Conf::Parser::set_defaults_from_command_list which was called 16 times, avg 130µs/call:
# 16 times (2.08ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 179, avg 130µs/call | ||||
185 | 16 | 44µs | my ($self, $arrref) = @_; | ||
186 | 16 | 40µs | my $conf = $self->{conf}; | ||
187 | 32 | 311µs | foreach my $cmd (@{$arrref}) { | ||
188 | # note! exists, not defined -- we want to be able to set | ||||
189 | # "undef" default values. | ||||
190 | 203 | 915µs | if (exists($cmd->{default})) { | ||
191 | 110 | 837µs | $conf->{$cmd->{setting}} = $cmd->{default}; | ||
192 | } | ||||
193 | } | ||||
194 | } | ||||
195 | |||||
196 | # spent 3.89ms within Mail::SpamAssassin::Conf::Parser::build_command_luts which was called 16 times, avg 243µs/call:
# 16 times (3.89ms+0s) by Mail::SpamAssassin::Conf::Parser::register_commands at line 180, avg 243µs/call | ||||
197 | 16 | 49µs | my ($self, $arrref) = @_; | ||
198 | |||||
199 | 16 | 51µs | my $conf = $self->{conf}; | ||
200 | |||||
201 | 16 | 26µs | my $set; | ||
202 | 32 | 312µs | foreach my $cmd (@{$arrref}) { | ||
203 | # first off, decide what set this is in. | ||||
204 | 210 | 674µs | if ($cmd->{is_frequent}) { $set = 'frequent'; } | ||
205 | 196 | 345µs | else { $set = 'remaining'; } | ||
206 | |||||
207 | # next, its priority (used to ensure frequently-used params | ||||
208 | # are parsed first) | ||||
209 | 203 | 441µs | my $cmdname = $cmd->{command} || $cmd->{setting}; | ||
210 | 203 | 1.33ms | $self->{command_luts}->{$set}->{$cmdname} = $cmd; | ||
211 | |||||
212 | 205 | 716µs | if ($cmd->{aliases} && scalar @{$cmd->{aliases}} > 0) { | ||
213 | 4 | 14µs | foreach my $name (@{$cmd->{aliases}}) { | ||
214 | 2 | 21µs | $self->{command_luts}->{$set}->{$name} = $cmd; | ||
215 | } | ||||
216 | } | ||||
217 | } | ||||
218 | } | ||||
219 | |||||
220 | ########################################################################### | ||||
221 | |||||
222 | # spent 4.55s (1.51+3.04) within Mail::SpamAssassin::Conf::Parser::parse which was called:
# once (1.51s+3.04s) by Mail::SpamAssassin::Conf::parse_rules at line 4623 of Mail/SpamAssassin/Conf.pm | ||||
223 | 1 | 4µ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 | 3µs | $lang ||= $ENV{'LC_MESSAGES'}; | ||
237 | 1 | 3µs | $lang ||= $ENV{'LANG'}; | ||
238 | 1 | 2µs | $lang ||= 'C'; # Nothing set means C/POSIX | ||
239 | |||||
240 | 1 | 20µs | 1 | 7µs | if ($lang =~ /^(C|POSIX)$/) { # spent 7µs making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:match |
241 | 1 | 2µ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 | 12µs | my %migrated_keys = map { $_ => 1 } | ||
250 | @Mail::SpamAssassin::Conf::MIGRATED_SETTINGS; | ||||
251 | |||||
252 | 1 | 3µ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 | 364µs | my @conf_lines = split (/\n/, $_[1]); | ||
257 | 1 | 2µs | my $line; | ||
258 | 1 | 4µs | $self->{if_stack} = \@if_stack; | ||
259 | 1 | 3µs | $self->{file_scoped_attrs} = { }; | ||
260 | |||||
261 | 1 | 3µs | my $keepmetadata = $conf->{main}->{keep_config_parsing_metadata}; | ||
262 | |||||
263 | 1 | 96.3ms | while (defined ($line = shift @conf_lines)) { | ||
264 | 16436 | 51.4ms | 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 | 177ms | 16436 | 43.2ms | if ($line =~ /^\# UPDATE version (\d+)$/) { # spent 43.2ms 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 | 12µs | $conf->{update_version}{$_} = $1 if defined $_ && $_ ne '(no file)'; | ||
276 | } | ||||
277 | } | ||||
278 | |||||
279 | 16436 | 205ms | 16436 | 66.5ms | $line =~ s/(?<!\\)#.*$//; # remove comments # spent 66.5ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call |
280 | 16436 | 182ms | 16436 | 32.3ms | $line =~ s/\\#/#/g; # hash chars are escaped, so unescape them # spent 32.3ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
281 | 16436 | 162ms | 16436 | 38.1ms | $line =~ s/^\s+//; # remove leading whitespace # spent 38.1ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
282 | 16436 | 201ms | 16436 | 58.9ms | $line =~ s/\s+$//; # remove tailing whitespace # spent 58.9ms making 16436 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call |
283 | 16436 | 37.3ms | next unless($line); # skip empty lines | ||
284 | |||||
285 | # handle i18n | ||||
286 | 10524 | 112ms | 11998 | 31.2ms | if ($line =~ s/^lang\s+(\S+)\s+//) { next if ($lang !~ /^$1/i); } # spent 21.5ms making 9050 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call
# spent 5.96ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 4µs/call
# spent 3.67ms making 1474 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
287 | |||||
288 | 7576 | 60.0ms | my($key, $value) = split(/\s+/, $line, 2); | ||
289 | 7576 | 18.2ms | $key = lc $key; | ||
290 | # convert all dashes in setting name to underscores. | ||||
291 | 7576 | 83.4ms | 7576 | 25.8ms | $key =~ s/-/_/g; # spent 25.8ms making 7576 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
292 | 7576 | 13.2ms | $value = '' unless defined($value); | ||
293 | |||||
294 | # # Do a better job untainting this info ... | ||||
295 | # # $value = untaint_var($value); | ||||
296 | # Do NOT blindly untaint now, do it carefully later when semantics is known! | ||||
297 | |||||
298 | 7576 | 11.8ms | my $parse_error; # undef by default, may be overridden | ||
299 | |||||
300 | # File/line number assertions | ||||
301 | 7576 | 13.8ms | if ($key eq 'file') { | ||
302 | 136 | 1.59ms | 136 | 675µs | if ($value =~ /^start\s+(.+)$/) { # spent 675µs making 136 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 5µs/call |
303 | 68 | 354µs | push (@curfile_stack, $self->{currentfile}); | ||
304 | 68 | 276µs | $self->{currentfile} = $1; | ||
305 | 68 | 307µs | next; | ||
306 | } | ||||
307 | |||||
308 | 68 | 880µs | 68 | 380µs | if ($value =~ /^end\s/) { # spent 380µs making 68 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 6µs/call |
309 | 68 | 335µs | $self->{file_scoped_attrs} = { }; | ||
310 | |||||
311 | 68 | 188µ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 | 141µs | $skip_parsing = 0; | ||
329 | |||||
330 | 68 | 301µs | my $curfile = pop @curfile_stack; | ||
331 | 68 | 294µs | if (defined $curfile) { | ||
332 | 68 | 225µs | $self->{currentfile} = $curfile; | ||
333 | } else { | ||||
334 | $self->{currentfile} = '(no file)'; | ||||
335 | } | ||||
336 | 68 | 287µs | next; | ||
337 | } | ||||
338 | } | ||||
339 | |||||
340 | # now handle the commands. | ||||
341 | 7440 | 12.5ms | if ($key eq 'include') { | ||
342 | 58 | 591µs | 58 | 30.0ms | $value = $self->fix_path_relative_to_current_file($value); # spent 30.0ms making 58 calls to Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file, avg 517µs/call |
343 | 58 | 759µs | 58 | 25.7ms | my $text = $conf->{main}->read_cf($value, 'included file'); # spent 25.7ms making 58 calls to Mail::SpamAssassin::read_cf, avg 444µs/call |
344 | 58 | 28.7ms | unshift (@conf_lines, split (/\n/, $text)); | ||
345 | 58 | 768µs | next; | ||
346 | } | ||||
347 | |||||
348 | 7382 | 12.4ms | if ($key eq 'ifplugin') { | ||
349 | 360 | 5.23ms | 360 | 120ms | $self->handle_conditional ($key, "plugin ($value)", # spent 120ms making 360 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 334µs/call |
350 | \@if_stack, \$skip_parsing); | ||||
351 | 360 | 1.48ms | next; | ||
352 | } | ||||
353 | |||||
354 | 7022 | 11.6ms | if ($key eq 'if') { | ||
355 | 148 | 1.64ms | 148 | 95.0ms | $self->handle_conditional ($key, $value, # spent 95.0ms making 148 calls to Mail::SpamAssassin::Conf::Parser::handle_conditional, avg 642µs/call |
356 | \@if_stack, \$skip_parsing); | ||||
357 | 148 | 669µs | next; | ||
358 | } | ||||
359 | |||||
360 | 6874 | 11.3ms | 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 | 8µs | next; | ||
369 | } | ||||
370 | |||||
371 | # and the endif statement: | ||||
372 | 6872 | 11.6ms | if ($key eq 'endif') { | ||
373 | 508 | 1.15ms | my $lastcond = pop @if_stack; | ||
374 | 508 | 836µs | if (!defined $lastcond) { | ||
375 | $parse_error = "config: found endif without matching conditional"; | ||||
376 | goto failed_line; | ||||
377 | } | ||||
378 | |||||
379 | 508 | 1.18ms | $skip_parsing = $lastcond->{skip_parsing}; | ||
380 | 508 | 3.71ms | next; | ||
381 | } | ||||
382 | |||||
383 | # preprocessing? skip all other commands | ||||
384 | 6364 | 10.3ms | next if $skip_parsing; | ||
385 | |||||
386 | 6184 | 10.2ms | if ($key eq 'require_version') { | ||
387 | # if it wasn't replaced during install, assume current version ... | ||||
388 | 17 | 52µs | next if ($value eq "\@\@VERSION\@\@"); | ||
389 | |||||
390 | 17 | 59µ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 | 37µ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 | 65µs | next; | ||
411 | } | ||||
412 | |||||
413 | 6167 | 15.1ms | my $cmd = $lut_frequent->{$key}; # check the frequent command set | ||
414 | 6167 | 13.9ms | if (!$cmd) { | ||
415 | 2208 | 5.17ms | $cmd = $lut_remaining->{$key}; # no? try the rest | ||
416 | } | ||||
417 | |||||
418 | # we've either fallen through with no match, in which case this | ||||
419 | # if() will fail, or we have a match. | ||||
420 | 6167 | 10.1ms | if ($cmd) { | ||
421 | 5666 | 10.2ms | if ($self->{scoresonly}) { # reading user config from spamd | ||
422 | if ($cmd->{is_priv} && !$conf->{allow_user_rules}) { | ||||
423 | info("config: not parsing, 'allow_user_rules' is 0: $line"); | ||||
424 | goto failed_line; | ||||
425 | } | ||||
426 | if ($cmd->{is_admin}) { | ||||
427 | info("config: not parsing, administrator setting: $line"); | ||||
428 | goto failed_line; | ||||
429 | } | ||||
430 | } | ||||
431 | |||||
432 | 5666 | 11.4ms | if (!$cmd->{code}) { | ||
433 | 21 | 158µs | 21 | 492µs | if (! $self->setup_default_code_cb($cmd)) { # spent 492µs making 21 calls to Mail::SpamAssassin::Conf::Parser::setup_default_code_cb, avg 23µs/call |
434 | goto failed_line; | ||||
435 | } | ||||
436 | } | ||||
437 | |||||
438 | 11332 | 65.9ms | 5666 | 2.05s | my $ret = &{$cmd->{code}} ($conf, $cmd->{setting}, $value, $line); # spent 555ms making 27 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:4145], avg 20.6ms/call
# spent 310ms making 465 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3174], avg 668µs/call
# spent 262ms making 1276 calls to Mail::SpamAssassin::Conf::Parser::set_hash_key_value, avg 206µs/call
# spent 250ms making 781 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2981], avg 320µs/call
# spent 218ms making 655 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3020], avg 333µs/call
# spent 146ms making 811 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:280], avg 180µs/call
# spent 98.5ms making 30 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1685], avg 3.28ms/call
# spent 43.9ms making 459 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3750], avg 96µs/call
# spent 38.4ms making 46 calls to Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[Mail/SpamAssassin/Plugin/MIMEHeader.pm:160], avg 834µs/call
# spent 26.2ms making 128 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3557], avg 205µs/call
# spent 23.7ms making 71 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3052], avg 334µs/call
# spent 15.7ms making 83 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:420], avg 189µs/call
# spent 13.2ms making 40 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3088], avg 331µs/call
# spent 11.1ms making 34 calls to Mail::SpamAssassin::Conf::Parser::set_addrlist_value, avg 327µs/call
# spent 5.13ms making 85 calls to Mail::SpamAssassin::Plugin::DKIM::__ANON__[Mail/SpamAssassin/Plugin/DKIM.pm:468], avg 60µs/call
# spent 5.03ms making 15 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2701], avg 336µs/call
# spent 4.91ms making 270 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:2044], avg 18µs/call
# spent 3.80ms making 21 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:662], avg 181µs/call
# spent 3.24ms making 63 calls to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:783], avg 51µs/call
# spent 3.17ms making 48 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3781], avg 66µs/call
# spent 2.77ms making 19 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:433], avg 146µs/call
# spent 2.71ms making 64 calls to Mail::SpamAssassin::Plugin::ReplaceTags::__ANON__[Mail/SpamAssassin/Plugin/ReplaceTags.pm:266], avg 42µs/call
# spent 2.64ms making 77 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3206], avg 34µs/call
# spent 1.89ms making 13 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3122], avg 145µs/call
# spent 1.17ms making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3804]
# spent 1.06ms making 5 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:935], avg 212µs/call
# spent 739µs making 2 calls to Mail::SpamAssassin::Plugin::AskDNS::__ANON__[Mail/SpamAssassin/Plugin/AskDNS.pm:356], avg 369µs/call
# spent 559µs making 17 calls to Mail::SpamAssassin::Conf::Parser::set_template_append, avg 33µs/call
# spent 425µs making 4 calls to Mail::SpamAssassin::Conf::Parser::set_numeric_value, avg 106µs/call
# spent 297µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:609]
# spent 231µs making 5 calls to Mail::SpamAssassin::Conf::Parser::set_bool_value, avg 46µs/call
# spent 201µs making 2 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1419], avg 101µs/call
# spent 173µs making 36 calls to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3402], avg 5µs/call
# spent 89µs making 3 calls to Mail::SpamAssassin::Conf::Parser::set_string_value, avg 30µs/call
# spent 78µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3835]
# spent 78µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::__ANON__[Mail/SpamAssassin/Plugin/URIDNSBL.pm:581]
# spent 77µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:3858]
# spent 50µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1007]
# spent 46µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1054]
# spent 45µs making 2 calls to Mail::SpamAssassin::Conf::Parser::set_template_clear, avg 23µs/call
# spent 27µs making 1 call to Mail::SpamAssassin::Plugin::TxRep::__ANON__[Mail/SpamAssassin/Plugin/TxRep.pm:495]
# spent 24µs making 1 call to Mail::SpamAssassin::Conf::__ANON__[Mail/SpamAssassin/Conf.pm:1437] |
439 | |||||
440 | 5666 | 12.3ms | if ($ret && $ret eq $Mail::SpamAssassin::Conf::INVALID_VALUE) | ||
441 | { | ||||
442 | $parse_error = "config: SpamAssassin failed to parse line, ". | ||||
443 | "\"$value\" is not valid for \"$key\", ". | ||||
444 | "skipping: $line"; | ||||
445 | goto failed_line; | ||||
446 | } | ||||
447 | elsif ($ret && $ret eq $Mail::SpamAssassin::Conf::INVALID_HEADER_FIELD_NAME) | ||||
448 | { | ||||
449 | $parse_error = "config: SpamAssassin failed to parse line, ". | ||||
450 | "it does not specify a valid header field name, ". | ||||
451 | "skipping: $line"; | ||||
452 | goto failed_line; | ||||
453 | } | ||||
454 | elsif ($ret && $ret eq $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE) | ||||
455 | { | ||||
456 | $parse_error = "config: SpamAssassin failed to parse line, ". | ||||
457 | "no value provided for \"$key\", ". | ||||
458 | "skipping: $line"; | ||||
459 | goto failed_line; | ||||
460 | } | ||||
461 | else { | ||||
462 | 5666 | 29.2ms | next; | ||
463 | } | ||||
464 | } | ||||
465 | |||||
466 | # last ditch: try to see if the plugins know what to do with it | ||||
467 | 501 | 5.55ms | 501 | 155ms | if ($conf->{main}->call_plugins("parse_config", { # spent 155ms making 501 calls to Mail::SpamAssassin::call_plugins, avg 310µs/call |
468 | key => $key, | ||||
469 | value => $value, | ||||
470 | line => $line, | ||||
471 | conf => $conf, | ||||
472 | user_config => $self->{scoresonly} | ||||
473 | })) | ||||
474 | { | ||||
475 | # a plugin dealt with it successfully. | ||||
476 | 501 | 3.47ms | 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 | 12µs | 1 | 12µs | $self->lint_check(); # spent 12µs making 1 call to Mail::SpamAssassin::Conf::Parser::lint_check |
500 | 1 | 9µs | 1 | 121ms | $self->set_default_scores(); # spent 121ms making 1 call to Mail::SpamAssassin::Conf::Parser::set_default_scores |
501 | 1 | 15µs | 1 | 139ms | $self->check_for_missing_descriptions(); # spent 139ms making 1 call to Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions |
502 | |||||
503 | 1 | 22µs | delete $self->{scoresonly}; | ||
504 | } | ||||
505 | |||||
506 | # spent 215ms (148+66.8) within Mail::SpamAssassin::Conf::Parser::handle_conditional which was called 508 times, avg 424µs/call:
# 360 times (79.3ms+40.9ms) by Mail::SpamAssassin::Conf::Parser::parse at line 349, avg 334µs/call
# 148 times (69.1ms+25.9ms) by Mail::SpamAssassin::Conf::Parser::parse at line 355, avg 642µs/call | ||||
507 | 508 | 2.52ms | my ($self, $key, $value, $if_stack_ref, $skip_parsing_ref) = @_; | ||
508 | 508 | 1.23ms | my $conf = $self->{conf}; | ||
509 | |||||
510 | 508 | 966µs | my $lexer = ARITH_EXPRESSION_LEXER; | ||
511 | 508 | 19.3ms | 1016 | 10.0ms | my @tokens = ($value =~ m/($lexer)/g); # spent 7.17ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 14µs/call
# spent 2.84ms making 508 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 6µs/call |
512 | |||||
513 | 508 | 1.12ms | my $eval = ''; | ||
514 | 508 | 858µs | my $bad = 0; | ||
515 | 508 | 2.01ms | foreach my $token (@tokens) { | ||
516 | 2161 | 51.6ms | 2650 | 10.3ms | if ($token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/) { # spent 10.3ms making 2650 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 4µs/call |
517 | # using tainted subr. argument may taint the whole expression, avoid | ||||
518 | 1164 | 7.75ms | 1164 | 26.8ms | my $u = untaint_var($token); # spent 26.8ms making 1164 calls to Mail::SpamAssassin::Util::untaint_var, avg 23µs/call |
519 | 1164 | 2.63ms | $eval .= $u . " "; | ||
520 | } | ||||
521 | elsif ($token eq 'plugin') { | ||||
522 | # replace with a method call | ||||
523 | 434 | 808µs | $eval .= '$self->cond_clause_plugin_loaded'; | ||
524 | } | ||||
525 | elsif ($token eq 'can') { | ||||
526 | # replace with a method call | ||||
527 | 55 | 131µ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 | 58µ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.24ms | 489 | 10.7ms | my $u = untaint_var($token); # spent 10.7ms making 489 calls to Mail::SpamAssassin::Util::untaint_var, avg 22µs/call |
541 | 489 | 1.26ms | $eval .= '"' . $u . '" '; | ||
542 | } | ||||
543 | else { | ||||
544 | $bad++; | ||||
545 | warn "config: unparseable chars in 'if $value': '$token'\n"; | ||||
546 | } | ||||
547 | } | ||||
548 | |||||
549 | 508 | 908µs | if ($bad) { | ||
550 | $self->lint_warn("bad 'if' line, in \"$self->{currentfile}\"", undef); | ||||
551 | return -1; | ||||
552 | } | ||||
553 | |||||
554 | 1016 | 5.07ms | push (@{$if_stack_ref}, { | ||
555 | type => 'if', | ||||
556 | conditional => $value, | ||||
557 | skip_parsing => $$skip_parsing_ref | ||||
558 | }); | ||||
559 | |||||
560 | 508 | 33.3ms | if (eval $eval) { # spent 831µs executing statements in 72 string evals (merged)
# spent 655µs executing statements in 59 string evals (merged)
# spent 498µs executing statements in 41 string evals (merged)
# spent 305µs executing statements in 26 string evals (merged)
# spent 296µs executing statements in 25 string evals (merged)
# spent 264µs executing statements in 20 string evals (merged)
# spent 232µs executing statements in 21 string evals (merged)
# spent 172µs executing statements in 14 string evals (merged)
# spent 169µs executing statements in 15 string evals (merged)
# spent 155µs executing statements in 13 string evals (merged)
# spent 149µs executing statements in 12 string evals (merged)
# spent 142µs executing statements in 11 string evals (merged)
# spent 141µs executing statements in 11 string evals (merged)
# spent 113µs executing statements in 8 string evals (merged)
# spent 112µs executing statements in 7 string evals (merged)
# spent 93µs executing statements in 7 string evals (merged)
# spent 91µs executing statements in 7 string evals (merged)
# spent 90µs executing statements in 7 string evals (merged)
# spent 87µs executing statements in 6 string evals (merged)
# spent 87µs executing statements in 6 string evals (merged)
# spent 82µs executing statements in 7 string evals (merged)
# spent 76µs executing statements in 6 string evals (merged)
# spent 73µs executing statements in 5 string evals (merged)
# spent 71µs executing statements in 5 string evals (merged)
# spent 71µs executing statements in 5 string evals (merged)
# spent 70µs executing statements in 7 string evals (merged)
# spent 70µs executing statements in 12 string evals (merged)
# spent 61µs executing statements in 5 string evals (merged)
# spent 56µs executing statements in 5 string evals (merged)
# spent 53µs executing statements in 4 string evals (merged)
# spent 48µs executing statements in 4 string evals (merged)
# spent 44µs executing statements in 4 string evals (merged)
# spent 44µs executing statements in 3 string evals (merged)
# spent 40µs executing statements in 3 string evals (merged)
# spent 38µs executing statements in 3 string evals (merged)
# spent 32µs executing statements in 3 string evals (merged)
# spent 30µs executing statements in 2 string evals (merged)
# spent 29µs executing statements in 2 string evals (merged)
# spent 29µs executing statements in 2 string evals (merged)
# spent 29µs executing statements in 2 string evals (merged)
# spent 28µs executing statements in 2 string evals (merged)
# spent 26µs executing statements in 2 string evals (merged)
# spent 26µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 23µs executing statements in 2 string evals (merged)
# spent 22µs executing statements in 2 string evals (merged)
# spent 17µs executing statements in string eval
# spent 16µs executing statements in 3 string evals (merged)
# spent 16µs executing statements in string eval
# spent 14µs executing statements in string eval
# spent 13µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in 2 string evals (merged)
# spent 11µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 6µs executing statements in string eval | ||
561 | # leave $skip_parsing as-is; we may not be parsing anyway in this block. | ||||
562 | # in other words, support nested 'if's and 'require_version's | ||||
563 | } else { | ||||
564 | 127 | 346µs | warn "config: error in $key - $eval: $@" if $@ ne ''; | ||
565 | 127 | 266µs | $$skip_parsing_ref = 1; | ||
566 | } | ||||
567 | } | ||||
568 | |||||
569 | # functions supported in the "if" eval: | ||||
570 | # spent 3.93ms within Mail::SpamAssassin::Conf::Parser::cond_clause_plugin_loaded which was called 434 times, avg 9µs/call:
# 72 times (567µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 119)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 59 times (525µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 287)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 41 times (382µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 132)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 26 times (206µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 823)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 25 times (213µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 154)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 20 times (185µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 742)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 15 times (128µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 289)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 14 times (168µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 128)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call
# 13 times (90µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 126)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 7µs/call
# 12 times (99µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 279)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 11 times (121µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 201)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call
# 11 times (108µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 170)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 8 times (68µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 115)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 7 times (68µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 278)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 7 times (67µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 274)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 7 times (66µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 275)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 7 times (55µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 754)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 7 times (45µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 276)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call
# 6 times (50µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 523)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 6 times (49µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 285)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 5 times (60µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 296)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 12µs/call
# 5 times (46µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 207)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 9µs/call
# 5 times (42µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 473)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 5 times (38µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 335)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 8µs/call
# 4 times (60µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 347)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 15µs/call
# 4 times (57µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 284)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 14µs/call
# 4 times (23µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 945)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call
# 3 times (49µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 131)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 16µs/call
# 3 times (18µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 304)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call
# 2 times (33µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 129)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 16µs/call
# 2 times (29µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 133)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 15µs/call
# 2 times (26µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 363)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 13µs/call
# 2 times (25µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 348)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 13µs/call
# 2 times (22µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 925)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 11µs/call
# 2 times (21µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 261)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 2 times (20µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 286)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 10µs/call
# 2 times (11µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1007)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 6µs/call
# once (18µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 942)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (18µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 277)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (16µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 372)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (16µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1062)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (11µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 116)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (6µs+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 231)[Mail/SpamAssassin/Conf/Parser.pm:560] | ||||
571 | 434 | 9.10ms | return $_[0]->{conf}->{plugins_loaded}->{$_[1]}; | ||
572 | } | ||||
573 | |||||
574 | # spent 5.01ms (829µs+4.18) within Mail::SpamAssassin::Conf::Parser::cond_clause_can which was called 55 times, avg 91µs/call:
# 21 times (274µs+1.45ms) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 634)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 82µs/call
# 7 times (124µs+534µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 932)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 94µs/call
# 6 times (85µs+492µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 718)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 96µs/call
# 5 times (72µs+378µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 290)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 90µs/call
# 3 times (39µs+252µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 940)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 97µs/call
# 3 times (47µs+222µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 947)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 90µs/call
# 2 times (43µs+175µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 531)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 109µs/call
# 2 times (29µs+154µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 120)[Mail/SpamAssassin/Conf/Parser.pm:560], avg 91µs/call
# once (16µs+108µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 117)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (20µs+89µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 114)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (23µs+85µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 299)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (21µs+82µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 529)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (20µs+81µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 1075)[Mail/SpamAssassin/Conf/Parser.pm:560]
# once (17µs+80µs) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 1 of (eval 118)[Mail/SpamAssassin/Conf/Parser.pm:560] | ||||
575 | 55 | 133µs | my ($self, $method) = @_; | ||
576 | 55 | 1.14ms | 55 | 4.18ms | $self->cond_clause_can_or_has('can', $method); # spent 4.18ms making 55 calls to Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has, avg 76µs/call |
577 | } | ||||
578 | |||||
579 | sub cond_clause_has { | ||||
580 | my ($self, $method) = @_; | ||||
581 | $self->cond_clause_can_or_has('has', $method); | ||||
582 | } | ||||
583 | |||||
584 | # spent 4.18ms (2.61+1.57) within Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has which was called 55 times, avg 76µs/call:
# 55 times (2.61ms+1.57ms) by Mail::SpamAssassin::Conf::Parser::cond_clause_can at line 576, avg 76µs/call | ||||
585 | 55 | 126µs | my ($self, $fn_name, $method) = @_; | ||
586 | |||||
587 | 55 | 297µs | local($1,$2); | ||
588 | 55 | 902µs | 55 | 422µs | if (!defined $method) { # spent 422µs making 55 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 8µs/call |
589 | $self->lint_warn("bad 'if' line, no argument to $fn_name(), ". | ||||
590 | "in \"$self->{currentfile}\"", undef); | ||||
591 | } elsif ($method =~ /^(.*)::([^:]+)$/) { | ||||
592 | 2 | 10.9ms | 2 | 154µs | # spent 98µs (42+56) within Mail::SpamAssassin::Conf::Parser::BEGIN@592 which was called:
# once (42µs+56µs) by Mail::SpamAssassin::Conf::BEGIN@88 at line 592 # spent 98µs making 1 call to Mail::SpamAssassin::Conf::Parser::BEGIN@592
# spent 56µs making 1 call to strict::unimport |
593 | 55 | 263µs | my($module, $meth) = ($1, $2); | ||
594 | return 1 if UNIVERSAL::can($module,$meth) && | ||||
595 | 110 | 2.24ms | 110 | 1.15ms | ( $fn_name eq 'has' || &{$method}() ); # spent 594µs making 55 calls to UNIVERSAL::can, avg 11µs/call
# spent 219µs making 24 calls to Mail::SpamAssassin::Conf::feature_bug6558_free, avg 9µs/call
# spent 99µs making 10 calls to Mail::SpamAssassin::Plugin::BodyEval::has_check_body_length, avg 10µs/call
# spent 82µs making 7 calls to Mail::SpamAssassin::Conf::perl_min_version_5010000, avg 12µs/call
# spent 46µs making 5 calls to Mail::SpamAssassin::Plugin::SPF::has_check_for_spf_errors, avg 9µs/call
# spent 29µs making 2 calls to Mail::SpamAssassin::Plugin::MIMEEval::has_check_abundant_unicode_ratio, avg 14µs/call
# spent 17µs making 2 calls to Mail::SpamAssassin::Conf::feature_registryboundaries, avg 8µs/call
# spent 16µs making 1 call to Mail::SpamAssassin::Conf::feature_originating_ip_headers
# spent 16µs making 1 call to Mail::SpamAssassin::Conf::feature_dns_local_ports_permit_avoid
# spent 10µs making 1 call to Mail::SpamAssassin::Plugin::MIMEEval::has_check_for_ascii_text_illegal
# spent 9µs making 1 call to Mail::SpamAssassin::Plugin::URIDNSBL::has_tflags_domains_only
# spent 8µs making 1 call to Mail::SpamAssassin::Conf::feature_yesno_takes_args |
596 | } else { | ||||
597 | $self->lint_warn("bad 'if' line, cannot find '::' in $fn_name($method), ". | ||||
598 | "in \"$self->{currentfile}\"", undef); | ||||
599 | } | ||||
600 | return; | ||||
601 | } | ||||
602 | |||||
603 | # Let's do some linting here ... | ||||
604 | # This is called from _parse(), BTW, so we can check for $conf->{tests} | ||||
605 | # easily before finish_parsing() is called and deletes it. | ||||
606 | # | ||||
607 | # spent 12µs within Mail::SpamAssassin::Conf::Parser::lint_check which was called:
# once (12µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 499 | ||||
608 | 1 | 2µs | my ($self) = @_; | ||
609 | 1 | 3µs | my $conf = $self->{conf}; | ||
610 | |||||
611 | 1 | 11µs | if ($conf->{lint_rules}) { | ||
612 | # Check for description and score issues in lint fashion | ||||
613 | while ( my $k = each %{$conf->{descriptions}} ) { | ||||
614 | if (!exists $conf->{tests}->{$k}) { | ||||
615 | $self->lint_warn("config: warning: description exists for non-existent rule $k\n", $k); | ||||
616 | } | ||||
617 | } | ||||
618 | |||||
619 | while ( my($sk) = each %{$conf->{scores}} ) { | ||||
620 | if (!exists $conf->{tests}->{$sk}) { | ||||
621 | # bug 5514: not a lint warning any more | ||||
622 | dbg("config: warning: score set for non-existent rule $sk"); | ||||
623 | } | ||||
624 | } | ||||
625 | } | ||||
626 | } | ||||
627 | |||||
628 | # we should set a default score for all valid rules... Do this here | ||||
629 | # instead of add_test because mostly 'score' occurs after the rule is | ||||
630 | # specified, so why set the scores to default, then set them again at | ||||
631 | # 'score'? | ||||
632 | # | ||||
633 | # spent 121ms (116+4.70) within Mail::SpamAssassin::Conf::Parser::set_default_scores which was called:
# once (116ms+4.70ms) by Mail::SpamAssassin::Conf::Parser::parse at line 500 | ||||
634 | 1 | 2µs | my ($self) = @_; | ||
635 | 1 | 3µs | my $conf = $self->{conf}; | ||
636 | |||||
637 | 2069 | 33.6ms | while ( my $k = each %{$conf->{tests}} ) { | ||
638 | 2067 | 6.07ms | if ( ! exists $conf->{scores}->{$k} ) { | ||
639 | # T_ rules (in a testing probationary period) get low, low scores | ||||
640 | 1284 | 19.0ms | 1284 | 2.52ms | my $set_score = ($k =~/^T_/) ? 0.01 : 1.0; # spent 2.52ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
641 | |||||
642 | 1284 | 12.3ms | 1284 | 2.18ms | $set_score = -$set_score if ( ($conf->{tflags}->{$k}||'') =~ /\bnice\b/ ); # spent 2.18ms making 1284 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
643 | 1284 | 4.89ms | for my $index (0..3) { | ||
644 | 5136 | 45.1ms | $conf->{scoreset}->[$index]->{$k} = $set_score; | ||
645 | } | ||||
646 | } | ||||
647 | } | ||||
648 | } | ||||
649 | |||||
650 | # loop through all the tests and if we are missing a description with debug | ||||
651 | # set, throw a warning except for testing T_ or meta __ rules. | ||||
652 | # spent 139ms (59.5+79.1) within Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions which was called:
# once (59.5ms+79.1ms) by Mail::SpamAssassin::Conf::Parser::parse at line 501 | ||||
653 | 1 | 3µs | my ($self) = @_; | ||
654 | 1 | 4µs | my $conf = $self->{conf}; | ||
655 | |||||
656 | 2069 | 23.9ms | while ( my $k = each %{$conf->{tests}} ) { | ||
657 | 2067 | 24.7ms | 2067 | 5.74ms | if ($k !~ m/^(?:T_|__)/i) { # spent 5.74ms making 2067 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
658 | 815 | 6.96ms | 815 | 72.8ms | if ( ! exists $conf->{descriptions}->{$k} ) { # spent 72.8ms making 815 calls to Mail::SpamAssassin::Util::TieOneStringHash::EXISTS, avg 89µs/call |
659 | 69 | 503µs | 69 | 474µs | dbg("config: warning: no description set for $k"); # spent 474µs making 69 calls to Mail::SpamAssassin::Logger::dbg, avg 7µs/call |
660 | } | ||||
661 | } | ||||
662 | } | ||||
663 | } | ||||
664 | |||||
665 | ########################################################################### | ||||
666 | |||||
667 | # spent 492µs within Mail::SpamAssassin::Conf::Parser::setup_default_code_cb which was called 21 times, avg 23µs/call:
# 21 times (492µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 433, avg 23µs/call | ||||
668 | 21 | 41µs | my ($self, $cmd) = @_; | ||
669 | 21 | 166µs | my $type = $cmd->{type}; | ||
670 | |||||
671 | 21 | 111µ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 | 169µ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 425µs (202+223) within Mail::SpamAssassin::Conf::Parser::set_numeric_value which was called 4 times, avg 106µs/call:
# 4 times (202µs+223µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 106µs/call | ||||
717 | 4 | 25µs | my ($conf, $key, $value, $line) = @_; | ||
718 | |||||
719 | 4 | 39µ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 | 67µs | 4 | 39µs | unless ($value =~ /^ [+-]? \d+ (?: \. \d* )? \z/sx) { # spent 39µs making 4 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 10µs/call |
723 | return $Mail::SpamAssassin::Conf::INVALID_VALUE; | ||||
724 | } | ||||
725 | # it is safe to untaint now that we know the syntax is a valid number | ||||
726 | 4 | 85µs | 4 | 172µs | $conf->{$key} = untaint_var($value) + 0; # spent 172µs making 4 calls to Mail::SpamAssassin::Util::untaint_var, avg 43µs/call |
727 | } | ||||
728 | |||||
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 231µs (217+14) within Mail::SpamAssassin::Conf::Parser::set_bool_value which was called 5 times, avg 46µs/call:
# 5 times (217µs+14µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 46µs/call | ||||
747 | 5 | 43µs | my ($conf, $key, $value, $line) = @_; | ||
748 | |||||
749 | 5 | 47µs | 5 | 14µs | unless (defined $value && $value !~ /^$/) { # spent 14µs making 5 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
750 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
751 | } | ||||
752 | |||||
753 | # bug 4462: allow yes/1 and no/0 for boolean values | ||||
754 | 5 | 14µs | $value = lc $value; | ||
755 | 5 | 26µ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 | 56µs | $conf->{$key} = $value; | ||
766 | } | ||||
767 | |||||
768 | # spent 89µs (80+9) within Mail::SpamAssassin::Conf::Parser::set_string_value which was called 3 times, avg 30µs/call:
# 3 times (80µs+9µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 30µs/call | ||||
769 | 3 | 17µs | my ($conf, $key, $value, $line) = @_; | ||
770 | |||||
771 | 3 | 32µs | 3 | 9µs | unless (defined $value && $value !~ /^$/) { # spent 9µs making 3 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
772 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
773 | } | ||||
774 | |||||
775 | 3 | 34µ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 262ms (48.8+214) within Mail::SpamAssassin::Conf::Parser::set_hash_key_value which was called 1276 times, avg 206µs/call:
# 1276 times (48.8ms+214ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 206µs/call | ||||
802 | 1276 | 6.49ms | my ($conf, $key, $value, $line) = @_; | ||
803 | 1276 | 8.39ms | my($k,$v) = split(/\s+/, $value, 2); | ||
804 | |||||
805 | 1276 | 2.62ms | unless (defined $v && $v ne '') { | ||
806 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
807 | } | ||||
808 | |||||
809 | 1276 | 30.4ms | 1684 | 214ms | $conf->{$key}->{$k} = $v; # keep tainted # spent 124ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::STORE, avg 147µs/call
# spent 89.7ms making 842 calls to Mail::SpamAssassin::Util::TieOneStringHash::FETCH, avg 107µs/call |
810 | } | ||||
811 | |||||
812 | # spent 11.1ms (912µs+10.2) within Mail::SpamAssassin::Conf::Parser::set_addrlist_value which was called 34 times, avg 327µs/call:
# 34 times (912µs+10.2ms) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 327µs/call | ||||
813 | 34 | 170µs | my ($conf, $key, $value, $line) = @_; | ||
814 | |||||
815 | 34 | 310µs | 34 | 98µs | unless (defined $value && $value !~ /^$/) { # spent 98µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
816 | return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; | ||||
817 | } | ||||
818 | 34 | 479µs | 34 | 10.1ms | $conf->{parser}->add_to_addrlist ($key, split (' ', $value)); # keep tainted # spent 10.1ms making 34 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist, avg 297µs/call |
819 | } | ||||
820 | |||||
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 559µs (512+48) within Mail::SpamAssassin::Conf::Parser::set_template_append which was called 17 times, avg 33µs/call:
# 17 times (512µs+48µs) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 33µs/call | ||||
831 | 17 | 211µs | my ($conf, $key, $value, $line) = @_; | ||
832 | 18 | 157µs | 17 | 48µs | if ( $value =~ /^"(.*?)"$/ ) { $value = $1; } # spent 48µs making 17 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
833 | 17 | 201µs | $conf->{$key} .= $value."\n"; # keep tainted | ||
834 | } | ||||
835 | |||||
836 | # spent 45µs within Mail::SpamAssassin::Conf::Parser::set_template_clear which was called 2 times, avg 23µs/call:
# 2 times (45µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 438, avg 23µs/call | ||||
837 | 2 | 19µs | my ($conf, $key, $value, $line) = @_; | ||
838 | 2 | 5µs | unless (!defined $value || $value eq '') { | ||
839 | return $Mail::SpamAssassin::Conf::INVALID_VALUE; | ||||
840 | } | ||||
841 | 2 | 20µs | $conf->{$key} = ''; | ||
842 | } | ||||
843 | |||||
844 | ########################################################################### | ||||
845 | |||||
846 | # spent 6.05s (95.7ms+5.95) within Mail::SpamAssassin::Conf::Parser::finish_parsing which was called:
# once (95.7ms+5.95s) by Mail::SpamAssassin::Conf::finish_parsing at line 4860 of Mail/SpamAssassin/Conf.pm | ||||
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 | 853µs | $conf->{main}->call_plugins("finish_parsing_start", { conf => $conf }); # spent 853µs making 1 call to Mail::SpamAssassin::call_plugins |
854 | } else { | ||||
855 | $conf->{main}->call_plugins("user_conf_parsing_start", { conf => $conf }); | ||||
856 | } | ||||
857 | |||||
858 | 1 | 352µs | 1 | 5.54s | $self->trace_meta_dependencies(); # spent 5.54s making 1 call to Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies |
859 | 1 | 359µs | 1 | 125ms | $self->fix_priorities(); # spent 125ms making 1 call to Mail::SpamAssassin::Conf::Parser::fix_priorities |
860 | |||||
861 | # don't do this if allow_user_rules is active, since it deletes entries | ||||
862 | # from {tests} | ||||
863 | 1 | 12µs | if (!$conf->{allow_user_rules}) { | ||
864 | 1 | 20µs | 1 | 98.0ms | $self->find_dup_rules(); # must be after fix_priorities() # spent 98.0ms making 1 call to Mail::SpamAssassin::Conf::Parser::find_dup_rules |
865 | } | ||||
866 | |||||
867 | 1 | 8µs | 1 | 8µs | dbg("config: finish parsing"); # spent 8µs making 1 call to Mail::SpamAssassin::Logger::dbg |
868 | |||||
869 | 2058 | 36.5ms | while (my ($name, $text) = each %{$conf->{tests}}) { | ||
870 | 2056 | 4.41ms | my $type = $conf->{test_types}->{$name}; | ||
871 | 2056 | 6.32ms | my $priority = $conf->{priority}->{$name} || 0; | ||
872 | 2056 | 3.89ms | $conf->{priorities}->{$priority}++; | ||
873 | |||||
874 | # eval type handling | ||||
875 | 2056 | 6.91ms | if (($type & 1) == 1) { | ||
876 | 379 | 9.33ms | 379 | 4.76ms | if (my ($function, $args) = ($text =~ m/(.*?)\s*\((.*?)\)\s*$/)) { # spent 4.76ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 13µs/call |
877 | 379 | 2.96ms | 379 | 42.2ms | my ($packed, $argsref) = # spent 42.2ms making 379 calls to Mail::SpamAssassin::Conf::Parser::pack_eval_method, avg 111µs/call |
878 | $self->pack_eval_method($function, $args, $name, $text); | ||||
879 | |||||
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.68ms | $conf->{body_evals}->{$priority}->{$name} = $packed; | ||
885 | } | ||||
886 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_EVALS) { | ||||
887 | 101 | 986µ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 | 924µs | $conf->{rbl_evals}->{$name} = [ $function, @$argsref ]; | ||
893 | } | ||||
894 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_EVALS) { | ||||
895 | 7 | 63µs | $conf->{rawbody_evals}->{$priority}->{$name} = $packed; | ||
896 | } | ||||
897 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_EVALS) { | ||||
898 | 11 | 62µ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.58ms | if ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS) { | ||
914 | 513 | 4.72ms | $conf->{body_tests}->{$priority}->{$name} = $text; | ||
915 | } | ||||
916 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS) { | ||||
917 | 595 | 5.50ms | $conf->{head_tests}->{$priority}->{$name} = $text; | ||
918 | } | ||||
919 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) { | ||||
920 | 463 | 4.15ms | $conf->{meta_tests}->{$priority}->{$name} = $text; | ||
921 | } | ||||
922 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS) { | ||||
923 | 69 | 631µs | $conf->{uri_tests}->{$priority}->{$name} = $text; | ||
924 | } | ||||
925 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS) { | ||||
926 | 33 | 319µs | $conf->{rawbody_tests}->{$priority}->{$name} = $text; | ||
927 | } | ||||
928 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS) { | ||||
929 | 2 | 8µ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 | 5µs | if (!$isuserconf) { | ||
942 | 1 | 15µs | 1 | 137ms | $conf->{main}->call_plugins("finish_parsing_end", { conf => $conf }); # spent 137ms making 1 call to Mail::SpamAssassin::call_plugins |
943 | } else { | ||||
944 | $conf->{main}->call_plugins("user_conf_parsing_end", { conf => $conf }); | ||||
945 | } | ||||
946 | |||||
947 | 1 | 12µs | 1 | 24µs | $conf->found_any_rules(); # before we might delete {tests} # spent 24µs making 1 call to Mail::SpamAssassin::Conf::found_any_rules |
948 | |||||
949 | 1 | 22µs | if (!$conf->{allow_user_rules}) { | ||
950 | # free up stuff we no longer need | ||||
951 | 1 | 1.83ms | delete $conf->{tests}; | ||
952 | 1 | 546µs | delete $conf->{priority}; | ||
953 | #test_types are needed - see bug 5503 | ||||
954 | #delete $conf->{test_types}; | ||||
955 | } | ||||
956 | } | ||||
957 | |||||
958 | # spent 5.54s (30.7ms+5.51) within Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies which was called:
# once (30.7ms+5.51s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 858 | ||||
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.14ms | foreach my $name (keys %{$conf->{tests}}) { | ||
964 | 2067 | 9.47ms | next unless ($conf->{test_types}->{$name} | ||
965 | == $Mail::SpamAssassin::Conf::TYPE_META_TESTS); | ||||
966 | |||||
967 | 464 | 970µs | my $deps = [ ]; | ||
968 | 464 | 843µs | my $alreadydone = { }; | ||
969 | 464 | 3.05ms | 464 | 5.51s | $self->_meta_deps_recurse($conf, $name, $name, $deps, $alreadydone); # spent 5.51s making 464 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 11.9ms/call |
970 | 928 | 12.7ms | $conf->{meta_dependencies}->{$name} = join (' ', @{$deps}); | ||
971 | } | ||||
972 | } | ||||
973 | |||||
974 | # spent 5.51s (4.04+1.47) within Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse which was called 13832 times, avg 398µs/call:
# 13368 times (3.87s+-3.87s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 1000, avg 0s/call
# 464 times (166ms+5.34s) by Mail::SpamAssassin::Conf::Parser::trace_meta_dependencies at line 969, avg 11.9ms/call | ||||
975 | 13832 | 29.6ms | my ($self, $conf, $toprule, $name, $deps, $alreadydone) = @_; | ||
976 | |||||
977 | # Only do each rule once per top-level meta; avoid infinite recursion | ||||
978 | 13832 | 52.8ms | return if $alreadydone->{$name}; | ||
979 | 11323 | 64.4ms | $alreadydone->{$name} = 1; | ||
980 | |||||
981 | # Obviously, don't trace empty or nonexistent rules | ||||
982 | 11323 | 52.5ms | my $rule = $conf->{tests}->{$name}; | ||
983 | 11323 | 19.1ms | return unless $rule; | ||
984 | |||||
985 | # Lex the rule into tokens using a rather simple RE method ... | ||||
986 | 11321 | 18.6ms | my $lexer = ARITH_EXPRESSION_LEXER; | ||
987 | 11321 | 779ms | 22642 | 505ms | my @tokens = ($rule =~ m/$lexer/g); # spent 463ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 41µs/call
# spent 42.1ms making 11321 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 4µs/call |
988 | |||||
989 | # Go through each token in the meta rule | ||||
990 | 11321 | 21.5ms | my $conf_tests = $conf->{tests}; | ||
991 | 11321 | 597ms | foreach my $token (@tokens) { | ||
992 | # has to be an alpha+numeric token | ||||
993 | # next if $token =~ /^(?:\W+|[+-]?\d+(?:\.\d+)?)$/; | ||||
994 | 269448 | 2.70s | 269448 | 614ms | next if $token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s; # faster # spent 614ms making 269448 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
995 | # and has to be a rule name | ||||
996 | 120401 | 533ms | next unless exists $conf_tests->{$token}; | ||
997 | |||||
998 | # add and recurse | ||||
999 | 26736 | 137ms | 13368 | 353ms | push(@{$deps}, untaint_var($token)); # spent 353ms making 13368 calls to Mail::SpamAssassin::Util::untaint_var, avg 26µs/call |
1000 | 13368 | 110ms | 13368 | 0s | $self->_meta_deps_recurse($conf, $toprule, $token, $deps, $alreadydone); # spent 11.1s making 13368 calls to Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse, avg 831µs/call, recursion: max depth 7, sum of overlapping time 11.1s |
1001 | } | ||||
1002 | } | ||||
1003 | |||||
1004 | # spent 125ms (105+20.0) within Mail::SpamAssassin::Conf::Parser::fix_priorities which was called:
# once (105ms+20.0ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 859 | ||||
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 | 3.08ms | 1 | 20.0ms | foreach my $rule (sort { # spent 20.0ms making 1 call to Mail::SpamAssassin::Conf::Parser::CORE:sort |
1015 | 9742 | 20.0ms | $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.51ms | my $deps = $conf->{meta_dependencies}->{$rule}; | ||
1021 | 2067 | 3.31ms | next unless (defined $deps); | ||
1022 | |||||
1023 | 464 | 1.51ms | my $basepri = $pri->{$rule}; | ||
1024 | 464 | 12.0ms | foreach my $dep (split ' ', $deps) { | ||
1025 | 13368 | 32.3ms | my $deppri = $pri->{$dep}; | ||
1026 | 13368 | 46.5ms | if ($deppri > $basepri) { | ||
1027 | dbg("rules: $rule (pri $basepri) requires $dep (pri $deppri): fixed"); | ||||
1028 | $pri->{$dep} = $basepri; | ||||
1029 | } | ||||
1030 | } | ||||
1031 | } | ||||
1032 | } | ||||
1033 | |||||
1034 | # spent 98.0ms (94.5+3.52) within Mail::SpamAssassin::Conf::Parser::find_dup_rules which was called:
# once (94.5ms+3.52ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 864 | ||||
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 | 35.9ms | while (my ($name, $text) = each %{$conf->{tests}}) { | ||
1041 | 2067 | 4.36ms | my $type = $conf->{test_types}->{$name}; | ||
1042 | |||||
1043 | # skip eval and empty tests | ||||
1044 | 2067 | 3.98ms | next if ($type & 1) || | ||
1045 | ($type eq $Mail::SpamAssassin::Conf::TYPE_EMPTY_TESTS); | ||||
1046 | |||||
1047 | 3372 | 20.0ms | 1686 | 3.31ms | my $tf = ($conf->{tflags}->{$name}||''); $tf =~ s/\s+/ /gs; # spent 3.31ms making 1686 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
1048 | # ensure similar, but differently-typed, rules are not marked as dups; | ||||
1049 | # take tflags into account too due to "tflags multiple" | ||||
1050 | 1686 | 4.97ms | $text = "$type\t$text\t$tf"; | ||
1051 | |||||
1052 | 1686 | 6.77ms | if (defined $names_for_text{$text}) { | ||
1053 | 11 | 82µs | $names_for_text{$text} .= " ".$name; | ||
1054 | 11 | 35µs | $dups{$text} = undef; # found (at least) one | ||
1055 | } else { | ||||
1056 | 1675 | 20.0ms | $names_for_text{$text} = $name; | ||
1057 | } | ||||
1058 | } | ||||
1059 | |||||
1060 | 1 | 577µs | foreach my $text (keys %dups) { | ||
1061 | 10 | 16µs | my $first; | ||
1062 | my $first_pri; | ||||
1063 | 22 | 280µs | 10 | 90µs | my @names = sort {$a cmp $b} split(' ', $names_for_text{$text}); # spent 90µs making 10 calls to Mail::SpamAssassin::Conf::Parser::CORE:sort, avg 9µs/call |
1064 | 10 | 33µs | foreach my $name (@names) { | ||
1065 | 21 | 167µs | my $priority = $conf->{priority}->{$name} || 0; | ||
1066 | |||||
1067 | 21 | 122µs | if (!defined $first || $priority < $first_pri) { | ||
1068 | 10 | 17µs | $first_pri = $priority; | ||
1069 | 10 | 24µs | $first = $name; | ||
1070 | } | ||||
1071 | } | ||||
1072 | # $first is now the earliest-occurring rule. mark others as dups | ||||
1073 | |||||
1074 | 10 | 17µs | my @dups; | ||
1075 | 10 | 51µs | foreach my $name (@names) { | ||
1076 | 21 | 45µs | next if $name eq $first; | ||
1077 | 11 | 49µs | push @dups, $name; | ||
1078 | 11 | 102µs | delete $conf->{tests}->{$name}; | ||
1079 | } | ||||
1080 | |||||
1081 | 10 | 143µs | 10 | 114µs | dbg("rules: $first merged duplicates: ".join(' ', @dups)); # spent 114µs making 10 calls to Mail::SpamAssassin::Logger::dbg, avg 11µs/call |
1082 | 10 | 130µs | $conf->{duplicate_rules}->{$first} = \@dups; | ||
1083 | } | ||||
1084 | } | ||||
1085 | |||||
1086 | # spent 42.2ms (35.5+6.68) within Mail::SpamAssassin::Conf::Parser::pack_eval_method which was called 379 times, avg 111µs/call:
# 379 times (35.5ms+6.68ms) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 877, avg 111µs/call | ||||
1087 | 379 | 3.78ms | my ($self, $function, $args, $name, $text) = @_; | ||
1088 | |||||
1089 | 379 | 652µs | my @args; | ||
1090 | 379 | 1.27ms | if (defined $args) { | ||
1091 | # bug 4419: Parse quoted strings, unquoted alphanumerics/floats, | ||||
1092 | # unquoted IPv4 and IPv6 addresses, and unquoted common domain names. | ||||
1093 | # s// is used so that we can determine whether or not we successfully | ||||
1094 | # parsed ALL arguments. | ||||
1095 | 379 | 1.59ms | local($1,$2,$3); | ||
1096 | 379 | 6.17ms | 379 | 2.54ms | while ($args =~ s/^\s* (?: (['"]) (.*?) \1 | ( [\d\.:A-Za-z-]+? ) ) # spent 2.54ms making 379 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 7µs/call |
1097 | \s* (?: , \s* | $ )//x) { | ||||
1098 | 483 | 7.80ms | 483 | 2.21ms | if (defined $2) { # spent 2.21ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 5µs/call |
1099 | 474 | 3.05ms | push @args, $2; | ||
1100 | } | ||||
1101 | else { | ||||
1102 | 9 | 78µs | push @args, $3; | ||
1103 | } | ||||
1104 | } | ||||
1105 | } | ||||
1106 | |||||
1107 | 379 | 713µ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 | 848µs | my $argstr = $function; | ||
1113 | 379 | 3.02ms | 379 | 908µs | $argstr =~ s/\s+//gs; # spent 908µ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 | 9.41ms | 483 | 1.03ms | map { my $s = $_; $s =~ s/\#/[HASH]/gs; 'q#' . $s . '#' } @args); # spent 1.03ms making 483 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
1118 | } | ||||
1119 | 379 | 2.95ms | return ($argstr, \@args); | ||
1120 | } | ||||
1121 | |||||
1122 | ########################################################################### | ||||
1123 | |||||
1124 | # spent 21µs within Mail::SpamAssassin::Conf::Parser::lint_trusted_networks which was called:
# once (21µs+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 939 | ||||
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 | 5µ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 | 14µs | return; | ||
1142 | } | ||||
1143 | |||||
1144 | foreach my $net_type ('internal_networks', 'msa_networks') { | ||||
1145 | next unless $conf->{"${net_type}_configured"}; | ||||
1146 | next if $net_type eq $matching_against; | ||||
1147 | |||||
1148 | my $replace_nets; | ||||
1149 | my @valid_net_list; | ||||
1150 | my $net_list = $conf->{$net_type}; | ||||
1151 | |||||
1152 | foreach my $net (@{$net_list->{nets}}) { | ||||
1153 | # don't check to see if an excluded network is included - that's senseless | ||||
1154 | if (!$net->{exclude} && !$nt->contains_net($net)) { | ||||
1155 | my $msg = "$matching_against doesn't contain $net_type entry '". | ||||
1156 | ($net->{as_string})."'"; | ||||
1157 | |||||
1158 | $self->lint_warn($msg, undef); # complain | ||||
1159 | $replace_nets = 1; # and omit it from the new internal set | ||||
1160 | } | ||||
1161 | else { | ||||
1162 | push @valid_net_list, $net; | ||||
1163 | } | ||||
1164 | } | ||||
1165 | |||||
1166 | if ($replace_nets) { | ||||
1167 | # something was invalid. replace the old nets list with a fixed version | ||||
1168 | # (which may be empty) | ||||
1169 | $net_list->{nets} = \@valid_net_list; | ||||
1170 | } | ||||
1171 | } | ||||
1172 | } | ||||
1173 | |||||
1174 | ########################################################################### | ||||
1175 | |||||
1176 | # spent 703ms (191+512) within Mail::SpamAssassin::Conf::Parser::add_test which was called 2074 times, avg 339µs/call:
# 548 times (59.6ms+114ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2979 of Mail/SpamAssassin/Conf.pm, avg 318µs/call
# 513 times (42.1ms+128ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3020] at line 3018 of Mail/SpamAssassin/Conf.pm, avg 331µs/call
# 465 times (48.3ms+243ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3174] at line 3173 of Mail/SpamAssassin/Conf.pm, avg 627µs/call
# 142 times (9.99ms+998µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3020] at line 3011 of Mail/SpamAssassin/Conf.pm, avg 77µs/call
# 102 times (6.87ms+660µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2958 of Mail/SpamAssassin/Conf.pm, avg 74µs/call
# 73 times (4.98ms+776µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2955 of Mail/SpamAssassin/Conf.pm, avg 79µs/call
# 71 times (6.20ms+15.2ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3052] at line 3051 of Mail/SpamAssassin/Conf.pm, avg 302µs/call
# 58 times (4.74ms+1.12ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2981] at line 2970 of Mail/SpamAssassin/Conf.pm, avg 101µs/call
# 46 times (3.64ms+306µs) by Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/MIMEHeader.pm:160] at line 140 of Mail/SpamAssassin/Plugin/MIMEHeader.pm, avg 86µs/call
# 33 times (3.19ms+7.12ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3088] at line 3086 of Mail/SpamAssassin/Conf.pm, avg 312µs/call
# 11 times (803µs+71µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3122] at line 3114 of Mail/SpamAssassin/Conf.pm, avg 79µs/call
# 7 times (438µs+97µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3088] at line 3080 of Mail/SpamAssassin/Conf.pm, avg 76µs/call
# 2 times (140µs+289µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3122] at line 3120 of Mail/SpamAssassin/Conf.pm, avg 215µs/call
# 2 times (111µs+44µs) by Mail::SpamAssassin::Plugin::AskDNS::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/AskDNS.pm:356] at line 353 of Mail/SpamAssassin/Plugin/AskDNS.pm, avg 77µs/call
# once (82µs+6µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:3206] at line 3204 of Mail/SpamAssassin/Conf.pm | ||||
1177 | 2074 | 9.71ms | my ($self, $name, $text, $type) = @_; | ||
1178 | 2074 | 4.21ms | my $conf = $self->{conf}; | ||
1179 | |||||
1180 | # Don't allow invalid names ... | ||||
1181 | 2074 | 30.1ms | 2074 | 8.74ms | if ($name !~ /^\D\w*$/) { # spent 8.74ms making 2074 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 4µs/call |
1182 | $self->lint_warn("config: error: rule '$name' has invalid characters ". | ||||
1183 | "(not Alphanumeric + Underscore + starting with a non-digit)\n", $name); | ||||
1184 | return; | ||||
1185 | } | ||||
1186 | |||||
1187 | # Also set a hard limit for ALL rules (rule names longer than 242 | ||||
1188 | # characters throw warnings). Check this separately from the above | ||||
1189 | # pattern to avoid vague error messages. | ||||
1190 | 2074 | 4.55ms | if (length $name > 200) { | ||
1191 | $self->lint_warn("config: error: rule '$name' is way too long ". | ||||
1192 | "(recommended maximum length is 22 characters)\n", $name); | ||||
1193 | return; | ||||
1194 | } | ||||
1195 | |||||
1196 | # Warn about, but use, long rule names during --lint | ||||
1197 | 2074 | 3.75ms | if ($conf->{lint_rules}) { | ||
1198 | if (length($name) > 50 && $name !~ /^__/ && $name !~ /^T_/) { | ||||
1199 | $self->lint_warn("config: warning: rule name '$name' is over 50 chars ". | ||||
1200 | "(recommended maximum length is 22 characters)\n", $name); | ||||
1201 | } | ||||
1202 | } | ||||
1203 | |||||
1204 | # all of these rule types are regexps | ||||
1205 | 2074 | 5.12ms | if ($type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS || | ||
1206 | $type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS || | ||||
1207 | $type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS || | ||||
1208 | $type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS) | ||||
1209 | { | ||||
1210 | 619 | 4.30ms | 619 | 146ms | return unless $self->is_delimited_regexp_valid($name, $text); # spent 146ms making 619 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 236µs/call |
1211 | } | ||||
1212 | 2074 | 5.65ms | if ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS) | ||
1213 | { | ||||
1214 | # RFC 5322 section 3.6.8, ftext printable US-ASCII chars not including ":" | ||||
1215 | # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables... | ||||
1216 | 606 | 6.83ms | 606 | 1.94ms | if ($text =~ /^!?defined\([!-9;-\176]+\)$/) { # spent 1.94ms making 606 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
1217 | # fine, implements 'exists:' | ||||
1218 | } else { | ||||
1219 | 548 | 11.8ms | 548 | 7.58ms | my ($pat) = ($text =~ /^\s*\S+\s*(?:\=|\!)\~\s*(\S.*?\S)\s*$/); # spent 7.58ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 14µs/call |
1220 | 1096 | 6.69ms | 548 | 1.41ms | if ($pat) { $pat =~ s/\s+\[if-unset:\s+(.+)\]\s*$//; } # spent 1.41ms making 548 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
1221 | 548 | 3.87ms | 548 | 101ms | return unless $self->is_delimited_regexp_valid($name, $pat); # spent 101ms making 548 calls to Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid, avg 184µs/call |
1222 | } | ||||
1223 | } | ||||
1224 | elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) | ||||
1225 | { | ||||
1226 | 465 | 3.32ms | 465 | 240ms | return unless $self->is_meta_valid($name, $text); # spent 240ms making 465 calls to Mail::SpamAssassin::Conf::Parser::is_meta_valid, avg 516µs/call |
1227 | } | ||||
1228 | |||||
1229 | 2074 | 26.4ms | $conf->{tests}->{$name} = $text; | ||
1230 | 2074 | 8.64ms | $conf->{test_types}->{$name} = $type; | ||
1231 | |||||
1232 | 2074 | 18.9ms | 2074 | 5.66ms | if ($name =~ /AUTOLEARNTEST/i) { # spent 5.66ms making 2074 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
1233 | dbg("config: auto-learn: $name has type $type = $conf->{test_types}->{$name} during add_test\n"); | ||||
1234 | } | ||||
1235 | |||||
1236 | |||||
1237 | 2074 | 6.79ms | if ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) { | ||
1238 | 465 | 3.73ms | $conf->{priority}->{$name} ||= 500; | ||
1239 | } | ||||
1240 | else { | ||||
1241 | 1609 | 11.6ms | $conf->{priority}->{$name} ||= 0; | ||
1242 | } | ||||
1243 | 2074 | 4.35ms | $conf->{priority}->{$name} ||= 0; | ||
1244 | 2074 | 16.6ms | $conf->{source_file}->{$name} = $self->{currentfile}; | ||
1245 | |||||
1246 | 2074 | 3.91ms | if ($conf->{main}->{keep_config_parsing_metadata}) { | ||
1247 | $conf->{if_stack}->{$name} = $self->get_if_stack_as_string(); | ||||
1248 | |||||
1249 | if ($self->{file_scoped_attrs}->{testrules}) { | ||||
1250 | $conf->{testrules}->{$name} = 1; # used in build/mkupdates/listpromotable | ||||
1251 | } | ||||
1252 | } | ||||
1253 | |||||
1254 | # if we found this rule in a user_prefs file, it's a user rule -- note that | ||||
1255 | # we may need to recompile the rule code for this type (if they've already | ||||
1256 | # been compiled, e.g. in spamd). | ||||
1257 | # | ||||
1258 | # Note: the want_rebuild_for_type 'flag' is actually a counter; it is decremented | ||||
1259 | # after each scan. This ensures that we always recompile at least once more; | ||||
1260 | # once to *define* the rule, and once afterwards to *undefine* the rule in the | ||||
1261 | # compiled ruleset again. | ||||
1262 | # | ||||
1263 | # If two consecutive scans use user rules, that's ok -- the second one will | ||||
1264 | # reset the counter, and we'll still recompile just once afterwards to undefine | ||||
1265 | # the rule again. | ||||
1266 | # | ||||
1267 | 2074 | 25.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 240ms (181+58.9) within Mail::SpamAssassin::Conf::Parser::is_meta_valid which was called 465 times, avg 516µs/call:
# 465 times (181ms+58.9ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1226, avg 516µs/call | ||||
1287 | 465 | 2.16ms | my ($self, $name, $rule) = @_; | ||
1288 | |||||
1289 | 465 | 963µs | my $meta = ''; | ||
1290 | 465 | 3.32ms | 465 | 19.6ms | $rule = untaint_var($rule); # must be careful below # spent 19.6ms making 465 calls to Mail::SpamAssassin::Util::untaint_var, avg 42µs/call |
1291 | |||||
1292 | # Lex the rule into tokens using a rather simple RE method ... | ||||
1293 | 465 | 876µs | my $lexer = ARITH_EXPRESSION_LEXER; | ||
1294 | 465 | 28.4ms | 930 | 19.0ms | my @tokens = ($rule =~ m/$lexer/g); # spent 16.3ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 35µs/call
# spent 2.70ms making 465 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 6µs/call |
1295 | 465 | 1.15ms | if (length($name) == 1) { | ||
1296 | for (@tokens) { | ||||
1297 | print "$name $_\n " or die "Error writing token: $!"; | ||||
1298 | } | ||||
1299 | } | ||||
1300 | # Go through each token in the meta rule | ||||
1301 | 465 | 1.75ms | foreach my $token (@tokens) { | ||
1302 | # Numbers can't be rule names | ||||
1303 | 7210 | 120ms | 7210 | 20.3ms | if ($token !~ /^[A-Za-z_][A-Za-z0-9_]*\z/s) { # spent 20.3ms making 7210 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 3µs/call |
1304 | 4112 | 7.78ms | $meta .= "$token "; | ||
1305 | } | ||||
1306 | # Zero will probably cause more errors | ||||
1307 | else { | ||||
1308 | 3098 | 5.50ms | $meta .= "0 "; | ||
1309 | } | ||||
1310 | } | ||||
1311 | |||||
1312 | 465 | 1.64ms | my $evalstr = 'my $x = ' . $meta . '; 1;'; | ||
1313 | 465 | 29.5ms | if (eval $evalstr) { # spent 412µs executing statements in 37 string evals (merged)
# spent 397µs executing statements in 42 string evals (merged)
# spent 261µs executing statements in 26 string evals (merged)
# spent 236µs executing statements in 24 string evals (merged)
# spent 206µs executing statements in 20 string evals (merged)
# spent 201µs executing statements in 17 string evals (merged)
# spent 118µs executing statements in 12 string evals (merged)
# spent 112µs executing statements in 14 string evals (merged)
# spent 92µs executing statements in 8 string evals (merged)
# spent 79µs executing statements in 6 string evals (merged)
# spent 73µs executing statements in 8 string evals (merged)
# spent 73µs executing statements in 6 string evals (merged)
# spent 70µs executing statements in 8 string evals (merged)
# spent 68µs executing statements in 5 string evals (merged)
# spent 65µs executing statements in 7 string evals (merged)
# spent 64µs executing statements in 8 string evals (merged)
# spent 60µs executing statements in 7 string evals (merged)
# spent 54µs executing statements in 6 string evals (merged)
# spent 44µs executing statements in 6 string evals (merged)
# spent 43µs executing statements in 5 string evals (merged)
# spent 42µs executing statements in 5 string evals (merged)
# spent 40µs executing statements in 4 string evals (merged)
# spent 40µs executing statements in 3 string evals (merged)
# spent 39µs executing statements in 3 string evals (merged)
# spent 37µs executing statements in 5 string evals (merged)
# spent 37µs executing statements in 3 string evals (merged)
# spent 33µs executing statements in 2 string evals (merged)
# spent 32µs executing statements in 4 string evals (merged)
# spent 32µs executing statements in 2 string evals (merged)
# spent 31µs executing statements in 4 string evals (merged)
# spent 29µs executing statements in 2 string evals (merged)
# spent 29µs executing statements in 2 string evals (merged)
# spent 27µs executing statements in 3 string evals (merged)
# spent 26µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 3 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 24µs executing statements in 3 string evals (merged)
# spent 24µs executing statements in 2 string evals (merged)
# spent 23µs executing statements in 2 string evals (merged)
# spent 23µs executing statements in 3 string evals (merged)
# spent 23µs executing statements in 3 string evals (merged)
# spent 22µs executing statements in 3 string evals (merged)
# spent 22µs executing statements in 2 string evals (merged)
# spent 22µs executing statements in 2 string evals (merged)
# spent 21µs executing statements in 2 string evals (merged)
# spent 21µs executing statements in string eval
# spent 21µs executing statements in 2 string evals (merged)
# spent 20µs executing statements in string eval
# spent 20µs executing statements in string eval
# spent 20µs executing statements in string eval
# spent 19µs executing statements in string eval
# spent 19µs executing statements in 2 string evals (merged)
# spent 18µs executing statements in string eval
# spent 18µs executing statements in 2 string evals (merged)
# spent 18µs executing statements in string eval
# spent 17µs executing statements in string eval
# spent 17µs executing statements in string eval
# spent 17µs executing statements in string eval
# spent 17µs executing statements in string eval
# spent 16µs executing statements in 2 string evals (merged)
# spent 16µs executing statements in string eval
# spent 16µs executing statements in string eval
# spent 16µs executing statements in string eval
# spent 16µs executing statements in 2 string evals (merged)
# spent 16µs executing statements in string eval
# spent 16µs executing statements in string eval
# spent 16µs executing statements in string eval
# spent 16µs executing statements in string eval
# spent 16µs executing statements in 2 string evals (merged)
# spent 16µs executing statements in string eval
# spent 15µs executing statements in string eval
# spent 15µs executing statements in 2 string evals (merged)
# spent 15µs executing statements in string eval
# spent 15µs executing statements in string eval
# spent 15µs executing statements in string eval
# spent 15µs executing statements in 2 string evals (merged)
# spent 14µs executing statements in string eval
# spent 14µs executing statements in 2 string evals (merged)
# spent 14µs executing statements in 2 string evals (merged)
# spent 14µs executing statements in string eval
# spent 13µs executing statements in string eval
# spent 13µs executing statements in string eval
# spent 13µs executing statements in string eval
# spent 13µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 12µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 11µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 10µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 9µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 8µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval
# spent 7µs executing statements in string eval | ||
1314 | 465 | 6.51ms | return 1; | ||
1315 | } | ||||
1316 | my $err = $@ ne '' ? $@ : "errno=$!"; chomp $err; | ||||
1317 | $err =~ s/\s+(?:at|near)\b.*//s; | ||||
1318 | $err =~ s/Illegal division by zero/division by zero possible/i; | ||||
1319 | $self->lint_warn("config: invalid expression for rule $name: \"$rule\": $err\n", $name); | ||||
1320 | return 0; | ||||
1321 | } | ||||
1322 | |||||
1323 | # spent 258ms (37.0+221) within Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid which was called 1228 times, avg 210µs/call:
# 619 times (15.4ms+131ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1210, avg 236µs/call
# 548 times (20.1ms+80.6ms) by Mail::SpamAssassin::Conf::Parser::add_test at line 1221, avg 184µs/call
# 46 times (1.19ms+7.49ms) by Mail::SpamAssassin::Plugin::MIMEHeader::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/MIMEHeader.pm:160] at line 116 of Mail/SpamAssassin/Plugin/MIMEHeader.pm, avg 189µs/call
# 15 times (366µs+2.64ms) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:2701] at line 2685 of Mail/SpamAssassin/Conf.pm, avg 201µs/call | ||||
1324 | 1228 | 5.68ms | my ($self, $name, $re) = @_; | ||
1325 | |||||
1326 | 1228 | 16.5ms | 1228 | 7.36ms | if (!$re || $re !~ /^\s*m?(\W).*(?:\1|>|}|\)|\])[a-z]*\s*$/) { # spent 7.36ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 6µs/call |
1327 | $re ||= ''; | ||||
1328 | $self->lint_warn("config: invalid regexp for rule $name: $re: missing or invalid delimiters\n", $name); | ||||
1329 | return 0; | ||||
1330 | } | ||||
1331 | 1228 | 14.4ms | 1228 | 214ms | return $self->is_regexp_valid($name, $re); # spent 214ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::is_regexp_valid, avg 174µs/call |
1332 | } | ||||
1333 | |||||
1334 | # spent 214ms (108+106) within Mail::SpamAssassin::Conf::Parser::is_regexp_valid which was called 1228 times, avg 174µs/call:
# 1228 times (108ms+106ms) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1331, avg 174µs/call | ||||
1335 | 1228 | 5.80ms | my ($self, $name, $re) = @_; | ||
1336 | |||||
1337 | # OK, try to remove any normal perl-style regexp delimiters at | ||||
1338 | # the start and end, and modifiers at the end if present, | ||||
1339 | # so we can validate those too. | ||||
1340 | 1228 | 2.82ms | my $origre = $re; | ||
1341 | 1228 | 2.77ms | my $safere = $re; | ||
1342 | 1228 | 2.35ms | my $mods = ''; | ||
1343 | 1228 | 4.44ms | local ($1,$2); | ||
1344 | 1228 | 58.9ms | 6034 | 20.1ms | if ($re =~ s/^m\{//) { # spent 20.1ms making 6034 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 3µs/call |
1345 | 28 | 255µs | 14 | 89µs | $re =~ s/\}([a-z]*)\z//; $mods = $1; # spent 89µs making 14 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 6µs/call |
1346 | } | ||||
1347 | elsif ($re =~ s/^m\(//) { | ||||
1348 | $re =~ s/\)([a-z]*)\z//; $mods = $1; | ||||
1349 | } | ||||
1350 | elsif ($re =~ s/^m<//) { | ||||
1351 | $re =~ s/>([a-z]*)\z//; $mods = $1; | ||||
1352 | } | ||||
1353 | elsif ($re =~ s/^m(\W)//) { | ||||
1354 | 100 | 2.37ms | 100 | 1.28ms | $re =~ s/\Q$1\E([a-z]*)\z//; $mods = $1; # spent 840µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 17µs/call
# spent 442µs making 50 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 9µs/call |
1355 | } | ||||
1356 | elsif ($re =~ s{^/(.*)/([a-z]*)\z}{$1}) { | ||||
1357 | 1164 | 3.63ms | $mods = $2; | ||
1358 | } | ||||
1359 | else { | ||||
1360 | $safere = "m#".$re."#"; | ||||
1361 | } | ||||
1362 | |||||
1363 | 1228 | 3.07ms | if ($self->{conf}->{lint_rules} || | ||
1364 | $self->{conf}->{ignore_always_matching_regexps}) | ||||
1365 | { | ||||
1366 | my $msg = $self->is_always_matching_regexp($name, $re); | ||||
1367 | |||||
1368 | if (defined $msg) { | ||||
1369 | if ($self->{conf}->{lint_rules}) { | ||||
1370 | $self->lint_warn($msg, $name); | ||||
1371 | } else { | ||||
1372 | warn $msg; | ||||
1373 | return 0; | ||||
1374 | } | ||||
1375 | } | ||||
1376 | } | ||||
1377 | |||||
1378 | # now prepend the modifiers, in order to check if they're valid | ||||
1379 | 1228 | 3.44ms | if ($mods) { | ||
1380 | 788 | 3.61ms | $re = "(?" . $mods . ")" . $re; | ||
1381 | } | ||||
1382 | |||||
1383 | # note: this MUST use m/...${re}.../ in some form or another, ie. | ||||
1384 | # interpolation of the $re variable into a code regexp, in order to test the | ||||
1385 | # security of the regexp. simply using ("" =~ $re) will NOT do that, and | ||||
1386 | # will therefore open a hole! | ||||
1387 | { # no re "strict"; # since perl 5.21.8: Ranges of ASCII printables... | ||||
1388 | 6140 | 130ms | 2456 | 84.5ms | if (eval { ("" =~ m{$re}); 1; }) { return 1 } # spent 82.1ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:regcomp, avg 67µs/call
# spent 2.37ms making 1228 calls to Mail::SpamAssassin::Conf::Parser::CORE:match, avg 2µs/call |
1389 | } | ||||
1390 | my $err = $@ ne '' ? $@ : "errno=$!"; chomp $err; | ||||
1391 | $err =~ s/ at .*? line \d.*$//; | ||||
1392 | $self->lint_warn("config: invalid regexp for rule $name: $origre: $err\n", $name); | ||||
1393 | return 0; | ||||
1394 | } | ||||
1395 | |||||
1396 | # check the pattern for some basic errors, and warn if found | ||||
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 10.1ms (9.29+823µs) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist which was called 34 times, avg 297µs/call:
# 34 times (9.29ms+823µs) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 818, avg 297µs/call | ||||
1417 | 34 | 130µs | my ($self, $singlelist, @addrs) = @_; | ||
1418 | 34 | 65µs | my $conf = $self->{conf}; | ||
1419 | |||||
1420 | 34 | 347µs | foreach my $addr (@addrs) { | ||
1421 | 34 | 92µs | $addr = lc $addr; | ||
1422 | 34 | 73µs | my $re = $addr; | ||
1423 | 34 | 296µs | 34 | 84µs | $re =~ s/[\000\\\(]/_/gs; # paranoia # spent 84µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
1424 | 34 | 8.15ms | 152 | 556µs | $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars # spent 425µs making 118 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 4µs/call
# spent 131µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call |
1425 | 34 | 95µs | $re =~ tr/?/./; # "?" -> "." | ||
1426 | 34 | 417µs | 34 | 184µs | $re =~ s/\*+/\.\*/g; # "*" -> "any string" # spent 184µs making 34 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 5µs/call |
1427 | 34 | 534µs | $conf->{$singlelist}->{$addr} = "^${re}\$"; | ||
1428 | } | ||||
1429 | } | ||||
1430 | |||||
1431 | # spent 10.3ms (7.89+2.41) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd which was called 102 times, avg 101µs/call:
# 83 times (6.36ms+1.95ms) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim at line 1470, avg 100µs/call
# 19 times (1.53ms+463µs) by Mail::SpamAssassin::Conf::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Conf.pm:433] at line 431 of Mail/SpamAssassin/Conf.pm, avg 105µs/call | ||||
1432 | 102 | 426µs | my ($self, $listname, $addr, $domain) = @_; | ||
1433 | 102 | 208µs | my $conf = $self->{conf}; | ||
1434 | |||||
1435 | 102 | 213µs | $domain = lc $domain; | ||
1436 | 102 | 236µs | $addr = lc $addr; | ||
1437 | 102 | 988µs | if ($conf->{$listname}->{$addr}) { | ||
1438 | 10 | 44µs | push @{$conf->{$listname}->{$addr}{domain}}, $domain; | ||
1439 | } | ||||
1440 | else { | ||||
1441 | 97 | 201µs | my $re = $addr; | ||
1442 | 97 | 825µs | 97 | 232µs | $re =~ s/[\000\\\(]/_/gs; # paranoia # spent 232µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 2µs/call |
1443 | 97 | 4.10ms | 458 | 1.64ms | $re =~ s/([^\*\?_a-zA-Z0-9])/\\$1/g; # escape any possible metachars # spent 1.24ms making 361 calls to Mail::SpamAssassin::Conf::Parser::CORE:substcont, avg 3µs/call
# spent 393µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 4µs/call |
1444 | 97 | 270µs | $re =~ tr/?/./; # "?" -> "." | ||
1445 | 97 | 1.16ms | 97 | 540µs | $re =~ s/\*+/\.\*/g; # "*" -> "any string" # spent 540µs making 97 calls to Mail::SpamAssassin::Conf::Parser::CORE:subst, avg 6µs/call |
1446 | 97 | 1.37ms | $conf->{$listname}->{$addr}{re} = "^${re}\$"; | ||
1447 | 97 | 486µ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 9.28ms (968µs+8.31) within Mail::SpamAssassin::Conf::Parser::add_to_addrlist_dkim which was called 83 times, avg 112µs/call:
# 83 times (968µs+8.31ms) by Mail::SpamAssassin::Plugin::DKIM::__ANON__[/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Plugin/DKIM.pm:420] at line 418 of Mail/SpamAssassin/Plugin/DKIM.pm, avg 112µs/call | ||||
1470 | 83 | 866µs | 83 | 8.31ms | add_to_addrlist_rcvd(@_); # spent 8.31ms making 83 calls to Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd, avg 100µs/call |
1471 | } | ||||
1472 | |||||
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 30.0ms (4.63+25.3) within Mail::SpamAssassin::Conf::Parser::fix_path_relative_to_current_file which was called 58 times, avg 517µs/call:
# 58 times (4.63ms+25.3ms) by Mail::SpamAssassin::Conf::Parser::parse at line 342, avg 517µs/call | ||||
1496 | 58 | 253µs | my ($self, $path) = @_; | ||
1497 | |||||
1498 | # the path may be specified as "~/foo", so deal with that | ||||
1499 | 58 | 604µs | 58 | 19.7ms | $path = $self->{conf}->{main}->sed_path($path); # spent 19.7ms making 58 calls to Mail::SpamAssassin::sed_path, avg 340µs/call |
1500 | |||||
1501 | 58 | 972µs | 58 | 1.09ms | if (!File::Spec->file_name_is_absolute ($path)) { # spent 1.09ms making 58 calls to File::Spec::Unix::file_name_is_absolute, avg 19µs/call |
1502 | 58 | 662µs | 58 | 2.64ms | my ($vol, $dirs, $file) = File::Spec->splitpath ($self->{currentfile}); # spent 2.64ms making 58 calls to File::Spec::Unix::splitpath, avg 46µs/call |
1503 | 58 | 564µs | 58 | 1.18ms | $path = File::Spec->catpath ($vol, $dirs, $path); # spent 1.18ms making 58 calls to File::Spec::Unix::catpath, avg 20µs/call |
1504 | 58 | 727µs | 58 | 698µs | dbg("config: fixed relative path: $path"); # spent 698µs making 58 calls to Mail::SpamAssassin::Logger::dbg, avg 12µs/call |
1505 | } | ||||
1506 | 58 | 551µ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.23s within Mail::SpamAssassin::Conf::Parser::CORE:match which was called 322611 times, avg 4µs/call:
# 269448 times (614ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 994, avg 2µs/call
# 16436 times (43.2ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 273, avg 3µs/call
# 11321 times (463ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 41µs/call
# 7210 times (20.3ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1303, avg 3µs/call
# 2650 times (10.3ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 516, avg 4µs/call
# 2074 times (8.74ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1181, avg 4µs/call
# 2074 times (5.66ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1232, avg 3µs/call
# 2067 times (5.74ms+0s) by Mail::SpamAssassin::Conf::Parser::check_for_missing_descriptions at line 657, avg 3µs/call
# 1474 times (3.67ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 2µs/call
# 1284 times (2.52ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 640, avg 2µs/call
# 1284 times (2.18ms+0s) by Mail::SpamAssassin::Conf::Parser::set_default_scores at line 642, avg 2µs/call
# 1228 times (7.36ms+0s) by Mail::SpamAssassin::Conf::Parser::is_delimited_regexp_valid at line 1326, avg 6µs/call
# 1228 times (2.37ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 2µs/call
# 606 times (1.94ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1216, avg 3µs/call
# 548 times (7.58ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1219, avg 14µs/call
# 508 times (7.17ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 14µs/call
# 465 times (16.3ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 35µs/call
# 379 times (4.76ms+0s) by Mail::SpamAssassin::Conf::Parser::finish_parsing at line 876, avg 13µs/call
# 136 times (675µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 302, avg 5µs/call
# 68 times (380µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 308, avg 6µs/call
# 55 times (422µs+0s) by Mail::SpamAssassin::Conf::Parser::cond_clause_can_or_has at line 588, avg 8µs/call
# 34 times (98µs+0s) by Mail::SpamAssassin::Conf::Parser::set_addrlist_value at line 815, avg 3µs/call
# 17 times (48µs+0s) by Mail::SpamAssassin::Conf::Parser::set_template_append at line 832, avg 3µs/call
# 5 times (14µs+0s) by Mail::SpamAssassin::Conf::Parser::set_bool_value at line 749, avg 3µs/call
# 4 times (39µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 722, avg 10µs/call
# 4 times (12µs+0s) by Mail::SpamAssassin::Conf::Parser::set_numeric_value at line 719, avg 3µs/call
# 3 times (9µs+0s) by Mail::SpamAssassin::Conf::Parser::set_string_value at line 771, avg 3µs/call
# once (7µs+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 240 | |||||
# spent 137ms within Mail::SpamAssassin::Conf::Parser::CORE:regcomp which was called 15046 times, avg 9µs/call:
# 11321 times (42.1ms+0s) by Mail::SpamAssassin::Conf::Parser::_meta_deps_recurse at line 987, avg 4µs/call
# 1474 times (5.96ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 4µs/call
# 1228 times (82.1ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1388, avg 67µs/call
# 508 times (2.84ms+0s) by Mail::SpamAssassin::Conf::Parser::handle_conditional at line 511, avg 6µs/call
# 465 times (2.70ms+0s) by Mail::SpamAssassin::Conf::Parser::is_meta_valid at line 1294, avg 6µs/call
# 50 times (840µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 17µs/call | |||||
sub Mail::SpamAssassin::Conf::Parser::CORE:sort; # opcode | |||||
# spent 277ms within Mail::SpamAssassin::Conf::Parser::CORE:subst which was called 92819 times, avg 3µs/call:
# 16436 times (66.5ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 279, avg 4µs/call
# 16436 times (58.9ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 282, avg 4µs/call
# 16436 times (38.1ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 281, avg 2µs/call
# 16436 times (32.3ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 280, avg 2µs/call
# 9050 times (21.5ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 286, avg 2µs/call
# 7576 times (25.8ms+0s) by Mail::SpamAssassin::Conf::Parser::parse at line 291, avg 3µs/call
# 6034 times (20.1ms+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1344, avg 3µs/call
# 1686 times (3.31ms+0s) by Mail::SpamAssassin::Conf::Parser::find_dup_rules at line 1047, avg 2µs/call
# 548 times (1.41ms+0s) by Mail::SpamAssassin::Conf::Parser::add_test at line 1220, avg 3µs/call
# 483 times (2.21ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1098, avg 5µs/call
# 483 times (1.03ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1117, avg 2µs/call
# 379 times (2.54ms+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1096, avg 7µs/call
# 379 times (908µs+0s) by Mail::SpamAssassin::Conf::Parser::pack_eval_method at line 1113, avg 2µs/call
# 97 times (540µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1445, avg 6µs/call
# 97 times (393µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 4µs/call
# 97 times (232µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1442, avg 2µs/call
# 50 times (442µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1354, avg 9µs/call
# 34 times (184µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1426, avg 5µs/call
# 34 times (131µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 4µs/call
# 34 times (84µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1423, avg 2µs/call
# 14 times (89µs+0s) by Mail::SpamAssassin::Conf::Parser::is_regexp_valid at line 1345, avg 6µs/call | |||||
# spent 1.67ms within Mail::SpamAssassin::Conf::Parser::CORE:substcont which was called 479 times, avg 3µs/call:
# 361 times (1.24ms+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist_rcvd at line 1443, avg 3µs/call
# 118 times (425µs+0s) by Mail::SpamAssassin::Conf::Parser::add_to_addrlist at line 1424, avg 4µs/call |