Skip to content

Commit 4f3d731

Browse files
committed
fix: reject empty kernel packages before linking
1 parent 84e07fd commit 4f3d731

3 files changed

Lines changed: 60 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- Added regression coverage for the exact `max_num_continuations` continuation-stack boundary ([#2995](https://github.com/0xMiden/miden-vm/pull/2995)).
2323
- Fixed AEAD padding handling so encrypt does not overwrite memory next to the plaintext buffer and decrypt leaves the plaintext output tail untouched ([#3008](https://github.com/0xMiden/miden-vm/pull/3008)).
2424
- Fixed MAST compaction after debug info is cleared so compiler-generated packages do not grow ([#3044](https://github.com/0xMiden/miden-vm/pull/3044)).
25+
- Rejected empty kernel packages before linking so malformed dependency metadata returns a structured package error instead of reaching the linker's non-empty-kernel assertion ([#3082](https://github.com/0xMiden/miden-vm/pull/3082)).
2526

2627
#### Changes
2728

crates/assembly/src/tests.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4990,6 +4990,43 @@ fn regression_empty_kernel_library_is_rejected() {
49904990
assert_diagnostic_lines!(err, "library must contain at least one exported procedure");
49914991
}
49924992

4993+
#[test]
4994+
fn regression_empty_kernel_package_is_rejected_without_panicking() {
4995+
use std::panic::{AssertUnwindSafe, catch_unwind};
4996+
4997+
let context = TestContext::default();
4998+
let source_manager = context.source_manager();
4999+
let kernel_lib = Assembler::new(source_manager.clone())
5000+
.assemble_kernel(
5001+
r#"
5002+
pub proc foo
5003+
add
5004+
end
5005+
"#,
5006+
)
5007+
.expect("kernel assembly should succeed");
5008+
let mut package = *Package::from_library(
5009+
PackageId::from("kernel"),
5010+
"1.0.0".parse().unwrap(),
5011+
TargetType::Kernel,
5012+
Arc::new(kernel_lib.as_ref().clone()),
5013+
[],
5014+
);
5015+
package.manifest = PackageManifest::new([]).expect("empty package manifest should be valid");
5016+
5017+
let linked = catch_unwind(AssertUnwindSafe(|| {
5018+
Assembler::new(source_manager)
5019+
.link_package(Arc::new(package), miden_project::Linkage::Dynamic)
5020+
}));
5021+
assert!(linked.is_ok(), "assembler panicked while linking an empty kernel package");
5022+
5023+
let error = linked.unwrap().expect_err("empty kernel packages should be rejected");
5024+
assert_diagnostic_lines!(
5025+
error,
5026+
"invalid kernel package: does not export any kernel procedures"
5027+
);
5028+
}
5029+
49935030
/// Reproduces issue #3035: a MAST with padded basic blocks grows when debug info is cleared and the
49945031
/// forest is compacted via self-merge.
49955032
#[test]

crates/mast-package/src/package/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ impl Package {
145145
}
146146
})
147147
.collect::<Vec<_>>();
148+
if exports.is_empty() {
149+
return Err(Report::msg(
150+
"invalid kernel package: does not export any kernel procedures",
151+
));
152+
}
148153
Kernel::new(&exports).map_err(|err| Report::msg(format!("invalid kernel package: {err}")))
149154
}
150155

@@ -525,6 +530,23 @@ mod tests {
525530
build_package(name, TargetType::Kernel, &format!("{name}::boot"), [], Vec::new())
526531
}
527532

533+
#[test]
534+
fn to_kernel_rejects_empty_kernel_exports() {
535+
let mut package = build_package("kernel", TargetType::Kernel, "$kernel::boot", [], vec![]);
536+
package.manifest =
537+
PackageManifest::new([]).expect("empty package manifest should be valid");
538+
539+
let error = package
540+
.to_kernel()
541+
.expect_err("kernel packages without exported procedures should be rejected");
542+
543+
assert!(
544+
error
545+
.to_string()
546+
.contains("invalid kernel package: does not export any kernel procedures")
547+
);
548+
}
549+
528550
fn kernel_dependency(package: &Package) -> Dependency {
529551
Dependency {
530552
name: package.name.clone(),

0 commit comments

Comments
 (0)