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 +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +18 -0
- data/Cargo.lock +4 -4
- data/crates/kobako-runtime/CHANGELOG.md +7 -0
- data/crates/kobako-runtime/Cargo.toml +2 -2
- data/crates/kobako-runtime/README.md +1 -1
- data/crates/kobako-transport/CHANGELOG.md +7 -0
- data/crates/kobako-transport/Cargo.toml +1 -1
- data/crates/kobako-transport/README.md +1 -1
- data/crates/kobako-wasmtime/CHANGELOG.md +7 -0
- data/crates/kobako-wasmtime/Cargo.toml +3 -3
- data/crates/kobako-wasmtime/README.md +1 -1
- data/data/kobako.wasm +0 -0
- data/ext/kobako/Cargo.toml +1 -1
- data/lib/kobako/codec/encoder.rb +4 -13
- data/lib/kobako/codec/handle_walk.rb +1 -1
- data/lib/kobako/codec/nesting.rb +43 -0
- data/lib/kobako/codec.rb +4 -2
- data/lib/kobako/transport/dispatcher.rb +1 -0
- data/lib/kobako/transport/run.rb +5 -2
- data/lib/kobako/transport/yielder.rb +6 -4
- data/lib/kobako/version.rb +1 -1
- data/sig/kobako/codec/nesting.rbs +9 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c0c1c827c03774c7feb9dcb7ff38a4e070203a94abff75c0f76c37f95368ac46
|
|
4
|
+
data.tar.gz: 696243ed20eb3354c2f8f545be8a52844a84a5cde353d6a177acba4d5378d017
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0628a560a80d649b8b8a40731d688253466b574cd88456fc69900815bb18444a50958364b8a8d8c99ef19244ad0c90ca7730cbde07d41d90a304a035377a23f
|
|
7
|
+
data.tar.gz: 8e2ca842efc9529f06840463db63e85823de7dbaac7b91613f6bf198a96e3b012cb36c589ca64d9603a11add54574458d4116e801694c3d0f27cbb99c2403ca4
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{".":"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.
|
|
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.
|
|
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.
|
|
879
|
+
version = "0.16.0"
|
|
880
880
|
|
|
881
881
|
[[package]]
|
|
882
882
|
name = "kobako-wasmtime"
|
|
883
|
-
version = "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.
|
|
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.
|
|
30
|
+
kobako-transport = { version = "0.16.0", path = "../kobako-transport" }
|
|
@@ -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
|
|
|
@@ -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.
|
|
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.
|
|
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.
|
|
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`
|
data/data/kobako.wasm
CHANGED
|
Binary file
|
data/ext/kobako/Cargo.toml
CHANGED
data/lib/kobako/codec/encoder.rb
CHANGED
|
@@ -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
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
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
|
|
33
|
-
#
|
|
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)
|
data/lib/kobako/transport/run.rb
CHANGED
|
@@ -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.
|
|
98
|
-
# set
|
|
99
|
-
# the
|
|
100
|
-
# class it
|
|
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}"
|
data/lib/kobako/version.rb
CHANGED
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.
|
|
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
|