kobako 0.25.0 → 0.26.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: a91b58cc6bac93dda7c202271315e49d20edd866905f506d74ad5a102ca7ba1f
4
- data.tar.gz: 0205b45a1aad4a5e85be647f977d58385f4706bfbe0b02456571f73bb815f4e0
3
+ metadata.gz: c0c1c827c03774c7feb9dcb7ff38a4e070203a94abff75c0f76c37f95368ac46
4
+ data.tar.gz: 696243ed20eb3354c2f8f545be8a52844a84a5cde353d6a177acba4d5378d017
5
5
  SHA512:
6
- metadata.gz: 96b6103795bd339b1f02e792064036d0b689a519dbcd5f875c3a72c14ce77cf36c5970d51178ac780835713077673e2679db4ffb71c77b03389e69c6c6e776a2
7
- data.tar.gz: 3a3c370d95055acb91d4481785474ec26170d4ec8088730dfdcbc45edd825e3d54e99160370382e5387f490a677e9ad55c5fd74659b9bcc24a315481eb9c68ee
6
+ metadata.gz: b0628a560a80d649b8b8a40731d688253466b574cd88456fc69900815bb18444a50958364b8a8d8c99ef19244ad0c90ca7730cbde07d41d90a304a035377a23f
7
+ data.tar.gz: 8e2ca842efc9529f06840463db63e85823de7dbaac7b91613f6bf198a96e3b012cb36c589ca64d9603a11add54574458d4116e801694c3d0f27cbb99c2403ca4
@@ -1 +1 @@
1
- {".":"0.25.0","wasm/kobako-core":"0.15.0","wasm/kobako-mruby":"0.15.0","wasm/kobako-io":"0.15.0","wasm/kobako-json":"0.15.0","wasm/kobako-regexp":"0.15.0","wasm/kobako-baker":"0.15.0","crates/kobako-transport":"0.15.0","crates/kobako-codec":"0.15.0","crates/kobako-runtime":"0.15.0","crates/kobako-wasmtime":"0.15.0","crates/kobako":"0.15.0"}
1
+ {".":"0.26.0","wasm/kobako-core":"0.16.0","wasm/kobako-mruby":"0.16.0","wasm/kobako-io":"0.16.0","wasm/kobako-json":"0.16.0","wasm/kobako-regexp":"0.16.0","wasm/kobako-baker":"0.16.0","crates/kobako-transport":"0.16.0","crates/kobako-codec":"0.16.0","crates/kobako-runtime":"0.16.0","crates/kobako-wasmtime":"0.16.0","crates/kobako":"0.16.0"}
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.26.0](https://github.com/elct9620/kobako/compare/v0.25.0...v0.26.0) (2026-09-15)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * **transport:** a #run argument or keyword value whose own nesting leaves the Run payload one level past the wire's 128-level bound used to reach the guest and fail there as Kobako::SandboxError "failed to decode the invocation arguments"; it is now refused by the host before the guest runs, still as Kobako::SandboxError, with a message naming the depth bound.
9
+ * **transport:** a Service answer nesting past 128 levels used to cross the host and fail in the guest's decoder, reaching the Host App as Kobako::Transport::Error; it is now refused at the host and reaches the Host App as Kobako::ServiceError, which guest code may rescue. A yield whose arguments nest past the bound — a single yielded value already at the bound does, since the arguments travel as one list — now raises Kobako::YieldValueError inside the Service at the yield instead of failing in the guest.
10
+
11
+ ### Bug Fixes
12
+
13
+ * **transport:** measure an entrypoint argument from the Run payload that carries it ([8f76912](https://github.com/elct9620/kobako/commit/8f76912f2290ec0d8484e8ac9a64cbb48409bf1d))
14
+ * **transport:** refuse a Service's over-deep value before the host writes it ([5594542](https://github.com/elct9620/kobako/commit/5594542c7160ae2f052025545a20bafabd7e51df))
15
+
16
+
17
+ ### Performance Improvements
18
+
19
+ * **codec:** walk into a value's members only where one could be a container ([a965136](https://github.com/elct9620/kobako/commit/a965136c989251b2ed991c2824214a017122430c))
20
+
3
21
  ## [0.25.0](https://github.com/elct9620/kobako/compare/v0.24.0...v0.25.0) (2026-09-14)
4
22
 
5
23
 
data/Cargo.lock CHANGED
@@ -858,7 +858,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
858
858
 
859
859
  [[package]]
860
860
  name = "kobako"
861
- version = "0.25.0"
861
+ version = "0.26.0"
862
862
  dependencies = [
863
863
  "kobako-runtime",
864
864
  "kobako-transport",
@@ -869,18 +869,18 @@ dependencies = [
869
869
 
870
870
  [[package]]
871
871
  name = "kobako-runtime"
872
- version = "0.15.0"
872
+ version = "0.16.0"
873
873
  dependencies = [
874
874
  "kobako-transport",
875
875
  ]
876
876
 
877
877
  [[package]]
878
878
  name = "kobako-transport"
879
- version = "0.15.0"
879
+ version = "0.16.0"
880
880
 
881
881
  [[package]]
882
882
  name = "kobako-wasmtime"
883
- version = "0.15.0"
883
+ version = "0.16.0"
884
884
  dependencies = [
885
885
  "kobako-runtime",
886
886
  "kobako-transport",
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.0](https://github.com/elct9620/kobako/compare/kobako-runtime-v0.15.0...kobako-runtime-v0.16.0) (2026-09-15)
4
+
5
+
6
+ ### Miscellaneous Chores
7
+
8
+ * **kobako-runtime:** Synchronize kobako crates versions
9
+
3
10
  ## [0.15.0](https://github.com/elct9620/kobako/compare/kobako-runtime-v0.14.0...kobako-runtime-v0.15.0) (2026-09-13)
4
11
 
5
12
 
@@ -13,7 +13,7 @@
13
13
 
14
14
  [package]
15
15
  name = "kobako-runtime"
16
- version = "0.15.0"
16
+ version = "0.16.0"
17
17
  edition = "2021"
18
18
  description = "Engine-neutral host runtime contract for embedding kobako Wasm guests."
19
19
  license = "Apache-2.0"
@@ -27,4 +27,4 @@ categories = ["wasm", "virtualization"]
27
27
  # in-tree builds (and the Ruby gem, which ships both crates) resolving
28
28
  # locally.
29
29
  [dependencies]
30
- kobako-transport = { version = "0.15.0", path = "../kobako-transport" }
30
+ kobako-transport = { version = "0.16.0", path = "../kobako-transport" }
@@ -26,7 +26,7 @@ map the neutral types onto their own language surface.
26
26
 
27
27
  ```toml
28
28
  [dependencies]
29
- kobako-runtime = "0.15.0" # x-release-please-version
29
+ kobako-runtime = "0.16.0" # x-release-please-version
30
30
  ```
31
31
 
32
32
  ## License
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.0](https://github.com/elct9620/kobako/compare/kobako-transport-v0.15.0...kobako-transport-v0.16.0) (2026-09-15)
4
+
5
+
6
+ ### Miscellaneous Chores
7
+
8
+ * **kobako-transport:** Synchronize kobako crates versions
9
+
3
10
  ## [0.15.0](https://github.com/elct9620/kobako/compare/kobako-transport-v0.14.0...kobako-transport-v0.15.0) (2026-09-13)
4
11
 
5
12
 
@@ -12,7 +12,7 @@
12
12
 
13
13
  [package]
14
14
  name = "kobako-transport"
15
- version = "0.15.0"
15
+ version = "0.16.0"
16
16
  edition = "2021"
17
17
  description = "The kobako core envelope — the fixed host↔guest wire frame every assembly shares."
18
18
  license = "Apache-2.0"
@@ -35,7 +35,7 @@ the golden vectors in this crate are derived from that document.
35
35
 
36
36
  ```toml
37
37
  [dependencies]
38
- kobako-transport = "0.15.0" # x-release-please-version
38
+ kobako-transport = "0.16.0" # x-release-please-version
39
39
  ```
40
40
 
41
41
  ## License
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.0](https://github.com/elct9620/kobako/compare/kobako-wasmtime-v0.15.0...kobako-wasmtime-v0.16.0) (2026-09-15)
4
+
5
+
6
+ ### Miscellaneous Chores
7
+
8
+ * **kobako-wasmtime:** Synchronize kobako crates versions
9
+
3
10
  ## [0.15.0](https://github.com/elct9620/kobako/compare/kobako-wasmtime-v0.14.0...kobako-wasmtime-v0.15.0) (2026-09-13)
4
11
 
5
12
 
@@ -15,7 +15,7 @@
15
15
 
16
16
  [package]
17
17
  name = "kobako-wasmtime"
18
- version = "0.15.0"
18
+ version = "0.16.0"
19
19
  edition = "2021"
20
20
  description = "wasmtime implementation of the kobako host runtime contract."
21
21
  license = "Apache-2.0"
@@ -28,10 +28,10 @@ categories = ["wasm", "virtualization"]
28
28
  # The engine-neutral contract this crate implements. The version pin
29
29
  # rides the linked release group; the path keeps in-tree builds (and
30
30
  # the Ruby gem, which ships both crates) resolving locally.
31
- kobako-runtime = { version = "0.15.0", path = "../kobako-runtime" }
31
+ kobako-runtime = { version = "0.16.0", path = "../kobako-runtime" }
32
32
  # The fixed tier: the core envelope this driver shuttles and the ABI
33
33
  # values it drives the exports against.
34
- kobako-transport = { version = "0.15.0", path = "../kobako-transport" }
34
+ kobako-transport = { version = "0.16.0", path = "../kobako-transport" }
35
35
  # wasmtime — host-side embedder for kobako.wasm. We disable default-features
36
36
  # and opt back in only what kobako needs: a Cranelift-backed runtime that can
37
37
  # compile a pre-built wasm32-wasip1 module on the host triple, plus the `wat`
@@ -24,7 +24,7 @@ SDK consumes the same surface.
24
24
 
25
25
  ```toml
26
26
  [dependencies]
27
- kobako-wasmtime = "0.15.0" # x-release-please-version
27
+ kobako-wasmtime = "0.16.0" # x-release-please-version
28
28
  ```
29
29
 
30
30
  ## License
data/data/kobako.wasm CHANGED
Binary file
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "kobako"
3
- version = "0.25.0"
3
+ version = "0.26.0"
4
4
  edition = "2021"
5
5
  authors = ["Aotokitsuruya <contact@aotoki.me>"]
6
6
  license = "Apache-2.0"
@@ -31,23 +31,14 @@ module Kobako
31
31
  # same error: an integer outside i64..u64 (+RangeError+) and any
32
32
  # packer-internal +NoMethodError+.
33
33
  #
34
- # A value that nests without bound — a reference cycle necessarily
35
- # does — exhausts the packer's own recursion instead, which Ruby
36
- # reports outside +StandardError+. Mapping it keeps an unwritable
37
- # value a wire violation the dispatch boundary can answer, rather than
38
- # one that escapes every caller's rescue and traps the invocation.
39
- #
40
- # The refusal is spent once per thread: a thread that has absorbed one
41
- # such overflow aborts on the next instead of raising, and a Hash cycle
42
- # never reaches Ruby at all — the packer walks a Hash through C frames
43
- # that carry no stack guard. Bounding the walk before the packer is
44
- # handed the value is what would make the refusal repeatable.
34
+ # The caller bounds +value+'s nesting first (Nesting): the packer takes
35
+ # no depth limit and walks a list or map in frames that carry no stack
36
+ # guard, so a value nesting without end — a reference cycle necessarily
37
+ # does — exhausts the machine stack instead of raising.
45
38
  def self.encode(value)
46
39
  FACTORY.dump(value)
47
40
  rescue ::RangeError, ::NoMethodError => e
48
41
  raise UnsupportedTypeError, e.message
49
- rescue ::SystemStackError
50
- raise InvalidTypeError, "value nests deeper than this host can write (a reference cycle necessarily does)"
51
42
  end
52
43
  end
53
44
  end
@@ -95,7 +95,7 @@ module Kobako
95
95
  return unless depth > MAX_NESTING_DEPTH
96
96
 
97
97
  raise Kobako::SandboxError,
98
- "a #run argument nests deeper than #{MAX_NESTING_DEPTH} levels and " \
98
+ "a #run argument nests deeper than #{MAX_NESTING_DEPTH} levels within the Run payload and " \
99
99
  "cannot cross the sandbox boundary (possible reference cycle)"
100
100
  end
101
101
 
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "error"
4
+
5
+ module Kobako
6
+ module Codec
7
+ # The structural nesting bound
8
+ # ({docs/wire/payload-msgpack.md}[link:../../../docs/wire/payload-msgpack.md]
9
+ # § Structural Nesting Depth), checked before a value reaches the
10
+ # packer. The packer takes no depth limit and walks a list or map in
11
+ # frames that carry no stack guard, so a value it cannot finish — a
12
+ # reference cycle necessarily is one — must be refused before it is
13
+ # handed over.
14
+ module Nesting
15
+ # Raise InvalidTypeError when +value+ nests past MAX_NESTING_DEPTH; a
16
+ # value nested exactly to the bound passes.
17
+ def self.assert_within_bound!(value, depth = 0)
18
+ case value
19
+ when ::Array then assert_members_within_bound!(value, depth)
20
+ when ::Hash
21
+ assert_members_within_bound!(value.keys, depth)
22
+ assert_members_within_bound!(value.values, depth)
23
+ end
24
+ end
25
+
26
+ # Measure the members of one container at +depth+, each sitting one
27
+ # level deeper. A member is matched by class rather than asked about
28
+ # itself — it may be a BasicObject — and only one that could be a
29
+ # container is walked into.
30
+ def self.assert_members_within_bound!(members, depth)
31
+ return if members.empty?
32
+ if depth >= MAX_NESTING_DEPTH
33
+ raise InvalidTypeError,
34
+ "value nests deeper than #{MAX_NESTING_DEPTH} levels (a reference cycle necessarily does)"
35
+ end
36
+ return unless members.any?(::Enumerable)
37
+
38
+ members.grep(::Enumerable) { |member| assert_within_bound!(member, depth + 1) }
39
+ end
40
+ private_class_method :assert_members_within_bound!
41
+ end
42
+ end
43
+ end
data/lib/kobako/codec.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require_relative "codec/error"
4
4
  require_relative "codec/utils"
5
5
  require_relative "codec/handle_walk"
6
+ require_relative "codec/nesting"
6
7
  require_relative "codec/state"
7
8
  require_relative "codec/ext_types"
8
9
  require_relative "codec/encoder"
@@ -29,8 +30,9 @@ module Kobako
29
30
  module Codec
30
31
  # The maximum structural nesting depth the wire represents (the
31
32
  # MessagePack ecosystem's bound), shared with the guest +kobako_codec+
32
- # so both sides cap identically. The host→guest wrap walk refuses a
33
- # +#run+ argument nesting past it — a reference cycle necessarily does.
33
+ # so both sides cap identically. The host refuses a value nesting past
34
+ # it — a reference cycle necessarily does — before handing it to the
35
+ # packer.
34
36
  MAX_NESTING_DEPTH = 128
35
37
 
36
38
  # Bracket a decode and return the block's result together with whether
@@ -236,6 +236,7 @@ module Kobako
236
236
  # known, instead of falling to the boundary's codec floor and reporting
237
237
  # as an exchange that produced no Service outcome.
238
238
  def encode_ok(value, handler)
239
+ Kobako::Codec::Nesting.assert_within_bound!(value)
239
240
  Kobako::Codec::Encoder.encode(value)
240
241
  rescue Kobako::Codec::UnsupportedTypeError
241
242
  encode_ok(wrap_as_handle(value, handler), handler)
@@ -54,10 +54,13 @@ module Kobako
54
54
  # invocation's table, sharing the same allocator the guest→host
55
55
  # return path uses. A wrapped leaf rides as ext 0x01 in its
56
56
  # original position (docs/wire/payload-msgpack.md § ext 0x01).
57
+ # The walk starts one level down, since +args+ and +kwargs+ ride
58
+ # inside the payload document the wire's nesting bound is counted
59
+ # from.
57
60
  def payload(handler)
58
61
  Payload::Arguments.new(
59
- args: Codec::HandleWalk.deep_wrap(args, handler),
60
- kwargs: Codec::HandleWalk.deep_wrap(kwargs, handler)
62
+ args: Codec::HandleWalk.deep_wrap(args, handler, 1),
63
+ kwargs: Codec::HandleWalk.deep_wrap(kwargs, handler, 1)
61
64
  ).encode
62
65
  end
63
66
 
@@ -94,11 +94,13 @@ module Kobako
94
94
 
95
95
  private
96
96
 
97
- # Encode what the Service is yielding. A value outside the wire type
98
- # set fails here, before the guest is re-entered, and is restated so
99
- # the Service reads a refusal of its own argument rather than a codec
100
- # class it never named.
97
+ # Encode what the Service is yielding. Arguments outside the wire
98
+ # type set, or nesting past the wire's bound as one list, fail here,
99
+ # before the guest is re-entered, and are restated so the Service
100
+ # reads a refusal of its own argument rather than a codec class it
101
+ # never named.
101
102
  def encode_args(args)
103
+ Kobako::Codec::Nesting.assert_within_bound!(args)
102
104
  Kobako::Codec::Encoder.encode(args)
103
105
  rescue Kobako::Codec::Error => e
104
106
  raise YieldValueError, "Service yielded a value the block cannot receive: #{e.message}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kobako
4
- VERSION = "0.25.0"
4
+ VERSION = "0.26.0"
5
5
  end
@@ -0,0 +1,9 @@
1
+ module Kobako
2
+ module Codec
3
+ module Nesting
4
+ def self.assert_within_bound!: (untyped value, ?Integer depth) -> void
5
+
6
+ def self.assert_members_within_bound!: (Array[untyped] members, Integer depth) -> void
7
+ end
8
+ end
9
+ 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.25.0
4
+ version: 0.26.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aotokitsuruya
@@ -117,6 +117,7 @@ files:
117
117
  - lib/kobako/codec/error.rb
118
118
  - lib/kobako/codec/ext_types.rb
119
119
  - lib/kobako/codec/handle_walk.rb
120
+ - lib/kobako/codec/nesting.rb
120
121
  - lib/kobako/codec/state.rb
121
122
  - lib/kobako/codec/utils.rb
122
123
  - lib/kobako/context.rb
@@ -160,6 +161,7 @@ files:
160
161
  - sig/kobako/codec/error.rbs
161
162
  - sig/kobako/codec/ext_types.rbs
162
163
  - sig/kobako/codec/handle_walk.rbs
164
+ - sig/kobako/codec/nesting.rbs
163
165
  - sig/kobako/codec/state.rbs
164
166
  - sig/kobako/codec/utils.rbs
165
167
  - sig/kobako/context.rbs