string compared each key against every source, but its break on a match
only left the loop over sources, so the next key overwrote the result:
string :is "a" ["a", "b"] was false while ["b", "a"] was true. RFC 5229
makes a test true when any key matches. It now stops at the first match.
date :regex and currentdate :regex called the :matches comparator, so a
regular expression was read as a wildcard pattern and "^20[0-9]{2}$"
never matched a year. They now use the regex comparator, with its size
limit and cache, like every other test.
sieve_tests_match_any_key_and_regex_dates in crates/common covers both
and fails without the fix. Upstream's svtests (restored in full) pass.
4.6 KiB
sieve-rs, vendored
The published sieve-rs 0.7.3, taken
from crates.io under AGPL-3.0-only, with the upstream project's name taken
out of the identifiers it spells into the Sieve language (docs/spec/SPEC.md
§2.4). The root Cargo.toml patches it in with [patch.crates-io].
Changes
Every changed file carries the AGPL 5(a) notice in its header.
src/compiler/grammar/mod.rs: the extensions scriptsrequireand ManageSieve advertises arevnd.inbuxa.whileandvnd.inbuxa.expressions. The pre-renamevnd.stalwart.*spellings are still accepted, never advertised, so a script written for upstream compiles when it's edited. Without them, the name is treated as an unknown extension andletorevalfails with "Undeclared capability". Thelegacy_extension_namestests cover both.src/runtime/mod.rs: the defaultenvironment "name"isinbuxa Sieve(the server sets its own name on both of its runtimes anyway), and the test-only capability isvnd.inbuxa.testsuite.src/lib.rs: the test-suite environment variables arevnd.inbuxa.*.src/runtime/tests/comparator.rs,src/compiler/grammar/mod.rs: every:regexpattern is built throughbuild_regex, which holds the compiled matcher and its lazy DFA to 1 MiB each (fancy-regex's default is 10 MiB), and a pattern built from variables is compiled once per run (RegexCache, 32 patterns, a field ofContextinsrc/lib.rsandsrc/runtime/context.rs) instead of once for every value it is tested against. Every caller ofComparator::regexpasses the cache. Thesieve_regexes_are_size_limitedandsieve_variable_patterns_compile_oncetests incrates/commoncover both.src/runtime/context.rs,src/lib.rs,src/runtime/tests/test_header.rs,test_address.rs,test_body.rs,test_string.rs,test_exists.rs,src/runtime/actions/action_editheader.rs: the bytes that tests scan count against the cpu limit, one instruction for every 64 KiB (SCAN_BYTES_PER_INSTRUCTION). Header, address, body and string tests anddeleteheadercharge each value they compare times the number of keys, and every search for a header charges the part's header block; the total isContext::scanned_bytes. A test stops scanning once the run is over the limit, and the run fails withCPULimitReachedas it does for too many instructions (deleteheaderthen deletes nothing). Thescan_limit_testsincontext.rscover it; they run from this directory withcargo test --offline --target-dir ../../target/sieve-rs-tests scan_limit(the crate'stest_suiteandparse_rfcneed upstream'stests/, which isn't kept).src/runtime/actions/action_vacation.rs,action_notify.rs: vacation and notify stay silent for mail withAuto-Submittedother thanno(RFC 3834). Upstream looked for the header asHeaderName::Other, but mail-parser 0.11 parses it asHeaderName::AutoSubmitted, so the check never ran and both answered other programs' mail, autoresponders included. Upstream 0.7.3 fails its own svtests "No reply to auto-submitted mail" and "Notifying on automated messages" for this reason. Thesieve_auto_submitted_mail_gets_no_replytest incrates/commoncovers it.src/runtime/tests/test_string.rs:stringis true when any key matches any source. Upstream'sbreakon a match only left the loop over sources, so the next key overwrote the result:string :is "a" ["a", "b"]was false while["b", "a"]was true.src/runtime/tests/test_date.rs:date :regexandcurrentdate :regexcompare with the regex comparator (through the same size limit and cache); upstream compared them as:matcheswildcard patterns, so"^20[0-9]{2}$"never matched a year. Thesieve_tests_match_any_key_and_regex_datestest incrates/commoncovers both.Cargo.toml: the example target is dropped, with the top-levelexamples/andtests/, which the server never builds. (src/keeps its owntestsmodules: the crate declares them.)
Updating
When the server's Cargo.lock moves sieve-rs to a new version, Cargo stops
using this copy and only warns that the patch went unused. The unit test
sieve_extensions_carry_the_fork_name in crates/common fails when that
happens. Re-vendor the new version from ~/.cargo/registry/src/*/sieve-rs-*,
dropping the top-level tests/ and examples/ (only those: rsync --exclude /tests --exclude /examples), Cargo.lock and Cargo.toml.orig, repeat
the changes above, and update the version here and in the root Cargo.toml
comment. tools/fork/name-check.py covers vendor/ too, so a rename missed
in a new version fails CI.