oxidecomputer / oxidecomputer/typify
[security] maybe compile fail or running unsafe/untrust code due to Rust comments are executable in doctests
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 898
- Forks
- 114
- Avg merge
- 4h 18m
- Merged PRs (30d)
- 14
Description
bug
[security] maybe compile fail or running unsafe/untrust code due to Rust comments are executable in doctests
reproduce
use std::collections::HashMap;
pub mod generated {
typify::import_types!(schema = "./src/schema.json");
}
pub fn minimal_reproduce_library() -> String {
format!(
"{:?} {:?}",
generated::Tmpfs(HashMap::default()),
generated::PoC(HashMap::default())
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = minimal_reproduce_library();
assert_eq!(result, "Tmpfs({}) PoC({})");
}
}
`./src/schema.yaml`
$defs:
Tmpfs:
type: "object"
description: |
A map of container directories which should be replaced by tmpfs
mounts, and their corresponding mount options. For example:
```
{ "/run": "rw,noexec,nosuid,size=65536k" }
```
additionalProperties:
type: "string"
PoC:
type: "object"
description: |
```
panic!(">>>>>>>>>> Here's a PoC showing you can be pwned this way.")
```
additionalProperties:
type: "string"
`./src/schema.json`
{
"$defs": {
"Tmpfs": {
"type": "object",
"description": "A map of container directories which should be replaced by tmpfs\nmounts, and their corresponding mount options. For example:\n\n```\n{ \"/run\": \"rw,noexec,nosuid,size=65536k\" }\n```\n",
"additionalProperties": {
"type": "string"
}
},
"PoC": {
"type": "object",
"description": "```\npanic!(\">>>>>>>>>> Here's a PoC showing you can be pwned this way.\")\n```\n",
"additionalProperties": {
"type": "string"
}
}
}
}
expanded
// ...
#[doc = "```\npanic!(\">>>>>>>>>> Here's a PoC showing you can be pwned this way.\")\n```\n"]
#[doc = r""]
#[doc = r" <details><summary>JSON schema</summary>"]
#[doc = r""]
#[doc = r" ```json"]
#[doc = "{"]
#[doc = " \"description\": \"```\\npanic!(\\\">>>>>>>>>> Here's a PoC showing you can be pwned this way.\\\")\\n```\\n\","]
#[doc = " \"type\": \"object\","]
#[doc = " \"additionalProperties\": {"]
#[doc = " \"type\": \"string\""]
#[doc = " }"]
#[doc = "}"]
#[doc = r" ```"]
#[doc = r" </details>"]
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct PoC(pub ::std::collections::HashMap<::std::string::String, ::std::string::String>);
/// ...
#[doc = "A map of container directories which should be replaced by tmpfs\nmounts, and their corresponding mount options. For example:\n\n```\n{ \"/run\": \"rw,noexec,nosuid,size=65536k\" }\n```\n"]
#[doc = r""]
#[doc = r" <details><summary>JSON schema</summary>"]
#[doc = r""]
#[doc = r" ```json"]
#[doc = "{"]
#[doc = " \"description\": \"A map of container directories which should be replaced by tmpfs\\nmounts, and their corresponding mount options. For example:\\n\\n```\\n{ \\\"/run\\\": \\\"rw,noexec,nosuid,size=65536k\\\" }\\n```\\n\","]
#[doc = " \"type\": \"object\","]
#[doc = " \"additionalProperties\": {"]
#[doc = " \"type\": \"string\""]
#[doc = " }"]
#[doc = "}"]
#[doc = r" ```"]
#[doc = r" </details>"]
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug)]
#[serde(transparent)]
pub struct Tmpfs(pub ::std::collections::HashMap<::std::string::String, ::std::string::String>);
// ...
actual
$ cargo test
...
Doc-tests reproduce
running 2 tests
test src/lib.rs - generated::Tmpfs (line 7) ... FAILED
test src/lib.rs - generated::PoC (line 4) ... FAILED
failures:
---- src/lib.rs - generated::Tmpfs (line 7) stdout ----
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:`
--> src/lib.rs:8:9
|
8 | { "/run": "rw,noexec,nosuid,size=65536k" }
| ^ expected one of `.`, `;`, `?`, `}`, or an operator
error: aborting due to 1 previous error
Couldn't compile the test.
---- src/lib.rs - generated::PoC (line 4) stdout ----
Test executable failed (exit status: 101).
stderr:
thread 'main' (xxx) panicked at src/lib.rs:3:1:
>>>>>>>>>> Here's a PoC showing you can be pwned this way.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
src/lib.rs - generated::PoC (line 4)
src/lib.rs - generated::Tmpfs (line 7)
test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.15s
all doctests ran in 0.16s; merged doctests compilation took 0.02s
error: doctest failed, to rerun pass `--doc`
expected
Should derive ZERO doctest by default.
Like --lib output.
$ cargo test --lib
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
And opt-in to allow doctest
pub mod generated {
unsafe {
typify::import_types!(
schema = "./src/schema.json",
unsafe_allow_doctest = true,
);
}
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reproducer's typify::import_types! invocation and run cargo test to observe the generated doctest failures; compare with cargo test --lib. Inspect the generated #[doc] blocks for Tmpfs and PoC, then verify that default generation produces no doctests and that the unsafe_allow_doctest option enables them.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100