From b071fb109c59278a99fa1dd1fed8dcffb3ac4627 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 7 Nov 2026 17:55:24 -0800 Subject: [PATCH] Plug-ins: the host import fuzz test reaches vc_log's text checks The fuzz test for hostile host import arguments drew vc_log's level from every i32, so almost every call stopped at the level check and never read memory. Levels are now also drawn from -1 to 4. The module docs, a test doc comment and docs/plugins.md now say that with an unknown total each change of done is passed on. --- crates/engine/tests/plugin_fuzz.rs | 2 +- crates/plugins/src/host.rs | 13 +++++++------ docs/plugins.md | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/engine/tests/plugin_fuzz.rs b/crates/engine/tests/plugin_fuzz.rs index 1d6f8de31..1791555f7 100644 --- a/crates/engine/tests/plugin_fuzz.rs +++ b/crates/engine/tests/plugin_fuzz.rs @@ -329,7 +329,7 @@ proptest! { prop_oneof![ (any::(), any::()).prop_map(|(d, t)| format!("(call $vc_progress (i64.const {d}) (i64.const {t}))")), Just("(drop (call $vc_cancelled))".to_string()), - (any::(), prop_oneof![any::(), 0x1ff00..0x20100i32], prop_oneof![any::(), 0..5000i32]) + (prop_oneof![any::(), -1..5i32], prop_oneof![any::(), 0x1ff00..0x20100i32], prop_oneof![any::(), 0..5000i32]) .prop_map(|(l, p, n)| format!("(drop (call $vc_log (i32.const {l}) (i32.const {p}) (i32.const {n})))")), ], 0..24, diff --git a/crates/plugins/src/host.rs b/crates/plugins/src/host.rs index 83e81dc8c..f47d8e69b 100644 --- a/crates/plugins/src/host.rs +++ b/crates/plugins/src/host.rs @@ -5,11 +5,11 @@ //! the module is loaded ([`check_imports`], [`check_granted`]): one it doesn't offer, one with //! another signature and one the manifest doesn't allow are refused by name. //! -//! Each call's arguments are checked: progress is clamped and passed on at most once per tenth of -//! a percent (and, past [`MAX_PROGRESS_REPORTS`], once per [`PROGRESS_STRIDE`] changes), log text -//! must lie inside the module's memory and be UTF-8, and each line ([`MAX_LOG_LINE`]) and each run -//! ([`MAX_LOG_LINES`], [`MAX_LOG_BYTES`], [`MAX_LOG_READ`]) are capped. Nothing a module passes can -//! panic the host. +//! Each call's arguments are checked: progress is clamped and passed on only when it changes (with +//! a known total, to another tenth of a percent; past [`MAX_PROGRESS_REPORTS`], once per +//! [`PROGRESS_STRIDE`] changes), log text must lie inside the module's memory and be UTF-8, and +//! each line ([`MAX_LOG_LINE`]) and each run ([`MAX_LOG_LINES`], [`MAX_LOG_BYTES`], +//! [`MAX_LOG_READ`]) are capped. Nothing a module passes can panic the host. use wasmi::{Caller, Engine, Extern, ExternType, Linker, Module, StoreLimits, ValType}; @@ -358,7 +358,8 @@ mod tests { } } - /// Reports are passed on once per tenth of a percent at most, whatever the total, and past + /// Reports are passed on only when they change (with a known total, to another tenth of a + /// percent, however the total changes; with an unknown total, each change of `done`), and past /// [`MAX_PROGRESS_REPORTS`] once per [`PROGRESS_STRIDE`] changes, except the first after the /// total becomes known; the last one is always kept. #[test] diff --git a/docs/plugins.md b/docs/plugins.md index 0aba62c08..011515406 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -195,10 +195,10 @@ still returns `1`. - A filter's or an exporter's progress is shown as a share: a heavy filter's progress window and the export's progress window draw a bar with a percentage, and Cancel there makes `vc_cancelled` return `1`. A plug-in that checks it can stop early, and the host discards what it returns after the Cancel or after its time budget ran out; one that - ignores it is still stopped by the instruction and time budgets. Progress is passed on at most - once per tenth of a percent; after 2,000 reports in a run, one change in 1,000 is passed on, and so is the first - report after the total becomes known or unknown. A live effect's progress is not shown, since it is drawn as part of - something else. + ignores it is still stopped by the instruction and time budgets. With a known total, a report is passed on only when + it reaches another tenth of a percent; with an unknown total, each change of `done` is passed on. After 2,000 reports + in a run, one change in 1,000 is passed on, and so is the first report after the total becomes known or unknown. A + live effect's progress is not shown, since it is drawn as part of something else. - Log lines go to the app's log (target `vectorcraft_plugins`) as `: `, with control and bidirectional characters escaped. The whole text must be UTF-8. A line shows its first 1,024 bytes, as at most 1,024 characters with the escapes, and ends with `…` when it is cut. A run writes at most 200 lines and 32 KiB of shown