You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by he...@apache.org on 2021/05/28 09:40:10 UTC
svn commit: r1890274 - in /spamassassin/trunk: ./ lib/Mail/SpamAssassin/
lib/Mail/SpamAssassin/Conf/ lib/Mail/SpamAssassin/Plugin/ t/
Author: hege
Date: Fri May 28 09:40:09 2021
New Revision: 1890274
URL: http://svn.apache.org/viewvc?rev=1890274&view=rev
Log:
Bug 7735 - Meta rules need to handle missing/unrun dependencies
- Meta rules no longer use priority values, they are evaluated dynamically
when the rules they depend on are finished.
- API: New $pms->rule_pending() and $pms->rule_ready() functions.
$pms->rule_pending($rulename) must be called from rules eval-function, if
the result can arrive later than when exiting the function (async
lookups). $pms->rule_ready($rulename) or $pms->got_hit(...) must be
called when the result has arrived. If these are not used, it can break
depending meta rule evaluation.
- API: Deprecated $pms->harvest_until_rule_completes, $pms->is_rule_complete
Added:
spamassassin/trunk/t/basic_meta_net.t (with props)
Modified:
spamassassin/trunk/MANIFEST
spamassassin/trunk/UPGRADE
spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/OneLineBodyRuleType.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Reuse.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm
spamassassin/trunk/t/basic_meta2.t
spamassassin/trunk/t/dcc.t
spamassassin/trunk/t/if_can.t
spamassassin/trunk/t/priorities.t
Modified: spamassassin/trunk/MANIFEST
URL: http://svn.apache.org/viewvc/spamassassin/trunk/MANIFEST?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/MANIFEST (original)
+++ spamassassin/trunk/MANIFEST Fri May 28 09:40:09 2021
@@ -249,6 +249,7 @@ t/basic_lint_net.t
t/basic_lint_without_sandbox.t
t/basic_meta.t
t/basic_meta2.t
+t/basic_meta_net.t
t/basic_obj_api.t
t/bayesbdb.t
t/bayesdbm.t
Modified: spamassassin/trunk/UPGRADE
URL: http://svn.apache.org/viewvc/spamassassin/trunk/UPGRADE?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/UPGRADE (original)
+++ spamassassin/trunk/UPGRADE Fri May 28 09:40:09 2021
@@ -2,6 +2,16 @@
Note for Users Upgrading to SpamAssassin 4.0.0
----------------------------------------------
+- Meta rules no longer use priority values, they are evaluated dynamically
+ when the rules they depend on are finished. (Bug 7735)
+
+- API: New $pms->rule_pending() and $pms->rule_ready() functions.
+ $pms->rule_pending($rulename) must be called from rules eval-function, if
+ the result can arrive later than when exiting the function (async
+ lookups). $pms->rule_ready($rulename) or $pms->got_hit(...) must be
+ called when the result has arrived. If these are not used, it can break
+ depending meta rule evaluation.
+
- Improved internal header address (From/To/Cc) parser, now also handles
multiple addresses. Optional support for external Email::Address::XS
parser, which can handle nested comments and other oddities.
@@ -92,12 +102,14 @@ Note for Users Upgrading to SpamAssassin
pyzor_max setting to pyzor_count_min. Added pyzor_whitelist_min and
pyzor_whitelist_factor setting. Also try to ignore "empty body" FPs.
-- API: deprecated register_async_rule_start/finish calls (they can be left
- in code for backwards compatibility). Plugins should only use
- bgsend_and_start_lookup which handles required things automatically
- (direct calls to bgsend or start_lookup should not be used),
- bgsend_and_start_lookup should always contain $ent->{rulename} for correct
- meta dependency handling. Deprecated also start_lookup, get_lookup, lookup_ns.
+- API: deprecated $pms->register_async_rule_start() and
+ $pms->register_async_rule_finish() calls (they can be left in code for
+ backwards compatibility). Plugins should only use
+ $pms->bgsend_and_start_lookup() which handles required things
+ automatically (direct calls to bgsend or start_lookup should not be used).
+ $pms->bgsend_and_start_lookup() should always contain $ent->{rulename} for
+ correct meta dependency handling. Deprecated also start_lookup,
+ get_lookup, lookup_ns, harvest_until_rule_completes, is_rule_complete.
- SPF: Mail::SPF is now only supported. Mail::SPF::Query use is deprecated,
along with settings do_not_use_mail_spf, do_not_use_mail_spf_query. SPF
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm Fri May 28 09:40:09 2021
@@ -4832,7 +4832,9 @@ sub new {
$self->{meta_tests} = { };
$self->{eval_plugins} = { };
$self->{eval_plugins_types} = { };
- $self->{duplicate_rules} = { };
+
+ # meta dependencies
+ $self->{meta_dependencies} = {};
# map eval function names to rulenames
$self->{eval_to_rule} = {};
@@ -5382,7 +5384,6 @@ sub free_uncompiled_rule_source {
{
#delete $self->{if_stack}; # it's Parser not Conf?
#delete $self->{source_file};
- #delete $self->{meta_dependencies};
}
}
@@ -5431,6 +5432,7 @@ sub feature_bayes_stopwords { 1 } # mult
sub feature_get_host { 1 } # $pms->get() :host :domain :ip :revip # was implemented together with AskDNS::has_tag_header # Bug 7734
sub feature_blocklist_welcomelist { 1 } # bz 7826
sub feature_header_address_parser { 1 } # improved header address parsing using Email::Address::XS, $pms->get() list context
+sub feature_local_tests_only { 1 } # Config parser supports "if (local_tests_only)"
sub has_tflags_nosubject { 1 } # tflags nosubject
sub has_tflags_nolog { 1 } # tflags nolog
sub perl_min_version_5010000 { return $] >= 5.010000 } # perl version check ("perl_version" not neatly backwards-compatible)
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm Fri May 28 09:40:09 2021
@@ -546,6 +546,9 @@ sub handle_conditional {
elsif ($token eq 'perl_version') {
$eval .= $]." ";
}
+ elsif ($token eq 'local_tests_only') {
+ $eval .= '($self->{conf}->{main}->{local_tests_only}?1:0) '
+ }
elsif ($token =~ /^(?:\W{1,5}|[+-]?\d+(?:\.\d+)?)$/) {
# using tainted subr. argument may taint the whole expression, avoid
my $u = untaint_var($token);
@@ -885,17 +888,11 @@ sub finish_parsing {
$conf->{main}->call_plugins("user_conf_parsing_start", { conf => $conf });
}
- $self->trace_meta_dependencies();
+ # compile meta rules
+ $self->compile_meta_rules();
$self->fix_priorities();
$self->fix_tflags();
- # don't do this if allow_user_rules is active, since it deletes entries
- # from {tests}
- if (!$conf->{allow_user_rules}) {
- # Duplicate merging is buggy, disabled, code to be removed
- #$self->find_dup_rules(); # must be after fix_priorities()
- }
-
dbg("config: finish parsing");
while (my ($name, $text) = each %{$conf->{tests}}) {
@@ -969,7 +966,7 @@ sub finish_parsing {
$conf->{head_tests}->{$priority}->{$name} = $text;
}
elsif ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
- $conf->{meta_tests}->{$priority}->{$name} = $text;
+ # Handled by compile_meta_rules()
}
elsif ($type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS) {
$conf->{uri_tests}->{$priority}->{$name} = $text;
@@ -1008,82 +1005,161 @@ sub finish_parsing {
}
}
-sub trace_meta_dependencies {
+# Returns all rulenames matching glob (FOO_*)
+sub expand_ruleglob {
+ my ($self, $ruleglob, $rulename) = @_;
+ my $expanded;
+ if (exists $self->{ruleglob_cache}{$ruleglob}) {
+ $expanded = $self->{ruleglob_cache}{$ruleglob};
+ } else {
+ my $reglob = $ruleglob;
+ $reglob =~ s/\?/./g;
+ $reglob =~ s/\*/.*?/g;
+ # Glob rules, but do not match ourselves..
+ my @rules = grep {/^${reglob}$/ && $_ ne $rulename} keys %{$self->{conf}->{scores}};
+ if (@rules) {
+ $expanded = join('+', sort @rules);
+ } else {
+ $expanded = '0';
+ }
+ }
+ my $logstr = $expanded eq '0' ? 'no matches' : $expanded;
+ dbg("rules: meta $rulename rules_matching($ruleglob) expanded: $logstr");
+ $self->{ruleglob_cache}{$ruleglob} = $expanded;
+ return " ($expanded) ";
+}
+
+sub compile_meta_rules {
my ($self) = @_;
+ my (%meta, %meta_deps, %rule_deps);
my $conf = $self->{conf};
- $conf->{meta_dependencies} = { };
foreach my $name (keys %{$conf->{tests}}) {
- next unless ($conf->{test_types}->{$name}
- == $Mail::SpamAssassin::Conf::TYPE_META_TESTS);
- my $alreadydone = {};
- $self->_meta_deps_recurse($conf, $name, $name, $alreadydone);
- }
-}
+ next unless $conf->{test_types}->{$name} == $Mail::SpamAssassin::Conf::TYPE_META_TESTS;
+ my $rule = $conf->{tests}->{$name};
-sub _meta_deps_recurse {
- my ($self, $conf, $toprule, $name, $alreadydone) = @_;
+ # Expand meta rules_matching() before lexing
+ $rule =~ s/${META_RULES_MATCHING_RE}/$self->expand_ruleglob($1,$name)/ge;
- # Avoid recomputing the dependencies of a rule
- return split(' ', $conf->{meta_dependencies}->{$name}) if defined $conf->{meta_dependencies}->{$name};
+ # Lex the rule into tokens using a rather simple RE method ...
+ my @tokens = ($rule =~ /$ARITH_EXPRESSION_LEXER/og);
- # Obviously, don't trace empty or nonexistent rules
- my $rule = $conf->{tests}->{$name};
- unless ($rule) {
- $conf->{meta_dependencies}->{$name} = '';
- return ( );
- }
+ # Set the rule blank to start
+ $meta{$name} = '';
+
+ # List dependencies that are meta tests in the same priority band
+ $meta_deps{$name} = [ ];
+
+ # List all rule dependencies
+ $rule_deps{$name} = [ ];
+
+ # Go through each token in the meta rule
+ foreach my $token (@tokens) {
+ # operator (triage, already validated by is_meta_valid)
+ if ($token !~ tr/+&|()!<>=//c) {
+ $meta{$name} .= "$token ";
+ }
+ # rule-like check for local_tests_only
+ elsif ($token eq 'local_tests_only') {
+ $meta{$name} .= '($_[0]->{main}->{local_tests_only}||0) ';
+ }
+ # ... rulename?
+ elsif ($token =~ IS_RULENAME) {
+ # Will end up later in a compiled sub called from do_meta_tests:
+ # $_[0] = $pms
+ # $_[1] = $h ($pms->{tests_already_hit}),
+ # $_[2] = hashref list of unrun rules
+ $meta{$name} .= "(\$_[1]->{'$token'}||(\$_[2]->{'$token'}?1:0)) ";
+
+ if (!exists $conf->{test_types}->{$token}) {
+ dbg("rules: meta test $name has undefined dependency '$token'");
+ push @{$rule_deps{$name}}, $token;
+ next;
+ }
- # Avoid infinite recursion
- return ( ) if exists $alreadydone->{$name};
- $alreadydone->{$name} = ( );
+ if ($conf->{scores}->{$token} == 0) {
+ # bug 5040: net rules in a non-net scoreset
+ # there are some cases where this is expected; don't warn
+ # in those cases.
+ unless ((($conf->get_score_set()) & 1) == 0 &&
+ ($conf->{tflags}->{$token}||'') =~ /\bnet\b/)
+ {
+ dbg("rules: meta test $name has dependency '$token' with a zero score");
+ }
+ }
- my %deps;
+ # If the token is another meta rule, add it as a dependency
+ if ($conf->{test_types}->{$token} == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
+ push @{$meta_deps{$name}}, $token;
+ }
- # Lex the rule into tokens using a rather simple RE method ...
- my @tokens = ($rule =~ /($ARITH_EXPRESSION_LEXER)/og);
+ # Record all dependencies
+ push @{$rule_deps{$name}}, $token;
+ }
+ # ... number or operator (already validated by is_meta_valid)
+ else {
+ $meta{$name} .= "$token ";
+ }
+ }
+ }
- # Go through each token in the meta rule
- my $conf_tests = $conf->{tests};
- foreach my $token (@tokens) {
- # has to be an alpha+numeric token
- next if $token =~ tr{A-Za-z0-9_}{}c || substr($token,0,1) =~ tr{A-Za-z_}{}c; # even faster
+ # Sort by length of dependencies list. It's more likely we'll get
+ # the dependencies worked out this way.
+ my @metas = sort { @{$meta_deps{$a}} <=> @{$meta_deps{$b}} } keys %meta;
+ my $count;
+ do {
+ $count = $#metas;
+ my %metas = map { $_ => 1 } @metas; # keep a small cache for fast lookups
+ # Go through each meta rule we haven't done yet
+ for (my $i = 0 ; $i <= $#metas ; $i++) {
+ next if (grep( $metas{$_}, @{ $meta_deps{ $metas[$i] } }));
+ splice @metas, $i--, 1; # remove this rule from our list
+ }
+ } while ($#metas != $count && $#metas > -1); # run until we can't go anymore
- # and has to be a rule name
- next unless exists $conf_tests->{$token};
+ # If there are any rules left, we can't solve the dependencies so complain
+ my %unsolved_metas = map { $_ => 1 } @metas; # keep a small cache for fast lookups
+ foreach my $rulename_t (@metas) {
+ my $msg = "rules: excluding meta test $rulename_t, unsolved meta dependencies: ".
+ join(", ", grep($unsolved_metas{$_}, @{ $meta_deps{$rulename_t} }));
+ $self->lint_warn($msg);
+ }
- # add and recurse
- $deps{untaint_var($token)} = ( );
- my @subdeps = $self->_meta_deps_recurse($conf, $toprule, $token, $alreadydone);
- @deps{@subdeps} = ( );
+ foreach my $name (keys %meta) {
+ if (@{$rule_deps{$name}}) {
+ $conf->{meta_dependencies}->{$name} = $rule_deps{$name};
+ }
+ if ($unsolved_metas{$name}) {
+ $conf->{meta_tests}->{$name} = sub { 0 };
+ } else {
+ # Compile meta sub
+ eval '$conf->{meta_tests}->{$name} = sub { '.$meta{$name}.'};';
+ # Paranoid check
+ die "rules: meta compilation failed for $name: '$meta{$name}': $@" if ($@);
+ }
}
- $conf->{meta_dependencies}->{$name} = join (' ', keys %deps);
- return keys %deps;
}
sub fix_priorities {
my ($self) = @_;
my $conf = $self->{conf};
- die unless $conf->{meta_dependencies}; # order requirement
+ return unless $conf->{meta_dependencies}; # order requirement
my $pri = $conf->{priority};
# sort into priority order, lowest first -- this way we ensure that if we
# rearrange the pri of a rule early on, we cannot accidentally increase its
# priority later.
- foreach my $rule (sort {
- $pri->{$a} <=> $pri->{$b}
- } keys %{$pri})
- {
+ foreach my $rule (sort { $pri->{$a} <=> $pri->{$b} } keys %{$pri}) {
# we only need to worry about meta rules -- they are the
# only type of rules which depend on other rules
my $deps = $conf->{meta_dependencies}->{$rule};
next unless (defined $deps);
my $basepri = $pri->{$rule};
- foreach my $dep (split ' ', $deps) {
+ foreach my $dep (@$deps) {
my $deppri = $pri->{$dep};
- if ($deppri > $basepri) {
+ if (defined $deppri && $deppri > $basepri) {
dbg("rules: $rule (pri $basepri) requires $dep (pri $deppri): fixed");
$pri->{$dep} = $basepri;
}
@@ -1100,7 +1176,7 @@ sub fix_tflags {
while (my($rulename,$deps) = each %{$conf->{meta_dependencies}}) {
my $tfl = $tflags->{$rulename}||'';
next if $tfl =~ /\bnet\b/;
- foreach my $deprule (split(' ', $deps)) {
+ foreach my $deprule (@$deps) {
if (($tflags->{$deprule}||'') =~ /\bnet\b/) {
dbg("rules: meta $rulename inherits tflag net, depends on $deprule");
$tflags->{$rulename} = $tfl eq '' ? 'net' : "$tfl net";
@@ -1110,58 +1186,6 @@ sub fix_tflags {
}
}
-sub find_dup_rules {
- my ($self) = @_;
- my $conf = $self->{conf};
-
- my %names_for_text;
- my %dups;
- while (my ($name, $text) = each %{$conf->{tests}}) {
- my $type = $conf->{test_types}->{$name};
-
- # skip eval and empty tests
- next if ($type & 1) ||
- ($type eq $Mail::SpamAssassin::Conf::TYPE_EMPTY_TESTS);
-
- my $tf = ($conf->{tflags}->{$name}||''); $tf =~ s/\s+/ /gs;
- # ensure similar, but differently-typed, rules are not marked as dups;
- # take tflags into account too due to "tflags multiple"
- $text = "$type\t$text\t$tf";
-
- if (defined $names_for_text{$text}) {
- $names_for_text{$text} .= " ".$name;
- $dups{$text} = undef; # found (at least) one
- } else {
- $names_for_text{$text} = $name;
- }
- }
-
- foreach my $text (keys %dups) {
- my $first;
- my $first_pri;
- my @names = sort {$a cmp $b} split(' ', $names_for_text{$text});
- foreach my $name (@names) {
- my $priority = $conf->{priority}->{$name} || 0;
-
- if (!defined $first || $priority < $first_pri) {
- $first_pri = $priority;
- $first = $name;
- }
- }
- # $first is now the earliest-occurring rule. mark others as dups
-
- my @dups;
- foreach my $name (@names) {
- next if $name eq $first;
- push @dups, $name;
- delete $conf->{tests}->{$name};
- }
-
- dbg("rules: $first merged duplicates: ".join(' ', @dups));
- $conf->{duplicate_rules}->{$first} = \@dups;
- }
-}
-
# Deprecated function
sub pack_eval_method {
warn "deprecated function pack_eval_method() used\n";
@@ -1358,12 +1382,6 @@ sub add_test {
dbg("config: auto-learn: $name has type $type = $conf->{test_types}->{$name} during add_test\n");
}
- if ($type == $Mail::SpamAssassin::Conf::TYPE_META_TESTS) {
- $conf->{priority}->{$name} ||= 500;
- }
- else {
- $conf->{priority}->{$name} ||= 0;
- }
$conf->{priority}->{$name} ||= 0;
if ($conf->{main}->{keep_config_parsing_metadata}) {
@@ -1417,8 +1435,8 @@ sub is_meta_valid {
my $meta = '';
# Paranoid check (Bug #7557)
- if ($rule =~ /(?:\:\:|->)/) {
- warn("config: invalid meta $name rule: $rule") ;
+ if ($rule =~ /(?:\:\:|->|[\$\@\%\;\{\}])/) {
+ warn("config: invalid meta $name rule: $rule\n");
return 0;
}
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm Fri May 28 09:40:09 2021
@@ -311,27 +311,8 @@ sub check_subtest {
return 0;
}
-sub harvest_until_rule_completes {
- my ($self, $rule) = @_;
-
- dbg("dns: harvest_until_rule_completes");
- my $result = 0;
-
- for (my $first=1; ; $first=0) {
- # complete_lookups() may call completed_callback(), which may
- # call start_lookup() again (like in Plugin::URIDNSBL)
- my ($alldone,$anydone) =
- $self->{async}->complete_lookups($first ? 0 : 1.0, 1);
-
- $result = 1 if $self->is_rule_complete($rule);
- last if $result || $alldone;
-
- dbg("dns: harvest_until_rule_completes - check_tick");
- $self->{main}->call_plugins ("check_tick", { permsgstatus => $self });
- }
-
- return $result;
-}
+# Deprecated since 4.0, meta rules do not depend on priorities anymore
+sub harvest_until_rule_completes {}
sub harvest_dnsbl_queries {
my ($self) = @_;
@@ -702,16 +683,19 @@ sub cleanup_kids {
sub register_async_rule_start {}
sub register_async_rule_finish {}
sub mark_all_async_rules_complete {}
+sub is_rule_complete {}
-sub is_rule_complete {
+# Return number of pending lookups for a rule,
+# or list all of rules still pending
+sub get_pending_lookups {
my ($self, $rule) = @_;
-
- return 1 if !exists $self->{async}->{pending_rules}{$rule};
- return 1 if !%{$self->{async}->{pending_rules}{$rule}};
- return 1 if $self->{tests_already_hit}->{$rule};
-
- dbg("dns: $rule is not complete yet");
- return 0;
+ if (defined $rule) {
+ return 0 if !exists $self->{async}->{pending_rules}{$rule};
+ return scalar keys %{$self->{async}->{pending_rules}{$rule}};
+ } else {
+ return grep { %{$self->{async}->{pending_rules}{$_}} }
+ keys %{$self->{async}->{pending_rules}};
+ }
}
###########################################################################
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm Fri May 28 09:40:09 2021
@@ -294,6 +294,7 @@ sub new {
'subtest_names_hit' => [ ],
'spamd_result_log_items' => [ ],
'tests_already_hit' => { },
+ 'tests_pending' => { },
'get_cache' => { },
'tag_data' => { },
'rule_errors' => 0,
@@ -2862,32 +2863,8 @@ sub add_uri_detail_list {
###########################################################################
-sub ensure_rules_are_complete {
- my $self = shift;
- my $metarule = shift;
- # @_ is now the list of rules
-
- foreach my $r (@_) {
- # dbg("rules: meta rule depends on net rule $r");
- next if ($self->is_rule_complete($r));
-
- dbg("rules: meta rule $metarule depends on pending rule $r, blocking");
- my $timer = $self->{main}->time_method("wait_for_pending_rules");
-
- my $start = time;
- $self->harvest_until_rule_completes($r);
- my $elapsed = sprintf "%.2f", time - $start;
-
- if (!$self->is_rule_complete($r)) {
- dbg("rules: rule $r is still not complete; exited early?");
- }
- elsif ($elapsed > 0) {
- my $txt = "rules: $r took $elapsed seconds to complete, for $metarule";
- # Info only if something took over 1 sec to wait, prevent log flood
- if ($elapsed >= 1) { info($txt); } else { dbg($txt); }
- }
- }
-}
+# Deprecated since 4.0, meta rules do not depend on priorities anymore
+sub ensure_rules_are_complete {}
###########################################################################
@@ -3134,18 +3111,54 @@ sub got_hit {
$params{ruletype},
$rule_descr);
- # take care of duplicate rules, too (bug 5206)
- # ... removed as it's buggy
- #my $dups = $conf_ref->{duplicate_rules}->{$rule};
- #if ($dups && @{$dups}) {
- # foreach my $dup (@{$dups}) {
- # $self->got_hit($dup, $area, %params);
- # }
- #}
-
return 1;
}
+=item $status->rule_pending ($rulename)
+
+Register a pending rule. Must be called from rules eval-function, if the
+result can arrive later than when exiting the function (async lookups).
+
+$status->rule_done($rulename) or $status->got_hit(...) must be called when
+the result has arrived. If these are not used, it can break depending meta
+rule evaluation.
+
+=cut
+
+sub rule_pending {
+ my ($self, $rule) = @_;
+
+ $self->{tests_pending}->{$rule} = 1;
+
+ if (exists $self->{tests_already_hit}->{$rule}) {
+ # Only clear result if not hit
+ if ($self->{tests_already_hit}->{$rule} == 0) {
+ delete $self->{tests_already_hit}->{$rule};
+ }
+ }
+}
+
+=item $status->rule_ready ($rulename)
+
+Mark a previously marked $status->rule_pending() rule ready. Alternatively
+$status->got_hit() will also mark rule ready. If these are not used, it can
+break depending meta rule evaluation.
+
+=cut
+
+sub rule_ready {
+ my ($self, $rule) = @_;
+
+ if ($self->get_pending_lookups($rule)) {
+ # Can't be ready if there are pending lookups, ignore for now.
+ # Final do_meta_tests() in Check.pm will allow pending anyway.
+ return;
+ }
+
+ delete $self->{tests_pending}->{$rule};
+ $self->{tests_already_hit}->{$rule} ||= 0;
+}
+
###########################################################################
=item $status->test_log ($text [, $rulename])
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/ASN.pm Fri May 28 09:40:09 2021
@@ -573,6 +573,7 @@ sub check_asn {
my ($self, $pms, $re) = @_;
my $rulename = $pms->get_current_eval_rule_name();
+ $pms->rule_pending($rulename); # mark async
if (!defined $re) {
warn "asn: rule $rulename eval argument missing\n";
@@ -597,6 +598,8 @@ sub check_asn {
sub _check_asn {
my ($self, $pms, $rulename, $rec) = @_;
+ $pms->rule_ready($rulename); # mark rule ready for metas
+
my $asn = $pms->get_tag('ASN');
return if !defined $asn;
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm Fri May 28 09:40:09 2021
@@ -469,6 +469,8 @@ sub process_response_packet {
# and returns a number for the rest; we deal with numbers from here on
$rcode = $rcode_value{$rcode} if exists $rcode_value{$rcode};
}
+
+ $pms->rule_ready($rulename); # mark rule ready for metas
}
if (!@answer) {
# a trick to make the following loop run at least once, so that we can
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Check.pm Fri May 28 09:40:09 2021
@@ -28,9 +28,6 @@ use Mail::SpamAssassin::Constants qw(:sa
our @ISA = qw(Mail::SpamAssassin::Plugin);
-my $ARITH_EXPRESSION_LEXER = ARITH_EXPRESSION_LEXER;
-my $META_RULES_MATCHING_RE = META_RULES_MATCHING_RE;
-
# methods defined by the compiled ruleset; deleted in finish_tests()
our @TEMPORARY_METHODS;
@@ -98,6 +95,10 @@ sub check_main {
my @uris = $pms->get_uri_list();
+ # initialize meta stuff
+ $pms->{meta_pending} = {};
+ $pms->{meta_pending}->{$_} = 1 foreach (keys %{$pms->{conf}->{meta_tests}});
+
# Make sure priority -100 exists for launching DNS
$pms->{conf}->{priorities}->{-100} ||= 1 if $do_dns;
@@ -176,14 +177,13 @@ sub check_main {
$pms->harvest_completed_queries() if $rbls_running;
last if $pms->{deadline_exceeded} || $pms->{shortcircuited};
- $self->do_meta_tests($pms, $priority);
- $pms->harvest_completed_queries() if $rbls_running;
- last if $pms->{deadline_exceeded} || $pms->{shortcircuited};
-
# we may need to call this more often than once through the loop, but
# it needs to be done at least once, either at the beginning or the end.
$self->{main}->call_plugins ("check_tick", { permsgstatus => $pms });
$pms->harvest_completed_queries() if $rbls_running;
+
+ # check for ready metas
+ $self->do_meta_tests($pms, $priority);
}
# Finish DNS results
@@ -205,6 +205,12 @@ sub check_main {
undef $bodytext;
undef $fulltext;
+ # last chance to handle left callbacks, make rule hits etc
+ $self->{main}->call_plugins ("check_cleanup", { permsgstatus => $pms });
+
+ # final check for ready metas
+ $self->finish_meta_tests($pms);
+
# check dns_block_rule (bug 6728)
# TODO No idea yet what would be the most logical place to do all these..
if ($pms->{conf}->{dns_block_rule}) {
@@ -222,8 +228,7 @@ sub check_main {
}
}
- # last chance to handle left callbacks, make rule hits etc
- $self->{main}->call_plugins ("check_cleanup", { permsgstatus => $pms });
+ # PMS cleanup will write reports etc, all rule hits must be registered by now
$pms->check_cleanup();
if ($pms->{deadline_exceeded}) {
@@ -263,6 +268,113 @@ sub finish_tests {
###########################################################################
+sub do_meta_tests {
+ my ($self, $pms, $priority) = @_;
+
+ # Needed for Reuse to work, otherwise we don't care about priorities
+ if ($self->{main}->have_plugin('start_rules')) {
+ $self->{main}->call_plugins('start_rules', {
+ permsgstatus => $pms,
+ ruletype => 'meta',
+ priority => $priority
+ });
+ }
+
+ return if $self->{am_compiling}; # nothing to compile here
+
+ my $mp = $pms->{meta_pending};
+ my $tp = $pms->{tests_pending};
+ my $md = $pms->{conf}->{meta_dependencies};
+ my $mt = $pms->{conf}->{meta_tests};
+ my $h = $pms->{tests_already_hit};
+ my $retry;
+
+ # Get pending async rule list
+ my %pl = map { $_ => 1 } $pms->get_pending_lookups();
+
+RULE:
+ foreach my $rulename (keys %$mp) {
+ # Meta is not ready if some dependency has not run yet
+ foreach my $deprule (@{$md->{$rulename}||[]}) {
+ if (!exists $h->{$deprule} || $tp->{$deprule} || $pl{$deprule}) {
+ next RULE;
+ }
+ }
+ # Metasubs look like ($_[0]->{$rulename}||($_[1]->{$rulename}?1:0)) ...
+ my $result = $mt->{$rulename}->($pms, $h, {});
+ if ($result) {
+ dbg("rules: ran meta rule $rulename ======> got hit ($result)");
+ $pms->got_hit($rulename, '', ruletype => 'meta', value => $result);
+ } else {
+ dbg("rules-all: ran meta rule $rulename, no hit") if $would_log_rules_all;
+ $h->{$rulename} = 0; # mark meta done
+ }
+ delete $mp->{$rulename};
+ # Reiterate all metas again, in case some meta depended on us
+ $retry = 1;
+ }
+
+ goto RULE if $retry--;
+}
+
+sub finish_meta_tests {
+ my ($self, $pms) = @_;
+
+ return if $self->{am_compiling}; # nothing to compile here
+
+ my $mp = $pms->{meta_pending};
+ my $md = $pms->{conf}->{meta_dependencies};
+ my $mt = $pms->{conf}->{meta_tests};
+ my $h = $pms->{tests_already_hit};
+ my $retry;
+ my %unrun_metas;
+
+RULE:
+ foreach my $rulename (keys %$mp) {
+ my %unrun;
+ # Meta is not ready if some dependency has not run yet
+ foreach my $deprule (@{$md->{$rulename}||[]}) {
+ if (!exists $h->{$deprule}) {
+ # Record all unrun deps for second meta evaluation
+ $unrun{$deprule} = 1;
+ }
+ }
+ # Metasubs look like ($_[0]->{$rulename}||($_[1]->{$rulename}?1:0)) ...
+ my $result = $mt->{$rulename}->($pms, $h, {});
+ my $result2 = $result;
+ if (%unrun) {
+ # Evaluate all unrun rules as true using %unrun list
+ $result2 = $mt->{$rulename}->($pms, $h, \%unrun);
+ }
+ # Evaluated second time with all unrun rules as true. If result is not
+ # the same, we can't safely finish the meta. (Bug 7735)
+ if ($result != $result2) {
+ $unrun_metas{$rulename} = \%unrun if $would_log_rules_all;
+ next RULE;
+ } elsif ($result) {
+ dbg("rules: ran meta rule $rulename ======> got hit ($result)");
+ $pms->got_hit($rulename, '', ruletype => 'meta', value => $result);
+ } else {
+ dbg("rules-all: ran meta rule $rulename, no hit") if $would_log_rules_all;
+ $h->{$rulename} = 0; # mark meta done
+ }
+ delete $mp->{$rulename};
+ # Reiterate all metas again, in case some meta depended on us
+ $retry = 1;
+ }
+
+ goto RULE if $retry--;
+
+ if ($would_log_rules_all && %unrun_metas) {
+ foreach (sort keys %unrun_metas) {
+ dbg("rules-all: unrun dependencies prevented meta $_ from running: ".
+ join(', ', sort keys %{$unrun_metas{$_}}));
+ }
+ }
+}
+
+###########################################################################
+
sub run_rbl_eval_tests {
my ($self, $pms) = @_;
@@ -346,6 +458,7 @@ sub run_generic_tests {
# start_rules_plugin_code '.$ruletype.' '.$priority.'
my $scoresptr = $self->{conf}->{scores};
my $qrptr = $self->{conf}->{test_qrs};
+ my $hitsptr = $self->{tests_already_hit};
');
if (defined $opts{pre_loop_body}) {
$opts{pre_loop_body}->($self, $pms, $conf, %nopts);
@@ -529,170 +642,6 @@ sub add_temporary_method {
###########################################################################
-# Returns all rulenames matching glob (FOO_*)
-sub expand_ruleglob {
- my ($self, $ruleglob, $pms, $conf, $rulename) = @_;
- my $expanded;
- if (exists $pms->{ruleglob_cache}{$ruleglob}) {
- $expanded = $pms->{ruleglob_cache}{$ruleglob};
- } else {
- my $reglob = $ruleglob;
- $reglob =~ s/\?/./g;
- $reglob =~ s/\*/.*?/g;
- # Glob rules, but do not match ourselves..
- my @rules = grep {/^${reglob}$/ && $_ ne $rulename} keys %{$conf->{scores}};
- if (@rules) {
- $expanded = join('+', sort @rules);
- } else {
- $expanded = '0';
- }
- }
- my $logstr = $expanded eq '0' ? 'no matches' : $expanded;
- dbg("rules: meta $rulename rules_matching($ruleglob) expanded: $logstr");
- $pms->{ruleglob_cache}{$ruleglob} = $expanded;
- return " ($expanded) ";
-};
-
-sub do_meta_tests {
- my ($self, $pms, $priority) = @_;
- my (%rule_deps, %meta, $rulename);
-
- $self->run_generic_tests ($pms, $priority,
- consttype => $Mail::SpamAssassin::Conf::TYPE_META_TESTS,
- type => 'meta',
- testhash => $pms->{conf}->{meta_tests},
- args => [ ],
- loop_body => sub
- {
- my ($self, $pms, $conf, $rulename, $rule, %opts) = @_;
-
- # Expand meta rules_matching() before lexing
- $rule =~ s/${META_RULES_MATCHING_RE}/$self->expand_ruleglob($1,$pms,$conf,$rulename)/ge;
-
- # Lex the rule into tokens using a rather simple RE method ...
- my @tokens = ($rule =~ /$ARITH_EXPRESSION_LEXER/og);
-
- # Set the rule blank to start
- $meta{$rulename} = "";
-
- # List dependencies that are meta tests in the same priority band
- $rule_deps{$rulename} = [ ];
-
- # Go through each token in the meta rule
- foreach my $token (@tokens) {
-
- # ... rulename?
- if ($token =~ IS_RULENAME) {
- # the " || 0" formulation is to avoid "use of uninitialized value"
- # warnings; this is better than adding a 0 to a hash for every
- # rule referred to in a meta...
- $meta{$rulename} .= "(\$h->{'$token'}||0) ";
-
- if (!exists $conf->{scores}->{$token}) {
- dbg("rules: meta test $rulename has undefined dependency '$token'");
- }
- elsif ($conf->{scores}->{$token} == 0) {
- # bug 5040: net rules in a non-net scoreset
- # there are some cases where this is expected; don't warn
- # in those cases.
- unless ((($conf->get_score_set()) & 1) == 0 &&
- ($conf->{tflags}->{$token}||'') =~ /\bnet\b/)
- {
- info("rules: meta test $rulename has dependency '$token' with a zero score");
- }
- }
-
- # If the token is another meta rule, add it as a dependency
- push (@{ $rule_deps{$rulename} }, $token)
- if (exists $conf->{meta_tests}->{$opts{priority}}->{$token});
- } else {
- # ... number or operator
- $meta{$rulename} .= "$token ";
- }
- }
- },
- pre_loop_body => sub
- {
- my ($self, $pms, $conf, %opts) = @_;
- $self->push_evalstr_prefix($pms, '
- my $r;
- my $h = $self->{tests_already_hit};
- ');
- },
- post_loop_body => sub
- {
- my ($self, $pms, $conf, %opts) = @_;
-
- # Sort by length of dependencies list. It's more likely we'll get
- # the dependencies worked out this way.
- my @metas = sort { @{ $rule_deps{$a} } <=> @{ $rule_deps{$b} } }
- keys %{$conf->{meta_tests}->{$opts{priority}}};
-
- my $count;
- my $tflags = $conf->{tflags};
-
- # Now go ahead and setup the eval string
- do {
- $count = $#metas;
- my %metas = map { $_ => 1 } @metas; # keep a small cache for fast lookups
-
- # Go through each meta rule we haven't done yet
- for (my $i = 0 ; $i <= $#metas ; $i++) {
-
- # If we depend on meta rules that haven't run yet, skip it
- next if (grep( $metas{$_}, @{ $rule_deps{ $metas[$i] } }));
-
- # If we depend on network tests, call ensure_rules_are_complete()
- # to block until they are
- if (!defined $conf->{meta_dependencies}->{ $metas[$i] }) {
- warn "no meta_dependencies defined for $metas[$i]";
- }
- my $alldeps = join ' ', grep {
- ($tflags->{$_}||'') =~ /\bnet\b/
- } split (' ', $conf->{meta_dependencies}->{ $metas[$i] } );
-
- if ($alldeps ne '') {
- $self->add_evalstr($pms, '
- $self->ensure_rules_are_complete(q{'.$metas[$i].'}, qw{'.$alldeps.'});
- ');
- }
-
- # conditionally include the dbg in the eval str
- my $dbgstr = '';
- if (would_log('dbg')) {
- $dbgstr = 'dbg("rules: ran meta rule '.$metas[$i].' ======> got hit");';
- }
-
- # Add this meta rule to the eval line
- $self->add_evalstr($pms, '
- $r = '.$meta{$metas[$i]}.';
- if ($r) { $self->got_hit(q#'.$metas[$i].'#, "", ruletype => "meta", value => $r); '.$dbgstr.' }
- ');
-
- splice @metas, $i--, 1; # remove this rule from our list
- }
- } while ($#metas != $count && $#metas > -1); # run until we can't go anymore
-
- # If there are any rules left, we can't solve the dependencies so complain
- my %metas = map { $_ => 1 } @metas; # keep a small cache for fast lookups
- foreach my $rulename_t (@metas) {
- $pms->{rule_errors}++; # flag to --lint that there was an error ...
- my $msg =
- "rules: excluding meta test $rulename_t, unsolved meta dependencies: " .
- join(", ", grep($metas{$_}, @{ $rule_deps{$rulename_t} }));
- if ($self->{main}->{lint_rules}) {
- warn $msg."\n";
- }
- else {
- info($msg);
- }
- }
- }
- );
-}
-
-###########################################################################
-
sub do_head_tests {
my ($self, $pms, $priority) = @_;
# hash to hold the rules, "header\tdefault value" => rulename
@@ -787,6 +736,7 @@ sub do_head_tests {
$self->add_evalstr($pms, '
if ($scoresptr->{q{'.$rulename.'}}) {
+ $hitsptr->{q{'.$rulename.'}} ||= 0;
'.$posline.'
'.$self->hash_line_for_rule($pms, $rulename).'
'.$ifwhile.' ('.$expr.') {
@@ -880,6 +830,7 @@ sub do_body_tests {
$self->add_evalstr($pms, '
if ($scoresptr->{q{'.$rulename.'}}) {
+ $hitsptr->{q{'.$rulename.'}} ||= 0;
'.$sub.'
'.$self->ran_rule_plugin_code($rulename, "body").'
}
@@ -941,6 +892,7 @@ sub do_uri_tests {
$self->add_evalstr($pms, '
if ($scoresptr->{q{'.$rulename.'}}) {
+ $hitsptr->{q{'.$rulename.'}} ||= 0;
'.$sub.'
'.$self->ran_rule_plugin_code($rulename, "uri").'
}
@@ -1001,6 +953,7 @@ sub do_rawbody_tests {
$self->add_evalstr($pms, '
if ($scoresptr->{q{'.$rulename.'}}) {
+ $hitsptr->{q{'.$rulename.'}} ||= 0;
'.$sub.'
'.$self->ran_rule_plugin_code($rulename, "rawbody").'
}
@@ -1037,6 +990,7 @@ sub do_full_tests {
$max ||= 0;
$self->add_evalstr($pms, '
if ($scoresptr->{q{'.$rulename.'}}) {
+ $hitsptr->{q{'.$rulename.'}} ||= 0;
pos $$fullmsgref = 0;
'.$self->hash_line_for_rule($pms, $rulename).'
dbg("rules-all: running full rule %s", q{'.$rulename.'});
@@ -1193,6 +1147,7 @@ sub run_eval_tests {
$evalstr .= '
if ($scoresptr->{q{'.$rulename.'}}) {
+ $hitsptr->{q{'.$rulename.'}} ||= 0;
$rulename = q#'.$rulename.'#;
';
@@ -1254,6 +1209,7 @@ sub run_eval_tests {
my \$testptr = \$self->{conf}->{$evalname}->{$priority};
my \$scoresptr = \$self->{conf}->{scores};
+ my \$hitsptr = \$self->{tests_already_hit};
my \$prepend2desc = q#$prepend2desc#;
my \$rulename;
my \$result;
@@ -1403,5 +1359,17 @@ sub free_ruleset_source {
}
###########################################################################
+
+sub compile_now_start {
+ my ($self, $params) = @_;
+ $self->{am_compiling} = 1;
+}
+
+sub compile_now_finish {
+ my ($self, $params) = @_;
+ delete $self->{am_compiling};
+}
+
+###########################################################################
1;
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DCC.pm Fri May 28 09:40:09 2021
@@ -730,6 +730,10 @@ sub _check_async {
foreach (@{$pms->{conf}->{eval_to_rule}->{check_dcc}}) {
$pms->got_hit($_, "", ruletype => 'eval');
}
+ } else {
+ foreach (@{$pms->{conf}->{eval_to_rule}->{check_dcc}}) {
+ $pms->rule_ready($_);
+ }
}
}
} else {
@@ -819,7 +823,13 @@ sub check_dcc {
return 0 if $self->{dcc_disabled};
return 0 if !$pms->{conf}->{use_dcc};
return 0 if $pms->{dcc_abort};
- return 0 if $pms->{dcc_async_start}; # async already handling?
+
+ # async already handling?
+ if ($pms->{dcc_async_start}) {
+ my $rulename = $pms->get_current_eval_rule_name();
+ $pms->rule_pending($rulename); # mark async
+ return 0;
+ }
return $pms->{dcc_result} if defined $pms->{dcc_result};
@@ -866,6 +876,8 @@ sub check_dcc_reputation_range {
# If callback, use got_hit()
if ($result) {
$pms->got_hit($cb_rulename, "", ruletype => 'eval');
+ } else {
+ $pms->rule_ready($cb_rulename);
}
return 0;
} else {
@@ -875,6 +887,7 @@ sub check_dcc_reputation_range {
# Install callback if waiting for async result
if (!defined $cb_rulename) {
my $rulename = $pms->get_current_eval_rule_name();
+ $pms->rule_pending($rulename); # mark async
# array matches check_dcc_reputation_range() argument order
push @{$pms->{dcc_range_callbacks}}, [undef, $min, $max, $rulename];
}
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DNSEval.pm Fri May 28 09:40:09 2021
@@ -394,6 +394,8 @@ sub check_rbl_backend {
return 0;
}
+ $pms->rule_pending($rule); # mark async
+
dbg("dnseval: only inspecting the following IPs: ".join(", ", @ips));
foreach my $ip (@ips) {
@@ -426,7 +428,9 @@ sub check_rbl_txt {
}
sub check_rbl_sub {
+ my ($self, $pms, $rule, $set, $subtest) = @_;
# just a dummy, check_start / init_rbl_subs handles the subs
+ $pms->rule_pending($rule); # mark async
return 0;
}
@@ -438,6 +442,8 @@ sub check_rbl_from_host {
return 0 if $self->{main}->{conf}->{skip_rbl_checks};
return 0 if !$pms->is_dns_available();
+ $pms->rule_pending($rule); # mark async
+
$self->_check_rbl_addresses($pms, $rule, $set, $rbl_server,
$subtest, $pms->all_from_addrs());
}
@@ -701,6 +707,8 @@ sub check_dns_sender {
$host = idn_to_ascii($host);
dbg("dnseval: checking A and MX for host $host");
+ $pms->rule_pending($rule); # mark async
+
$self->do_sender_lookup($pms, $rule, 'A', $host);
$self->do_sender_lookup($pms, $rule, 'MX', $host);
@@ -717,7 +725,8 @@ sub do_sender_lookup {
$pms->{async}->bgsend_and_start_lookup(
$host, $type, undef, $ent, sub {
my ($ent, $pkt) = @_;
- return if !$pkt;
+ return if !$pkt; # aborted / timed out
+ $pms->rule_ready($ent->{rulename}); # mark as run, could still hit
foreach my $answer ($pkt->answer) {
next if !$answer;
next if $answer->type ne 'A' && $answer->type ne 'MX';
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/HashBL.pm Fri May 28 09:40:09 2021
@@ -444,6 +444,8 @@ sub check_hashbl_emails {
$seen{$email} = 1;
}
+ return 0 unless @filtered_emails;
+
# Randomize order
if ($opts =~ /\bshuffle\b/) {
Mail::SpamAssassin::Util::fisher_yates_shuffle(\@filtered_emails);
@@ -453,6 +455,8 @@ sub check_hashbl_emails {
my $max = $opts =~ /\bmax=(\d+)\b/ ? $1 : 10;
$#filtered_emails = $max-1 if scalar @filtered_emails > $max;
+ $pms->rule_pending($rulename); # mark async
+
foreach my $email (@filtered_emails) {
$self->_submit_query($pms, $rulename, $email, $list, $opts, $subtest);
}
@@ -513,6 +517,8 @@ sub check_hashbl_uris {
$seen{$uri} = 1;
}
+ return 0 unless @filtered_uris;
+
# Randomize order
if ($opts =~ /\bshuffle\b/) {
Mail::SpamAssassin::Util::fisher_yates_shuffle(\@filtered_uris);
@@ -522,6 +528,8 @@ sub check_hashbl_uris {
my $max = $opts =~ /\bmax=(\d+)\b/ ? $1 : 10;
$#filtered_uris = $max-1 if scalar @filtered_uris > $max;
+ $pms->rule_pending($rulename); # mark async
+
foreach my $furi (@filtered_uris) {
$self->_submit_query($pms, $rulename, $furi, $list, $opts, $subtest);
}
@@ -608,6 +616,8 @@ sub check_hashbl_bodyre {
my $max = $opts =~ /\bmax=(\d+)\b/ ? $1 : 10;
$#matches = $max-1 if scalar @matches > $max;
+ $pms->rule_pending($rulename); # mark async
+
foreach my $match (@matches) {
$self->_submit_query($pms, $rulename, $match, $list, $opts, $subtest);
}
@@ -673,6 +683,8 @@ sub _finish_query {
return;
}
+ $pms->rule_ready($rulename); # mark rule ready for metas
+
my $dnsmatch = $ent->{subtest} ? $ent->{subtest} : qr/^127\./;
my @answer = $pkt->answer;
foreach my $rr (@answer) {
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/OneLineBodyRuleType.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/OneLineBodyRuleType.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/OneLineBodyRuleType.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/OneLineBodyRuleType.pm Fri May 28 09:40:09 2021
@@ -92,6 +92,7 @@ sub do_one_line_body_tests {
my $sub = '
my ($self, $line) = @_;
my $qrptr = $self->{main}->{conf}->{test_qrs};
+ my $hitsptr = $self->{tests_already_hit};
';
if (($conf->{tflags}->{$rulename}||'') =~ /\bmultiple\b/)
@@ -101,8 +102,8 @@ sub do_one_line_body_tests {
$max = untaint_var($max);
if ($max) {
$sub .= '
- if (exists $self->{tests_already_hit}->{q{'.$rulename.'}}) {
- return 0 if $self->{tests_already_hit}->{q{'.$rulename.'}} >= '.$max.';
+ if ($hitsptr->{q{'.$rulename.'}}) {
+ return 0 if $hitsptr->{q{'.$rulename.'}} >= '.$max.';
}
';
}
@@ -129,6 +130,10 @@ sub do_one_line_body_tests {
}
+ $sub .= '
+ $self->rule_ready(q{'.$rulename.'});
+ ';
+
return if ($opts{doing_user_rules} &&
!$self->is_user_rule_sub($rulename.'_one_line_body_test'));
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Pyzor.pm Fri May 28 09:40:09 2021
@@ -324,6 +324,7 @@ sub check_pyzor {
## forking method
$pms->{pyzor_rulename} = $pms->get_current_eval_rule_name();
+ $pms->rule_pending($pms->{pyzor_rulename}); # mark async
# create socketpair for communication
$pms->{pyzor_backchannel} = Mail::SpamAssassin::SubProcBackChannel->new();
@@ -502,6 +503,8 @@ sub _check_forked_result {
return 0;
}
+ $pms->rule_ready($pms->{pyzor_rulename}); # mark rule ready for metas
+
dbg("pyzor: child process $kid_pid finished, reading results");
my $backmsg;
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Razor2.pm Fri May 28 09:40:09 2021
@@ -443,6 +443,7 @@ sub check_razor2 {
## forking method
$pms->{razor2_rulename} = $pms->get_current_eval_rule_name();
+ $pms->rule_pending($pms->{razor2_rulename}); # mark async
# create socketpair for communication
$pms->{razor2_backchannel} = Mail::SpamAssassin::SubProcBackChannel->new();
@@ -549,6 +550,8 @@ sub _check_forked_result {
return 0;
}
+ $pms->rule_ready($pms->{razor2_rulename}); # mark rule ready for metas
+
dbg("razor2: child process $kid_pid finished, reading results");
my $backmsg;
@@ -635,16 +638,21 @@ sub check_razor2_range {
# continue.
return unless $self->{razor2_available};
return unless $self->{main}->{conf}->{use_razor2};
- return if $pms->{razor2_abort};
# Check if callback overriding rulename
if (!defined $rulename) {
$rulename = $pms->get_current_eval_rule_name();
}
+ if ($pms->{razor2_abort}) {
+ $pms->rule_ready($rulename); # mark rule ready for metas
+ return;
+ }
+
# If forked, call back later unless results are in
if ($self->{main}->{conf}->{razor_fork}) {
if (!defined $pms->{razor2_result}) {
+ $pms->rule_pending($rulename); # mark async
dbg("razor2: delaying check_razor2_range call for $rulename");
# array matches check_razor2_range() argument order
push @{$pms->{razor2_range_callbacks}},
@@ -660,6 +668,8 @@ sub check_razor2_range {
}
}
+ $pms->rule_ready($rulename); # mark rule ready for metas
+
my $cf = 0;
if ($engine) {
$cf = $pms->{razor2_cf_score}->{$engine};
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Reuse.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Reuse.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Reuse.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Reuse.pm Fri May 28 09:40:09 2021
@@ -197,6 +197,8 @@ sub check_start {
dbg("reuse: rule $rule hit, will add at priority $priority, stage " .
"$stage");
last;
+ } else {
+ $pms->rule_ready($rule);
}
}
}
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm Fri May 28 09:40:09 2021
@@ -342,6 +342,9 @@ sub new {
# this is just a placeholder; in fact the results are dealt with later
sub check_uridnsbl {
+ my ($self, $pms) = @_;
+ my $rulename = $pms->get_current_eval_rule_name();
+ $pms->rule_pending($rulename); # mark async
return 0;
}
@@ -1058,19 +1061,19 @@ sub lookup_single_dnsbl {
sub complete_dnsbl_lookup {
my ($self, $pms, $ent, $pkt) = @_;
+ my $rulename = $ent->{rulename};
+
if (!$pkt) {
# $pkt will be undef if the DNS query was aborted (e.g. timed out)
dbg("uridnsbl: complete_dnsbl_lookup aborted %s %s",
- $ent->{rulename}, $ent->{key});
+ $rulename, $ent->{key});
return;
}
- dbg("uridnsbl: complete_dnsbl_lookup $ent->{key} $ent->{rulename}");
- my $conf = $pms->{conf};
-
- my $rulename = $ent->{rulename};
- my $rulecf = $conf->{uridnsbls}->{$rulename};
+ $pms->rule_ready($rulename); # mark rule ready for metas
+ dbg("uridnsbl: complete_dnsbl_lookup $ent->{key} $rulename");
+ my $rulecf = $pms->{conf}->{uridnsbls}->{$rulename};
my @subtests;
my @answer = $pkt->answer;
foreach my $rr (@answer)
@@ -1127,7 +1130,9 @@ sub complete_dnsbl_lookup {
: sprintf('%08x%s%08x', $n1,$delim,$n2),
$match ? 'match' : 'no');
}
- $self->got_dnsbl_hit($pms, $ent, $rdatastr, $rulename) if $match;
+ if ($match) {
+ $self->got_dnsbl_hit($pms, $ent, $rdatastr, $rulename);
+ }
}
}
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URILocalBL.pm Fri May 28 09:40:09 2021
@@ -390,9 +390,13 @@ sub check_uri_local_bl {
}
}
+ return 0 unless %found_hosts;
+
# bail out now if dns not available
return 0 if !$pms->is_dns_available();
+ $pms->rule_pending($rulename); # mark async
+
foreach my $host (keys %found_hosts) {
$host = idn_to_ascii($host);
dbg("launching A/AAAA lookup for $host");
@@ -428,6 +432,8 @@ sub _finish_lookup {
return;
}
+ $pms->rule_ready($rulename); # mark rule ready for metas
+
my @answer = $pkt->answer;
my @addrs;
foreach my $rr (@answer) {
Modified: spamassassin/trunk/t/basic_meta2.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/basic_meta2.t?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/t/basic_meta2.t (original)
+++ spamassassin/trunk/t/basic_meta2.t Fri May 28 09:40:09 2021
@@ -5,23 +5,29 @@ use lib 't';
use SATest; sa_t_init("basic_meta2");
use Test::More;
-plan tests => 5;
+plan tests => 15;
# ---------------------------------------------------------------------------
%patterns = (
-
q{ TEST_FOO_1 } => '',
q{ TEST_FOO_2 } => '',
q{ TEST_FOO_3 } => '',
- q{ TEST_META_1 } => '',
-
+ q{ TEST_META_1 } => '',
+ q{ TEST_META_3 } => '',
+ q{ TEST_META_5 } => '',
+ q{ TEST_META_7 } => '',
+ q{ TEST_META_A } => '',
+ q{ TEST_META_B } => '',
);
%anti_patterns = (
-
q{ TEST_NEG_1 } => '',
-
+ q{ TEST_META_2 } => '',
+ q{ TEST_META_4 } => '',
+ q{ TEST_META_6 } => '',
+ q{ TEST_META_8 } => '',
+ q{ TEST_META_9 } => '',
);
tstlocalrules (qq{
@@ -39,6 +45,41 @@ tstlocalrules (qq{
meta TEST_META_1 (TEST_FOO_1 + TEST_FOO_2 + TEST_NEG_1) == 2
+ ##
+ ## Unrun rule dependencies (Bug 7735)
+ ##
+
+ # Non-existing rule
+ # Should not hit, meta is evaled twice: (!0) && (!1)
+ meta TEST_META_2 !NONEXISTINGRULE
+ # Should hit, meta is evaled twice: (!0 || 0) && (!1 || 1)
+ meta TEST_META_3 !NONEXISTINGRULE || NONEXISTINGRULE
+
+ # Disabled rule, same as above
+ body TEST_DISABLED /a/
+ score TEST_DISABLED 0
+ # Should not hit
+ meta TEST_META_4 !TEST_DISABLED
+ # Should hit
+ meta TEST_META_5 !TEST_DISABLED || TEST_DISABLED
+
+ # Unrun rule (due to local tests only), same as above
+ askdns TEST_DISABLED2 spamassassin.org TXT /./
+ # Should not hit
+ meta TEST_META_6 !TEST_DISABLED2
+ # Should hit
+ meta TEST_META_7 !TEST_DISABLED2 || TEST_DISABLED2
+
+ # Should not hit
+ meta TEST_META_8 __FOO_1 + NONEXISTINGRULE == 2
+ # Should not hit
+ meta TEST_META_9 __FOO_1 + NONEXISTINGRULE + __FOO_2 == 2
+ # Should hit (both eval checks are true thanks to >1)
+ meta TEST_META_A __FOO_1 + NONEXISTINGRULE + __FOO_2 > 1
+
+ # local_tests_only
+ meta TEST_META_B NONEXISTINGRULE || local_tests_only
+
});
sarun ("-L -t < data/nice/001 2>&1", \&patterns_run_cb);
Added: spamassassin/trunk/t/basic_meta_net.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/basic_meta_net.t?rev=1890274&view=auto
==============================================================================
--- spamassassin/trunk/t/basic_meta_net.t (added)
+++ spamassassin/trunk/t/basic_meta_net.t Fri May 28 09:40:09 2021
@@ -0,0 +1,88 @@
+#!/usr/bin/perl -T
+
+use lib '.';
+use lib 't';
+use SATest; sa_t_init("basic_meta_net");
+use Test::More;
+
+plan skip_all => "Net tests disabled" unless conf_bool('run_net_tests');
+plan skip_all => "Can't use Net::DNS Safely" unless can_use_net_dns_safely();
+
+plan tests => 20;
+
+# ---------------------------------------------------------------------------
+
+
+%patterns = (
+ q{ X_META_POS4 } => '',
+);
+%anti_patterns = (
+ q{ X_URIBL_A } => '',
+ q{ X_ASKDNS } => '',
+ q{ X_META_POS1 } => '',
+ q{ X_META_POS2 } => '',
+ q{ X_META_POS3 } => '',
+ q{ X_META_NEG1 } => '',
+ q{ X_META_NEG2 } => '',
+ q{ X_META_NEG3 } => '',
+ q{ X_META_NEG4 } => '',
+);
+
+#
+# Nothing should hit with a failed lookup
+#
+
+tstlocalrules (qq{
+ # Force DNS queries to fail/timeout
+ rbl_timeout 2 1
+ dns_server 240.0.0.240
+
+ urirhssub X_URIBL_A dnsbltest.spamassassin.org. A 2
+ body X_URIBL_A eval:check_uridnsbl('X_URIBL_A')
+ tflags X_URIBL_A net
+
+ askdns X_ASKDNS spamassassin.org TXT /./
+
+ meta X_META_POS1 X_URIBL_A
+ meta X_META_POS2 X_ASKDNS
+ meta X_META_POS3 X_URIBL_A || X_ASKDNS
+
+ meta X_META_NEG1 !X_URIBL_A
+ meta X_META_NEG2 !X_ASKDNS
+ meta X_META_NEG3 !X_URIBL_A || !X_ASKDNS
+
+ # local_tests_only
+ meta X_META_NEG4 local_tests_only
+ meta X_META_POS4 !local_tests_only
+});
+
+sarun ("-t < data/spam/dnsbl.eml 2>&1", \&patterns_run_cb);
+ok_all_patterns();
+
+#
+# Local only, nothing should hit as nothing is queried
+#
+
+tstlocalrules (qq{
+ urirhssub X_URIBL_A dnsbltest.spamassassin.org. A 2
+ body X_URIBL_A eval:check_uridnsbl('X_URIBL_A')
+ tflags X_URIBL_A net
+
+ askdns X_ASKDNS spamassassin.org TXT /./
+
+ meta X_META_POS1 X_URIBL_A
+ meta X_META_POS2 X_ASKDNS
+ meta X_META_POS3 X_URIBL_A || X_ASKDNS
+
+ meta X_META_NEG1 !X_URIBL_A
+ meta X_META_NEG2 !X_ASKDNS
+ meta X_META_NEG3 !X_URIBL_A || !X_ASKDNS
+
+ # local_tests_only
+ meta X_META_POS4 local_tests_only
+ meta X_META_NEG4 !local_tests_only
+});
+
+sarun ("-t -L < data/spam/dnsbl.eml", \&patterns_run_cb);
+ok_all_patterns();
+
Propchange: spamassassin/trunk/t/basic_meta_net.t
------------------------------------------------------------------------------
svn:executable = *
Modified: spamassassin/trunk/t/dcc.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/dcc.t?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/t/dcc.t (original)
+++ spamassassin/trunk/t/dcc.t Fri May 28 09:40:09 2021
@@ -9,7 +9,7 @@ use Test::More;
plan skip_all => "Net tests disabled" unless conf_bool('run_net_tests');
plan skip_all => "DCC tests disabled" unless conf_bool('run_dcc_tests');
plan skip_all => "DCC executable not found in path" unless HAS_DCC;
-plan tests => 8;
+plan tests => 16;
diag('Note: Failure may not be an SpamAssassin bug, as DCC tests can fail due to problems with the DCC servers.');
@@ -17,15 +17,17 @@ diag('Note: Failure may not be an SpamAs
# ---------------------------------------------------------------------------
%patterns = (
-
q{ spam reported to DCC }, 'dcc report',
-
);
tstprefs ("
dns_available no
use_dcc 1
+ meta X_META_POS DCC_CHECK
+ meta X_META_NEG !DCC_CHECK
score DCC_CHECK 3.3
+ score X_META_POS 3.3
+ score X_META_NEG 3.3
");
ok sarun ("-t -D info -r < data/spam/gtubedcc.eml 2>&1", \&patterns_run_cb);
@@ -34,12 +36,26 @@ ok sarun ("-t -D info -r < data/spam/gtu
ok_all_patterns();
%patterns = (
-
q{ 3.3 DCC_CHECK }, 'dcc',
-
+ q{ 3.3 X_META_POS }, 'pos',
+);
+%anti_patterns = (
+ q{ 3.3 X_META_NEG }, 'neg',
);
ok sarun ("-t < data/spam/gtubedcc.eml 2>&1", \&patterns_run_cb);
ok_all_patterns();
ok sarun ("-t < data/spam/gtubedcc_crlf.eml 2>&1", \&patterns_run_cb);
ok_all_patterns();
+
+# Local only, metas should not hit as no queries are made
+%patterns = (
+);
+%anti_patterns = (
+ q{ 3.3 DCC_CHECK }, 'dcc',
+ q{ 3.3 X_META_POS }, 'pos',
+ q{ 3.3 X_META_NEG }, 'neg',
+);
+ok sarun ("-t -L < data/spam/gtubedcc.eml 2>&1", \&patterns_run_cb);
+ok_all_patterns();
+
Modified: spamassassin/trunk/t/if_can.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/if_can.t?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/t/if_can.t (original)
+++ spamassassin/trunk/t/if_can.t Fri May 28 09:40:09 2021
@@ -2,7 +2,7 @@
use lib '.'; use lib 't';
use SATest; sa_t_init("if_can");
-use Test::More tests => 17;
+use Test::More tests => 19;
# ---------------------------------------------------------------------------
@@ -20,6 +20,7 @@ use Test::More tests => 17;
q{ SHOULD_BE_CALLED09 }, 'should_be_called09',
q{ SHOULD_BE_CALLED10 }, 'should_be_called10',
q{ SHOULD_BE_CALLED11 }, 'should_be_called11',
+ q{ SHOULD_BE_CALLED12 }, 'should_be_called12',
);
%anti_patterns = (
@@ -28,6 +29,7 @@ use Test::More tests => 17;
q{ SHOULD_NOT_BE_CALLED02 }, 'should_not_be_called02',
q{ SHOULD_NOT_BE_CALLED03 }, 'should_not_be_called03',
q{ SHOULD_NOT_BE_CALLED04 }, 'should_not_be_called04',
+ q{ SHOULD_NOT_BE_CALLED05 }, 'should_not_be_called05',
);
tstlocalrules (q{
@@ -82,6 +84,13 @@ tstlocalrules (q{
endif
endif
+ if can(Mail::SpamAssassin::Conf::feature_local_tests_only) && local_tests_only
+ body SHOULD_BE_CALLED12 /./
+ endif
+ if can(Mail::SpamAssassin::Conf::feature_local_tests_only) && !local_tests_only
+ body SHOULD_NOT_BE_CALLED05 /./
+ endif
+
});
ok (sarun ("-L -t < data/spam/gtube.eml", \&patterns_run_cb));
Modified: spamassassin/trunk/t/priorities.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/priorities.t?rev=1890274&r1=1890273&r2=1890274&view=diff
==============================================================================
--- spamassassin/trunk/t/priorities.t (original)
+++ spamassassin/trunk/t/priorities.t Fri May 28 09:40:09 2021
@@ -83,8 +83,8 @@ ok assert_rule_pri 'FOO1', -28;
sub assert_rule_pri {
my ($r, $pri) = @_;
- if (defined $conf->{rbl_evals}->{$r}) {
- # ignore rbl_evals; they do not use the priority system at all
+ if (defined $conf->{rbl_evals}->{$r} || defined $conf->{meta_tests}->{$r}) {
+ # ignore rbl_evals and metas; they do not use the priority system at all
return 1;
}