A calendar's recurrence rules were each allowed 100,000 passes that find nothing before calcard gave up on them, counted afresh for every rule and after every instance found, and nothing bounded the total. Anyone who can put an object on a calendar (a CalDAV or JMAP upload, or an iMIP invitation the server processes) could send a few thousand components whose rules never match, such as FREQ=MONTHLY;BYMONTH=2;BYMONTHDAY=31, or rules that match rarely, and storing or processing that object cost tens of seconds of CPU. The per-period candidate check doesn't catch these: each period is small, there are just very many of them. Expansion now has one budget of 1,000,000 work units for all the rules of the object together (about 50 ms in a release build). Every pass over a period costs a unit, a pass that finds nothing a unit per 16 days it scanned, candidates looked at but not produced a unit each, and so does each time skipped while looking for the next BYHOUR/BYMINUTE/BYSECOND match. When it runs out, expansion stops the way it does at the instance limit: the object is kept and the instances found so far are indexed. The expansion also reports it, so the server logs a calendar rule expansion error naming it. Rules are no longer started once the instance limit is reached. Ordinary rules use a small part of the budget: 3,000 daily, weekly, monthly, yearly or every-leap-day instances expand as before. Test: in calcard's new budget tests, 40 rules that never match took 3,999,960 iterations on the vendored copy and a sparse daily rule 2,922,306 (both over the 1,000,000 asserted); both now stop within the budget and report it. 4,000 never-matching components (412 KB) took 13.7 s (daily), 31.7 s (yearly) and 41.8 s (monthly) in a release build, now 36 ms, 45 ms and 57 ms.
109 lines
2.9 KiB
TOML
109 lines
2.9 KiB
TOML
[workspace]
|
|
resolver = "2"
|
|
# Vendored crates are patched in below, not built as members.
|
|
exclude = ["vendor"]
|
|
members = [
|
|
"crates/main",
|
|
"crates/types",
|
|
"crates/http",
|
|
"crates/http-proto",
|
|
"crates/jmap",
|
|
"crates/jmap-proto",
|
|
"crates/email",
|
|
"crates/imap",
|
|
"crates/imap-proto",
|
|
"crates/smtp",
|
|
"crates/managesieve",
|
|
"crates/pop3",
|
|
"crates/dav-proto",
|
|
"crates/scim-proto",
|
|
"crates/scim",
|
|
"crates/dav",
|
|
"crates/groupware",
|
|
"crates/spam-filter",
|
|
"crates/nlp",
|
|
"crates/store",
|
|
"crates/coordinator",
|
|
"crates/directory",
|
|
"crates/registry",
|
|
"crates/services",
|
|
"crates/utils",
|
|
"crates/common",
|
|
"crates/trc",
|
|
"crates/migration",
|
|
"crates/features",
|
|
"tests",
|
|
]
|
|
|
|
[workspace.lints.clippy]
|
|
result_unit_err = "allow"
|
|
|
|
[profile.dev]
|
|
opt-level = 0
|
|
debug = 1
|
|
#codegen-units = 4
|
|
lto = false
|
|
incremental = true
|
|
panic = 'unwind'
|
|
debug-assertions = true
|
|
overflow-checks = false
|
|
rpath = false
|
|
|
|
[profile.release]
|
|
opt-level = 3
|
|
debug = false
|
|
codegen-units = 1
|
|
lto = true
|
|
incremental = false
|
|
panic = 'unwind'
|
|
debug-assertions = false
|
|
overflow-checks = false
|
|
rpath = false
|
|
strip = true
|
|
|
|
[profile.test]
|
|
opt-level = 0
|
|
debug = 1
|
|
#codegen-units = 16
|
|
lto = false
|
|
incremental = true
|
|
debug-assertions = true
|
|
overflow-checks = true
|
|
rpath = false
|
|
|
|
[profile.bench]
|
|
opt-level = 3
|
|
debug = false
|
|
codegen-units = 1
|
|
lto = true
|
|
incremental = false
|
|
debug-assertions = false
|
|
overflow-checks = false
|
|
rpath = false
|
|
|
|
# inbuxa: sieve-rs spells upstream's name into its Sieve extension names
|
|
# (vnd.stalwart.*), which scripts `require` and ManageSieve advertises.
|
|
# vendor/sieve-rs is the published 0.7.3 with those renamed; see its
|
|
# VENDORED.md. Re-vendor when the version in Cargo.lock moves.
|
|
#
|
|
# inbuxa: vendor/calcard is the published 0.3.14 with one work budget shared
|
|
# by all the recurrence rules an expansion runs; see its VENDORED.md.
|
|
# Re-vendor when the version in Cargo.lock moves.
|
|
#
|
|
# inbuxa: hickory and opentelemetry are upstream's patched branches, vendored
|
|
# at the commits upstream pins so builds never fetch from upstream's
|
|
# repositories; see vendor/hickory-dns/VENDORED.md and
|
|
# vendor/opentelemetry-rust/VENDORED.md.
|
|
[patch.crates-io]
|
|
sieve-rs = { path = "vendor/sieve-rs" }
|
|
calcard = { path = "vendor/calcard" }
|
|
hickory-proto = { path = "vendor/hickory-dns/hickory-proto" }
|
|
hickory-net = { path = "vendor/hickory-dns/hickory-net" }
|
|
hickory-resolver = { path = "vendor/hickory-dns/hickory-resolver" }
|
|
opentelemetry = { path = "vendor/opentelemetry-rust/opentelemetry" }
|
|
opentelemetry_sdk = { path = "vendor/opentelemetry-rust/opentelemetry_sdk" }
|
|
opentelemetry-otlp = { path = "vendor/opentelemetry-rust/opentelemetry-otlp" }
|
|
opentelemetry-proto = { path = "vendor/opentelemetry-rust/opentelemetry-proto" }
|
|
opentelemetry-http = { path = "vendor/opentelemetry-rust/opentelemetry-http" }
|
|
opentelemetry-semantic-conventions = { path = "vendor/opentelemetry-rust/opentelemetry-semantic-conventions" }
|