kobako 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd12a974208b6d2ef80dd443bf6a57c66295db8ee79624691a7d2ffe3dd1ec3d
4
- data.tar.gz: b54a381dd914fabc424a6a9784800fcc5277dbd2e1dc4a2c278c11306b12ba46
3
+ metadata.gz: ac6c01cd421449a5b87d4a21777b257a204018747d468481ff309382d08f8a89
4
+ data.tar.gz: 2c172f0ffb8d0cb600bc8837102e584ca4492f1f59ce8d77989169d078976bb0
5
5
  SHA512:
6
- metadata.gz: 3fe7c845ce6a0570904454600fc90e1c149562422dd71c654c1653b7bbbd90962437e28461c5f02a2c7639ab567d924e4f45da4c3d0f4485c9a943d3af630b9b
7
- data.tar.gz: be6770e7a751d1243b7b719da70d7d0b4cef850f46d0018eb1b0f339502911376aa5ba793513fcf8fd79806f1b61aae34ff4abfa03ad9a5e6eab0fbdf93179b3
6
+ metadata.gz: 88fb3c50f8e631dbe6139ef9f8ab5e5ad50f4ee08a2aec0b8cdbba5e70c9670fb78c24e80a59916daa23ce6e9663f73ba82ad26c78e69588f59e91c72a4b1cf9
7
+ data.tar.gz: 1eacade67c1ddc6de4fa8a75e5975272157ea2e08c55dcb5c790eb3528941b3b96091f3695b60389d5c93d75599b04ff99a1af530530971f2765a94b101c3f57
@@ -1 +1 @@
1
- {".":"0.6.2"}
1
+ {".":"0.7.0"}
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.7.0](https://github.com/elct9620/kobako/compare/v0.6.2...v0.7.0) (2026-06-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * **examples/async-io:** demo single-thread I/O overlap across Sandboxes ([858a0f7](https://github.com/elct9620/kobako/commit/858a0f70bb0730e5e3ad3f49a5caadf948f6ed7d))
9
+ * **guest:** reject construction of Handle proxies (B-39) ([bda5e2b](https://github.com/elct9620/kobako/commit/bda5e2b5e48fe25adeefac19c47f1b93585091bf))
10
+ * **guest:** reject construction of Member proxies (B-38) ([885c281](https://github.com/elct9620/kobako/commit/885c2812da8627e4ec7c185d9e04e4056c94a7fd))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **ext:** surface the buried root cause on non-cap traps ([dbd1ce5](https://github.com/elct9620/kobako/commit/dbd1ce51f25ab8c83d39daee64278192d763d5ef))
16
+ * **guest:** bound the encoder walk so cycles and deep nesting fail cleanly ([90880ff](https://github.com/elct9620/kobako/commit/90880ffe6f0ee911b3c7c076ef6c86b9e08c62e1))
17
+ * **guest:** stop an embedded NUL in a returned value from hard-trapping ([14fbb97](https://github.com/elct9620/kobako/commit/14fbb97ecb47b4263585602754e92237bb951d46))
18
+ * **guest:** stop named-capture regexes from hard-trapping the sandbox ([a279ea1](https://github.com/elct9620/kobako/commit/a279ea1e2f196580b396342851e4e75ff9ea5cfa))
19
+
3
20
  ## [0.6.2](https://github.com/elct9620/kobako/compare/v0.6.1...v0.6.2) (2026-05-31)
4
21
 
5
22
 
data/Cargo.lock CHANGED
@@ -864,7 +864,7 @@ dependencies = [
864
864
 
865
865
  [[package]]
866
866
  name = "kobako"
867
- version = "0.6.2"
867
+ version = "0.7.0"
868
868
  dependencies = [
869
869
  "magnus",
870
870
  "wasmtime",
data/data/kobako.wasm CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "kobako"
3
- version = "0.6.2"
3
+ version = "0.7.0"
4
4
  edition = "2021"
5
5
  authors = ["Aotokitsuruya <contact@aotoki.me>"]
6
6
  license = "Apache-2.0"
@@ -76,8 +76,9 @@ fn classify_trap(err: &wasmtime::Error) -> TrapClass {
76
76
  /// `"linear memory growth exceeded memory_limit: ..."`). The wasmtime
77
77
  /// outer wrapper at `format!("{}", err)` would otherwise surface only
78
78
  /// the `"error while executing at wasm backtrace: ..."` framing, which
79
- /// is operator noise on a cap trap. For `TrapClass::Other` the
80
- /// wasmtime wrapper IS the diagnostic (real script trap) so it stays.
79
+ /// is operator noise on a cap trap. For `TrapClass::Other` the framing
80
+ /// is kept but the chain's root cause is appended (see
81
+ /// `other_trap_message`) so the real trap reason survives.
81
82
  pub(super) fn call_err(ruby: &Ruby, err: wasmtime::Error) -> MagnusError {
82
83
  match classify_trap(&err) {
83
84
  TrapClass::Timeout => {
@@ -94,7 +95,24 @@ pub(super) fn call_err(ruby: &Ruby, err: wasmtime::Error) -> MagnusError {
94
95
  .unwrap_or_else(|| format!("{}", err));
95
96
  memory_limit_err(ruby, msg)
96
97
  }
97
- TrapClass::Other => trap_err(ruby, format!("{}", err)),
98
+ TrapClass::Other => trap_err(ruby, other_trap_message(&err)),
99
+ }
100
+ }
101
+
102
+ /// Compose the message for a non-cap trap. wasmtime's `Display` surfaces only
103
+ /// the `"error while executing at wasm backtrace: ..."` framing; the actual
104
+ /// trap reason (e.g. `"wasm trap: indirect call type mismatch"`) is the
105
+ /// chain's root cause and would otherwise be dropped, making real guest
106
+ /// faults undiagnosable. Append the root cause unless the framing already
107
+ /// carries it. Pure so it can be exercised from `cargo test` without the
108
+ /// magnus surface.
109
+ fn other_trap_message(err: &wasmtime::Error) -> String {
110
+ let display = format!("{}", err);
111
+ let root = err.root_cause().to_string();
112
+ if display.contains(&root) {
113
+ display
114
+ } else {
115
+ format!("{display}\n\n{root}")
98
116
  }
99
117
  }
100
118
 
@@ -111,7 +129,7 @@ pub(super) fn instantiate_err(ruby: &Ruby, err: wasmtime::Error) -> MagnusError
111
129
 
112
130
  #[cfg(test)]
113
131
  mod tests {
114
- use super::{classify_trap, TrapClass};
132
+ use super::{classify_trap, other_trap_message, TrapClass};
115
133
  use crate::runtime::invocation::{MemoryLimitTrap, TimeoutTrap};
116
134
 
117
135
  #[test]
@@ -131,4 +149,30 @@ mod tests {
131
149
  let err = wasmtime::Error::msg("some other wasmtime fault");
132
150
  assert_eq!(classify_trap(&err), TrapClass::Other);
133
151
  }
152
+
153
+ // A guest hard trap reaches the host as a wasmtime error whose Display is
154
+ // only the backtrace framing, with the trap reason buried as the chain's
155
+ // root cause. The named-capture regex bug surfaced as exactly this shape.
156
+ #[test]
157
+ fn other_trap_message_surfaces_buried_trap_reason() {
158
+ let err = wasmtime::Error::msg("wasm trap: indirect call type mismatch")
159
+ .context("error while executing at wasm backtrace:\n 0: 0x1 - <unknown>");
160
+ let msg = other_trap_message(&err);
161
+ assert!(
162
+ msg.contains("indirect call type mismatch"),
163
+ "a non-cap trap surfaced through Kobako::TrapError must carry the root trap reason, not only the backtrace framing; got: {msg}"
164
+ );
165
+ assert!(
166
+ msg.contains("error while executing"),
167
+ "a non-cap trap surfaced through Kobako::TrapError must keep the wasm backtrace framing; got: {msg}"
168
+ );
169
+ }
170
+
171
+ // A flat error (no cause chain) is its own root_cause; appending it would
172
+ // duplicate the whole message.
173
+ #[test]
174
+ fn other_trap_message_does_not_duplicate_a_flat_error() {
175
+ let err = wasmtime::Error::msg("plain fault");
176
+ assert_eq!(other_trap_message(&err), "plain fault");
177
+ }
134
178
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kobako
4
- VERSION = "0.6.2"
4
+ VERSION = "0.7.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kobako
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aotokitsuruya