Skip to content

Commit

Permalink
[compiler-v2] Fix bytecode verification error due to incorrect const …
Browse files Browse the repository at this point in the history
…folding (#15982)
  • Loading branch information
vineethk authored Feb 26, 2025
1 parent 41f2ce1 commit 2dd16bb
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -1,94 +1,124 @@

Diagnostics:
error: Invalid expression in `const`. Operator `<<` result value out of range for `u8`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `8`
┌─ tests/folding/unfoldable_constants.move:3:22
3 │ const SHL0: u8 = 1 << 8;
│ ^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u64`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `64`
┌─ tests/folding/unfoldable_constants.move:4:23
4 │ const SHL1: u64 = 1 << 64;
│ ^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u128`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `128`
┌─ tests/folding/unfoldable_constants.move:5:24
5 │ const SHL2: u128 = 1 << 128;
│ ^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u16`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `16`
┌─ tests/folding/unfoldable_constants.move:6:23
6 │ const SHL3: u16 = 1 << 16;
│ ^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u32`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `32`
┌─ tests/folding/unfoldable_constants.move:7:23
7 │ const SHL4: u32 = 1 << 32;
│ ^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u8`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `8`
┌─ tests/folding/unfoldable_constants.move:9:25
9 │ const SHL0B: u32 = (1u8 << 8 as u32);
│ ^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u64`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `64`
┌─ tests/folding/unfoldable_constants.move:10:26
10 │ const SHL1B: u128 = ((1u64 << 64) as u128);
│ ^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u128`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `128`
┌─ tests/folding/unfoldable_constants.move:11:26
11 │ const SHL2B: u256 = ((1u128 << 128) as u256);
│ ^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u16`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `16`
┌─ tests/folding/unfoldable_constants.move:12:25
12 │ const SHL3B: u32 = ((1u16 << 16) as u32);
│ ^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u32`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `32`
┌─ tests/folding/unfoldable_constants.move:13:25
13 │ const SHL4B: u64 = ((1u32 << 32) as u64);
│ ^^^^^^^^^^^^

error: Invalid expression in `const`. Parameter to unary expression not foldable to constant
┌─ tests/folding/unfoldable_constants.move:21:24
error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `8`
┌─ tests/folding/unfoldable_constants.move:15:22
15 │ const SHR0: u8 = 0 >> 8;
│ ^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `64`
┌─ tests/folding/unfoldable_constants.move:16:23
16 │ const SHR1: u64 = 0 >> 64;
│ ^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `128`
┌─ tests/folding/unfoldable_constants.move:17:24
17 │ const SHR2: u128 = 0 >> 128;
│ ^^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `16`
┌─ tests/folding/unfoldable_constants.move:18:23
18 │ const SHR3: u16 = 0 >> 16;
│ ^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `32`
┌─ tests/folding/unfoldable_constants.move:19:23
19 │ const SHR4: u32 = 0 >> 32;
│ ^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `8`
┌─ tests/folding/unfoldable_constants.move:21:25
21 │ const SHR0B: u32 = ((0u8 >> 8) as u32);
^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^

error: Invalid expression in `const`. Parameter to unary expression not foldable to constant
┌─ tests/folding/unfoldable_constants.move:22:25
error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `64`
┌─ tests/folding/unfoldable_constants.move:22:26
22 │ const SHR1B: u128 = ((0u64 >> 64) as u128);
^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^

error: Invalid expression in `const`. Parameter to unary expression not foldable to constant
┌─ tests/folding/unfoldable_constants.move:23:25
error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `128`
┌─ tests/folding/unfoldable_constants.move:23:26
23 │ const SHR2B: u256 = ((0u128 >> 128) as u256);
^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^

error: Invalid expression in `const`. Parameter to unary expression not foldable to constant
┌─ tests/folding/unfoldable_constants.move:24:24
error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `16`
┌─ tests/folding/unfoldable_constants.move:24:25
24 │ const SHR3B: u32 = ((0u16 >> 16) as u32);
^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^

error: Invalid expression in `const`. Parameter to unary expression not foldable to constant
┌─ tests/folding/unfoldable_constants.move:25:24
error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `32`
┌─ tests/folding/unfoldable_constants.move:25:25
25 │ const SHR4B: u64 = ((0u32 >> 32) as u64);
^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `/` result value out of range for `u8`
┌─ tests/folding/unfoldable_constants.move:27:22
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,65 @@

Diagnostics:
error: Invalid expression in `const`. Operator `<<` result value out of range for `u8`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `8`
┌─ tests/folding/unfoldable_constants_blocks.move:4:9
4 │ (1: u8) << 8;
│ ^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u64`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `64`
┌─ tests/folding/unfoldable_constants_blocks.move:5:9
5 │ (1: u64) << 64;
│ ^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u128`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `128`
┌─ tests/folding/unfoldable_constants_blocks.move:6:9
6 │ (1: u128) << 128;
│ ^^^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u16`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `16`
┌─ tests/folding/unfoldable_constants_blocks.move:7:9
7 │ (1: u16) << 16;
│ ^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `<<` result value out of range for `u32`
error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `32`
┌─ tests/folding/unfoldable_constants_blocks.move:8:9
8 │ (1: u32) << 32;
│ ^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `8`
┌─ tests/folding/unfoldable_constants_blocks.move:10:9
10 │ (0: u8) >> 8;
│ ^^^^^^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `64`
┌─ tests/folding/unfoldable_constants_blocks.move:11:9
11 │ (0: u64) >> 64;
│ ^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `128`
┌─ tests/folding/unfoldable_constants_blocks.move:12:9
12 │ (0: u128) >> 128;
│ ^^^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `16`
┌─ tests/folding/unfoldable_constants_blocks.move:13:9
13 │ (0: u16) >> 16;
│ ^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `32`
┌─ tests/folding/unfoldable_constants_blocks.move:14:9
14 │ (0: u32) >> 32;
│ ^^^^^^^^^^^^^^

error: Invalid expression in `const`. Operator `/` result value out of range for `u8`
┌─ tests/folding/unfoldable_constants_blocks.move:16:9
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
comparison between v1 and v2 failed:
= processed 1 task
=
= task 0 'publish'. lines 1-9:
- Error: error[E08001]: cannot compute constant value
+ Error: compilation errors:
+ error: Invalid expression in `const`. Operand on the right is too large for `<<`, should be less than `8`
= ┌─ TEMPFILE:3:20
= │
= 3 │ const C1: u8 = 0 << 8;
- │ ^^^^^^ Invalid expression in 'const'. This expression could not be evaluated to a value
+ │ ^^^^^^
=
- error[E08001]: cannot compute constant value
+ error: Invalid expression in `const`. Operand on the right is too large for `>>`, should be less than `8`
= ┌─ TEMPFILE:4:20
= │
= 4 │ const C2: u8 = 0 >> 8;
- │ ^^^^^^ Invalid expression in 'const'. This expression could not be evaluated to a value
+ │ ^^^^^^
=
=
=
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//# publish
module 0xc0ffee::m {
const C1: u8 = 0 << 8;
const C2: u8 = 0 >> 8;

public fun test(): u8 {
C1 + C2
}
}
49 changes: 44 additions & 5 deletions third_party/move/move-model/src/constant_folder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,27 @@ impl<'env> ConstantFolder<'env> {
}
}

/// Check the RHS of a shift: `rhs` should be less than result type size.
fn shift_rhs_check(
&mut self,
rhs: &BigInt,
result_ty_size: &BigInt,
id: NodeId,
binop_name: &str,
) -> Option<()> {
if rhs < result_ty_size {
Some(())
} else {
self.constant_folding_error(id, |_| {
format!(
"Operand on the right is too large for `{}`, should be less than `{}`",
binop_name, result_ty_size
)
.to_owned()
})
}
}

fn checked_shl(a: &BigInt, b: &BigInt) -> Option<BigInt> {
b.to_u16().map(|b| a.shl(b))
}
Expand All @@ -237,7 +258,7 @@ impl<'env> ConstantFolder<'env> {
.unwrap_or_else(|| BigInt::from(256))
}

/// Try constant folding of a non-tuple binary operation `oper` applied to arguements `arg0` and
/// Try constant folding of a non-tuple binary operation `oper` applied to arguments `arg0` and
/// `arg1`, returning `Some(exp)` where `exp` is a ExpData::Value(id, ..)` expression if
/// constant folding is possible. Operation result type may be obtained from `id`.
///
Expand Down Expand Up @@ -282,14 +303,32 @@ impl<'env> ConstantFolder<'env> {
O::Shl => {
// result_pty should be same size as arg0
let arg0_size = Self::ptype_num_bits_bigint(result_pty);
self.binop_num(name(), Self::checked_shl, id, result_pty, val0, val1)
.filter(|_r| val1 < &arg0_size) // shift fails if val1 >= bits in val0
self.shift_rhs_check(val1, &arg0_size, id, name())
.and_then(|_| {
self.binop_num(
name(),
Self::checked_shl,
id,
result_pty,
val0,
val1,
)
})
},
O::Shr => {
// result_pty should be same size as arg0
let arg0_size = Self::ptype_num_bits_bigint(result_pty);
self.binop_num(name(), Self::checked_shr, id, result_pty, val0, val1)
.filter(|_r| val1 < &arg0_size) // shift fails if val1 >= bits in val0
self.shift_rhs_check(val1, &arg0_size, id, name())
.and_then(|_| {
self.binop_num(
name(),
Self::checked_shr,
id,
result_pty,
val0,
val1,
)
})
},
O::BitAnd => Some(V(id, Number(val0.bitand(val1))).into_exp()),
O::BitOr => Some(V(id, Number(val0.bitor(val1))).into_exp()),
Expand Down

0 comments on commit 2dd16bb

Please sign in to comment.