Skip to content

Commit c90c0f3

Browse files
committed
Add missing subtype checks for table, memory, and global fields
The subtype checker was ignoring several fields when comparing core WebAssembly types: - Table: table64 and shared flags were bound but unused (prefixed with _) - Memory: page_size_log2 was bound but unused - Global: shared flag was bound but unused This meant two types differing only in these fields would incorrectly pass the subtype check. Added the missing comparisons and unit tests for each case.
1 parent e1e684a commit c90c0f3

File tree

1 file changed

+116
-8
lines changed

1 file changed

+116
-8
lines changed

crates/wac-types/src/checker.rs

Lines changed: 116 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -411,15 +411,15 @@ impl<'a> SubtypeChecker<'a> {
411411
element_type: ae,
412412
initial: ai,
413413
maximum: am,
414-
table64: _a64,
415-
shared: _ashared,
414+
table64: a64,
415+
shared: ashared,
416416
},
417417
CoreExtern::Table {
418418
element_type: be,
419419
initial: bi,
420420
maximum: bm,
421-
table64: _b64,
422-
shared: _bshared,
421+
table64: b64,
422+
shared: bshared,
423423
},
424424
) => {
425425
if ae != be {
@@ -431,6 +431,14 @@ impl<'a> SubtypeChecker<'a> {
431431
bail!("mismatched table limits");
432432
}
433433

434+
if a64 != b64 {
435+
bail!("mismatched table64 flag for tables");
436+
}
437+
438+
if ashared != bshared {
439+
bail!("mismatched shared flag for tables");
440+
}
441+
434442
Ok(())
435443
}
436444
(
@@ -439,14 +447,14 @@ impl<'a> SubtypeChecker<'a> {
439447
shared: ashared,
440448
initial: ai,
441449
maximum: am,
442-
page_size_log2: _apsl,
450+
page_size_log2: apsl,
443451
},
444452
CoreExtern::Memory {
445453
memory64: b64,
446454
shared: bshared,
447455
initial: bi,
448456
maximum: bm,
449-
page_size_log2: _bpsl,
457+
page_size_log2: bpsl,
450458
},
451459
) => {
452460
if ashared != bshared {
@@ -461,18 +469,22 @@ impl<'a> SubtypeChecker<'a> {
461469
bail!("mismatched memory limits");
462470
}
463471

472+
if apsl != bpsl {
473+
bail!("mismatched page_size_log2 for memories");
474+
}
475+
464476
Ok(())
465477
}
466478
(
467479
CoreExtern::Global {
468480
val_type: avt,
469481
mutable: am,
470-
shared: _ashared,
482+
shared: ashared,
471483
},
472484
CoreExtern::Global {
473485
val_type: bvt,
474486
mutable: bm,
475-
shared: _bshared,
487+
shared: bshared,
476488
},
477489
) => {
478490
if am != bm {
@@ -484,6 +496,10 @@ impl<'a> SubtypeChecker<'a> {
484496
bail!("expected global type {expected}, found {found}");
485497
}
486498

499+
if ashared != bshared {
500+
bail!("mismatched shared flag for globals");
501+
}
502+
487503
Ok(())
488504
}
489505
(CoreExtern::Tag(a), CoreExtern::Tag(b)) => self.core_func(a, at, b, bt),
@@ -795,3 +811,95 @@ impl<'a> SubtypeChecker<'a> {
795811
Ok(())
796812
}
797813
}
814+
815+
#[cfg(test)]
816+
mod tests {
817+
use super::*;
818+
use crate::{CoreRefType, CoreType, HeapType};
819+
820+
fn check_core_extern(a: &CoreExtern, b: &CoreExtern) -> Result<()> {
821+
let types = Types::default();
822+
let mut cache = HashSet::new();
823+
let checker = SubtypeChecker::new(&mut cache);
824+
checker.core_extern(a, &types, b, &types)
825+
}
826+
827+
fn base_table() -> CoreExtern {
828+
CoreExtern::Table {
829+
element_type: CoreRefType {
830+
nullable: true,
831+
heap_type: HeapType::Func,
832+
},
833+
initial: 1,
834+
maximum: None,
835+
table64: false,
836+
shared: false,
837+
}
838+
}
839+
840+
#[test]
841+
fn mismatched_table64_is_rejected() {
842+
let a = base_table();
843+
let mut b = base_table();
844+
if let CoreExtern::Table { table64, .. } = &mut b {
845+
*table64 = true;
846+
}
847+
assert!(
848+
check_core_extern(&a, &b).is_err(),
849+
"mismatched table64 should be rejected"
850+
);
851+
}
852+
853+
#[test]
854+
fn mismatched_table_shared_is_rejected() {
855+
let a = base_table();
856+
let mut b = base_table();
857+
if let CoreExtern::Table { shared, .. } = &mut b {
858+
*shared = true;
859+
}
860+
assert!(
861+
check_core_extern(&a, &b).is_err(),
862+
"mismatched table shared should be rejected"
863+
);
864+
}
865+
866+
#[test]
867+
fn mismatched_memory_page_size_log2_is_rejected() {
868+
let a = CoreExtern::Memory {
869+
memory64: false,
870+
shared: false,
871+
initial: 1,
872+
maximum: None,
873+
page_size_log2: Some(16),
874+
};
875+
let b = CoreExtern::Memory {
876+
memory64: false,
877+
shared: false,
878+
initial: 1,
879+
maximum: None,
880+
page_size_log2: Some(14),
881+
};
882+
assert!(
883+
check_core_extern(&a, &b).is_err(),
884+
"mismatched page_size_log2 should be rejected"
885+
);
886+
}
887+
888+
#[test]
889+
fn mismatched_global_shared_is_rejected() {
890+
let a = CoreExtern::Global {
891+
val_type: CoreType::I32,
892+
mutable: false,
893+
shared: false,
894+
};
895+
let b = CoreExtern::Global {
896+
val_type: CoreType::I32,
897+
mutable: false,
898+
shared: true,
899+
};
900+
assert!(
901+
check_core_extern(&a, &b).is_err(),
902+
"mismatched global shared should be rejected"
903+
);
904+
}
905+
}

0 commit comments

Comments
 (0)