-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolving transitive dependencies of WIT exports #208
Comments
Nice writeup and analysis! I think you're right that we should reject that world. What took me a sec was how to precisely state the criteria/rationale for rejection. I think it might be this: if we say that the semantics of a Wit interface is a component type that represents (type $anonymous_interface (component
(import (interface "foo:bar/a") (instance $a (export "name" (type (sub resource)))))
(alias export $a "name" (type $name))
(import (interface "foo:bar/b") (instance $b (export "name" (type (eq $name)))))
(alias export $b "name" (type $name2))
(export "name" (instance
(export "name" (type (eq $name)))
(export "name2" (type (eq $name2)))
))
)) (Attempting to import |
This commit is a fix for the issue described in WebAssembly/component-model#208. The process of elaborating a world's exports is no longer as straightforward as imports and additionally is no longer infallible. Instead metadata is tracked to ensure that transitively added imports are always used as imports and never both as imports and exports.
Yeah that sounds right to me, and it's actually what the fuzzer ended up catching. Part of the creation of a component using resources implicitly assumed that two imports of a resource were the same (they had an In any case bytecodealliance/wasm-tools#1081 implements the idea here to reject more worlds. |
This commit is a fix for the issue described in WebAssembly/component-model#208. The process of elaborating a world's exports is no longer as straightforward as imports and additionally is no longer infallible. Instead metadata is tracked to ensure that transitively added imports are always used as imports and never both as imports and exports.
This commit is a fix for the issue described in WebAssembly/component-model#208. The process of elaborating a world's exports is no longer as straightforward as imports and additionally is no longer infallible. Instead metadata is tracked to ensure that transitively added imports are always used as imports and never both as imports and exports.
This commit fully integrates resource types in the component model with the `wit-component` crate, implementing features such as: * A WIT package using `resource` types can now be round-tripped through its WebAssembly encoding. This enables use cases such as `wit-bindgen` which embed type information in custom sections of core wasm binaries produced by native compilers. * Core modules can be lifted into components and the component can use resources. This provides a target for `wit-bindgen` and other code generators to use when generating guest code. Resource intrinsics and destructors are all available to the core wasm as desired. * WIT can be inferred from components using resources, where functions are represented as `resource`-related functions in WIT. * The `roundtrip-wit` fuzzer is extended with resources support meaning all of the above support will be fuzzed on OSS-Fuzz. This required a number of refactorings in `wit-component` especially around how type information was handled. Previous processing was a bit fast-and-loose because where exactly a type was defined didn't really matter since everything was nominal. With resource types, however, definition locations are significant and this required some fixes to previous processing. One example of this is that WebAssembly/component-model#208 was discovered through this work and the fixes required were implemented previously and further handled here in `wit-component`. Overall this PR has been almost exclusively fuzz-driven in its development. I started out with the bare bones of getting simple components working with resources being imported and exported, then added fuzzing support to `wit-smith`, then let the fuzzer go wild. Quite a few issues were discovered which led to all of the refactorings and processing here in this PR. I definitely won't claim that this is a simplification at all to `wit-component` by any measure. Rather it's taking a complicated codebase and making it more complicated. In my mind though the "saving grace" is that I'm pretty confident in the testing/fuzzing story here. It's relatively easy to isolate issues and add test cases for the various things that can crop up and the fuzzer has quite good coverage of all the various paths through `wit-component`. All that's to say that this is surely not the "best" or easiest to understand implementation of resources, but it's intended to be sufficient for now.
This commit is a fix for the issue described in WebAssembly/component-model#208. The process of elaborating a world's exports is no longer as straightforward as imports and additionally is no longer infallible. Instead metadata is tracked to ensure that transitively added imports are always used as imports and never both as imports and exports.
#1081) * Reject worlds with interfaces that can access both imports and exports This commit is a fix for the issue described in WebAssembly/component-model#208. The process of elaborating a world's exports is no longer as straightforward as imports and additionally is no longer infallible. Instead metadata is tracked to ensure that transitively added imports are always used as imports and never both as imports and exports. * Update error message
This commit fully integrates resource types in the component model with the `wit-component` crate, implementing features such as: * A WIT package using `resource` types can now be round-tripped through its WebAssembly encoding. This enables use cases such as `wit-bindgen` which embed type information in custom sections of core wasm binaries produced by native compilers. * Core modules can be lifted into components and the component can use resources. This provides a target for `wit-bindgen` and other code generators to use when generating guest code. Resource intrinsics and destructors are all available to the core wasm as desired. * WIT can be inferred from components using resources, where functions are represented as `resource`-related functions in WIT. * The `roundtrip-wit` fuzzer is extended with resources support meaning all of the above support will be fuzzed on OSS-Fuzz. This required a number of refactorings in `wit-component` especially around how type information was handled. Previous processing was a bit fast-and-loose because where exactly a type was defined didn't really matter since everything was nominal. With resource types, however, definition locations are significant and this required some fixes to previous processing. One example of this is that WebAssembly/component-model#208 was discovered through this work and the fixes required were implemented previously and further handled here in `wit-component`. Overall this PR has been almost exclusively fuzz-driven in its development. I started out with the bare bones of getting simple components working with resources being imported and exported, then added fuzzing support to `wit-smith`, then let the fuzzer go wild. Quite a few issues were discovered which led to all of the refactorings and processing here in this PR. I definitely won't claim that this is a simplification at all to `wit-component` by any measure. Rather it's taking a complicated codebase and making it more complicated. In my mind though the "saving grace" is that I'm pretty confident in the testing/fuzzing story here. It's relatively easy to isolate issues and add test cases for the various things that can crop up and the fuzzer has quite good coverage of all the various paths through `wit-component`. All that's to say that this is surely not the "best" or easiest to understand implementation of resources, but it's intended to be sufficient for now.
This commit fully integrates resource types in the component model with the `wit-component` crate, implementing features such as: * A WIT package using `resource` types can now be round-tripped through its WebAssembly encoding. This enables use cases such as `wit-bindgen` which embed type information in custom sections of core wasm binaries produced by native compilers. * Core modules can be lifted into components and the component can use resources. This provides a target for `wit-bindgen` and other code generators to use when generating guest code. Resource intrinsics and destructors are all available to the core wasm as desired. * WIT can be inferred from components using resources, where functions are represented as `resource`-related functions in WIT. * The `roundtrip-wit` fuzzer is extended with resources support meaning all of the above support will be fuzzed on OSS-Fuzz. This required a number of refactorings in `wit-component` especially around how type information was handled. Previous processing was a bit fast-and-loose because where exactly a type was defined didn't really matter since everything was nominal. With resource types, however, definition locations are significant and this required some fixes to previous processing. One example of this is that WebAssembly/component-model#208 was discovered through this work and the fixes required were implemented previously and further handled here in `wit-component`. Overall this PR has been almost exclusively fuzz-driven in its development. I started out with the bare bones of getting simple components working with resources being imported and exported, then added fuzzing support to `wit-smith`, then let the fuzzer go wild. Quite a few issues were discovered which led to all of the refactorings and processing here in this PR. I definitely won't claim that this is a simplification at all to `wit-component` by any measure. Rather it's taking a complicated codebase and making it more complicated. In my mind though the "saving grace" is that I'm pretty confident in the testing/fuzzing story here. It's relatively easy to isolate issues and add test cases for the various things that can crop up and the fuzzer has quite good coverage of all the various paths through `wit-component`. All that's to say that this is surely not the "best" or easiest to understand implementation of resources, but it's intended to be sufficient for now.
This commit fully integrates resource types in the component model with the `wit-component` crate, implementing features such as: * A WIT package using `resource` types can now be round-tripped through its WebAssembly encoding. This enables use cases such as `wit-bindgen` which embed type information in custom sections of core wasm binaries produced by native compilers. * Core modules can be lifted into components and the component can use resources. This provides a target for `wit-bindgen` and other code generators to use when generating guest code. Resource intrinsics and destructors are all available to the core wasm as desired. * WIT can be inferred from components using resources, where functions are represented as `resource`-related functions in WIT. * The `roundtrip-wit` fuzzer is extended with resources support meaning all of the above support will be fuzzed on OSS-Fuzz. This required a number of refactorings in `wit-component` especially around how type information was handled. Previous processing was a bit fast-and-loose because where exactly a type was defined didn't really matter since everything was nominal. With resource types, however, definition locations are significant and this required some fixes to previous processing. One example of this is that WebAssembly/component-model#208 was discovered through this work and the fixes required were implemented previously and further handled here in `wit-component`. Overall this PR has been almost exclusively fuzz-driven in its development. I started out with the bare bones of getting simple components working with resources being imported and exported, then added fuzzing support to `wit-smith`, then let the fuzzer go wild. Quite a few issues were discovered which led to all of the refactorings and processing here in this PR. I definitely won't claim that this is a simplification at all to `wit-component` by any measure. Rather it's taking a complicated codebase and making it more complicated. In my mind though the "saving grace" is that I'm pretty confident in the testing/fuzzing story here. It's relatively easy to isolate issues and add test cases for the various things that can crop up and the fuzzer has quite good coverage of all the various paths through `wit-component`. All that's to say that this is surely not the "best" or easiest to understand implementation of resources, but it's intended to be sufficient for now.
* Add support for resources to `wit-component` This commit fully integrates resource types in the component model with the `wit-component` crate, implementing features such as: * A WIT package using `resource` types can now be round-tripped through its WebAssembly encoding. This enables use cases such as `wit-bindgen` which embed type information in custom sections of core wasm binaries produced by native compilers. * Core modules can be lifted into components and the component can use resources. This provides a target for `wit-bindgen` and other code generators to use when generating guest code. Resource intrinsics and destructors are all available to the core wasm as desired. * WIT can be inferred from components using resources, where functions are represented as `resource`-related functions in WIT. * The `roundtrip-wit` fuzzer is extended with resources support meaning all of the above support will be fuzzed on OSS-Fuzz. This required a number of refactorings in `wit-component` especially around how type information was handled. Previous processing was a bit fast-and-loose because where exactly a type was defined didn't really matter since everything was nominal. With resource types, however, definition locations are significant and this required some fixes to previous processing. One example of this is that WebAssembly/component-model#208 was discovered through this work and the fixes required were implemented previously and further handled here in `wit-component`. Overall this PR has been almost exclusively fuzz-driven in its development. I started out with the bare bones of getting simple components working with resources being imported and exported, then added fuzzing support to `wit-smith`, then let the fuzzer go wild. Quite a few issues were discovered which led to all of the refactorings and processing here in this PR. I definitely won't claim that this is a simplification at all to `wit-component` by any measure. Rather it's taking a complicated codebase and making it more complicated. In my mind though the "saving grace" is that I'm pretty confident in the testing/fuzzing story here. It's relatively easy to isolate issues and add test cases for the various things that can crop up and the fuzzer has quite good coverage of all the various paths through `wit-component`. All that's to say that this is surely not the "best" or easiest to understand implementation of resources, but it's intended to be sufficient for now. * add basic ABI/bindgen support for resources These additions are needed for `wit-bindgen` guest binding generation. Signed-off-by: Joel Dice <[email protected]> * Update expected fuzz error message --------- Signed-off-by: Joel Dice <[email protected]> Co-authored-by: Joel Dice <[email protected]>
One of the subtelties of imports and exports in WIT is that they both need to somehow resolve their transitive dependencies. For example this world:
the
bar
import transitively depends onfoo
for type information (trivially in this case but it could be more complicated too, or "significant" with resources). For the import case this is resolved by injecting more dependencies, as is evidence by runningwasm-tools component wit
over the above, printing:Despite not being written explicitly the
import foo
statement was injected automatically. More broadly all transitive dependencies of imports are injected as further imports. This works well for now and probably is the right thing to do, but the tricky part is with exports. Instead if the above world is:(note the change of
import
toexport
then what to do here is less clear. For now what happens is that the transitive dependencies are sometimes still injected as imports:If, however, the world were subtly different a different resolution is applied. If the world explicitly lists both interfaces as
export
-edthen no imports are injected. Instead it's assumed that
bar
's dependency onfoo
is satisfied by the exported interfacefoo
. More generally the algorithm here is roughly that dependencies of exports are walked and if they don't exist as an export then all futher transitive dependencies are added as imports. If the export already exists then it's assumed that's already taken care of its dependencies, so it's skipped.This strategy was intended to be a reasonable default for the time being where in the future "power user" syntax (or something like that) could be added to configure more advanced scenarios (e.g. changing these heuristics). In fuzzing resources, however, I've found that this doesn't actually work. Consider for example this world:
here the
name
kebab import depends on botha
andb
. It's also the case thatb
depends ona
. Given the above heuristics though what's happening is:name
's dependency ona
is satisfied byexport a
name
's dependency onb
is satisfied by an injectedimport b
, which in turn injects animport a
This means that
name
actually can access two different copies ofresource name
, one from the import and one from the export. This not only causes problems (hence the fuzz bug) but additionally I think isn't the desired semantics/behavior in WIT. For example ifb
defined some aggregate type that containeda
's resource then thename
export should be able to use the aggregate and the resource froma
and have them work together. Given the current lowering, though, that's not possible since they're actually different copies.Ok that's the problem statement (roughly at least). The question for me now is how to fix it? Some hard requirements that must be satisfied are, in my opinion:
One alternative I can think of is that all transitive dependencies of exports are forced to be imports. This means that it will change the meaning of a few examples I listed above. Additionally the
world w
in question here would rightfully have two copies ofa
's resource, one imported and used byexport name
and one defined locally and exported (used byexport a
). The downside of this though is that there's no means by which a resource can be defined locally and used by another export.Another alternative is to make the above
world w
simply invalid. There are two "paths" to thea
interface where one is imported and one is exported, so it's an invalid world as a result. The fix would be to addexport b
to the list of exports which means thatexport name
would use both exports.I'm curious though if others have thoughts on this? I realize I could be missing something obvious by accident or something like that! As I type this all out though I'm realizing the "simply say
world w
is invalid" is probably the way to go since it doesn't close off some more interesting use cases while still making this reasonable to work with today.The text was updated successfully, but these errors were encountered: