Skip to content

Commit 9b3fe5f

Browse files
committed
Merge remote-tracking branch 'origin/main' into dependabot/cargo/src/code-validator/guest/napi-3.9.0
Signed-off-by: Simon Davies <simongdavies@users.noreply.github.com> # Conflicts: # .gitignore # .prettierignore # src/code-validator/guest/Cargo.lock # src/code-validator/guest/host/build.rs
2 parents 1533fb6 + fe77770 commit 9b3fe5f

4 files changed

Lines changed: 32 additions & 26 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@ plugins/host-modules.d.ts
5555
output-hyperagent-*/
5656
scripts/bash-bundle/_tmp_bundle.js
5757

58-
# Generated NAPI binding loader + type declarations (emitted by `napi build`)
58+
# Generated NAPI bindings (emitted by `napi build`)
5959
src/code-validator/guest/host/index.d.ts
6060
src/code-validator/guest/host/index.js

.prettierignore

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# Generated NAPI binding loader + type declarations (emitted by `napi build`).
2-
# napi-derive >= 3 writes JSDoc into the .d.ts and emits a loader .js, neither of
3-
# which is Prettier-formatted. The canonical, hand-written loader/types live in
4-
# src/code-validator/guest/index.js and src/code-validator/guest/index.d.ts.
1+
# Generated NAPI binding type declarations (emitted by `napi build`).
2+
# napi-derive >= 3 writes JSDoc into this file, which is not Prettier-formatted.
3+
# The canonical, hand-written types live in src/code-validator/guest/index.d.ts.
54
src/code-validator/guest/host/index.d.ts
6-
src/code-validator/guest/host/index.js

src/code-validator/guest/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/code-validator/guest/host/build.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -166,30 +166,38 @@ fn bundle_runtime() {
166166
let runtime_resource = build_runtime();
167167
let runtime_bytes = fs::read(&runtime_resource).expect("Failed to read runtime binary");
168168

169-
// Compute SHA256 hash
169+
assert!(
170+
!runtime_bytes.is_empty(),
171+
"analysis runtime binary is empty: {runtime_resource:?}"
172+
);
173+
174+
let out_dir = env::var_os("OUT_DIR").unwrap();
175+
176+
// Snapshot the runtime binary into this crate's OUT_DIR and embed THAT copy.
177+
//
178+
// The hash below is computed from `runtime_bytes`, while the embedded bytes
179+
// come from `include_bytes!` evaluated when this crate is compiled — two
180+
// reads at different times. The build path of `runtime_resource` lives in a
181+
// shared target directory that other cargo invocations (clippy, the napi
182+
// typedef pass, repeated `just build`/`just test` runs) can rebuild, and the
183+
// guest binary is not bit-for-bit reproducible. If that file changed between
184+
// hashing and the `include_bytes!` compile, the embedded bytes would no
185+
// longer match the stored hash and the runtime integrity check would fail.
186+
//
187+
// Writing a private snapshot into OUT_DIR — which nothing else ever touches —
188+
// and pointing `include_bytes!` at it guarantees the embedded bytes are
189+
// exactly the bytes we hashed, as a single atomic pair.
190+
let embedded_path = Path::new(&out_dir).join("analysis-runtime.bin");
191+
fs::write(&embedded_path, &runtime_bytes).expect("Failed to write runtime snapshot");
192+
193+
// Compute SHA256 hash of the same in-memory buffer we just embedded.
170194
use sha2::{Digest, Sha256};
171195
let mut hasher = Sha256::new();
172196
hasher.update(&runtime_bytes);
173197
let hash = hasher.finalize();
174198
let hash_hex = hex::encode(hash);
175199

176-
let out_dir = env::var_os("OUT_DIR").unwrap();
177-
let out_dir = Path::new(&out_dir);
178-
179-
// Stage the runtime binary into OUT_DIR and embed that copy rather than the
180-
// live build-target binary. `include_bytes!` is expanded by rustc when the
181-
// host crate is compiled, which happens after this build script runs. If we
182-
// pointed `include_bytes!` at the mutable target-dir binary, a later rebuild
183-
// of the runtime (e.g. by clippy or a subsequent `cargo build` that does not
184-
// re-trigger this script) could change those bytes while the recorded
185-
// ANALYSIS_RUNTIME_SHA256 stays stale, producing a `.node` whose embedded
186-
// bytes and integrity hash disagree. The OUT_DIR copy is written here, in
187-
// lock-step with the hash, and is only ever touched by this build script, so
188-
// the embedded bytes and hash can never desync.
189-
let embedded_path = out_dir.join("analysis-runtime.bin");
190-
fs::write(&embedded_path, &runtime_bytes).expect("Failed to stage runtime binary in OUT_DIR");
191-
192-
let dest_path = out_dir.join("host_resource.rs");
200+
let dest_path = Path::new(&out_dir).join("host_resource.rs");
193201
let contents = format!(
194202
r#"pub(crate) static ANALYSIS_RUNTIME: &[u8] = include_bytes!({embedded_path:?});
195203
pub(crate) const ANALYSIS_RUNTIME_SHA256: &str = "{hash_hex}";"#

0 commit comments

Comments
 (0)