Change CLIF shuffle to validate lane indices (#5995)

* Change CLIF `shuffle` to validate lane indices

Previously the CLIF `shuffle` instruction did not perform any validation
on the lane shuffle mask and specified that out-of-bounds lanes always
returned 0 as the value. This behavior though is not required by
WebAssembly which validates that lane indices are always in-bounds.
Additionally since these are static immediates even other code
generators should be able to verify that the immediates are in-bounds.

As a result this commit updates the definition of the `shuffle`
instruction to specify that all byte immediates must be in-bounds in the
range of [0, 32). The verifier has been updated and some test cases have
been removed that were testing this functionality.

Closes #5989

* Only generate valid shuffle immediates in fuzzer
This commit is contained in:
Alex Crichton
2023-03-13 09:24:11 -05:00
committed by GitHub
parent 2386eee56b
commit 7956dc6ba2
8 changed files with 33 additions and 120 deletions

View File

@@ -1422,7 +1422,7 @@ pub(crate) fn define(
Shuffle two vectors using the given immediate bytes. For each of the 16 bytes of the
immediate, a value i of 0-15 selects the i-th element of the first vector and a value i of
16-31 selects the (i-16)th element of the second vector. Immediate values outside of the
0-31 range place a 0 in the resulting vector lane.
0-31 range are not valid.
"#,
&formats.shuffle,
)

View File

@@ -1685,6 +1685,28 @@ impl<'a> Verifier<'a> {
Ok(())
}
}
ir::InstructionData::Shuffle {
opcode: ir::instructions::Opcode::Shuffle,
imm,
..
} => {
let imm = self.func.dfg.immediates.get(imm).unwrap().as_slice();
if imm.len() != 16 {
errors.fatal((
inst,
self.context(inst),
format!("the shuffle immediate wasn't 16-bytes long"),
))
} else if let Some(i) = imm.iter().find(|i| **i >= 32) {
errors.fatal((
inst,
self.context(inst),
format!("shuffle immediate index {i} is larger than the maximum 31"),
))
} else {
Ok(())
}
}
_ => Ok(()),
}
}