Open
Description
Bug description
Explicitly casting a small integer (i8, u8, i16, u16) to bool via <bool>x, x as bool, or bool(x) emits i32.ne 0 without masking or sign-extending the operand first, so an overflowed value that wraps to 0 evaluates to true.
For a = 255 in the example below, c wraps to 0 in u8. Calling g(255) returns 0 (false), whereas f(255) returns 1 (true) because f compiles to i32.add followed directly by i32.ne 0 without i32.and 255. Both functions should return 0 (false).
This happens because convertExpression only wraps short integers when fromType.size < toType.size, skipping bool where toType.size == 1.
Steps to reproduce
export function f(a: u8): bool {
let c: u8 = a + 1;
return <bool>c;
}
export function g(a: u8): bool {
let c: u8 = a + 1;
return c ? true : false;
}Credit: https://ucsbplse.github.io/
AssemblyScript version
v0.28.20
Metadata
Metadata
Assignees
Labels
No labels
Activity
[-]Explicit bool cast of u8/i8/u16/i16 does not truncate high bits[/-][+]Small integer types (u8/i8/u16/i16) are not wrapped or truncated in bool casts and bitwise AND[/+][-]Small integer types (u8/i8/u16/i16) are not wrapped or truncated in bool casts and bitwise AND[/-][+]Explicit bool cast of u8/i8/u16/i16 does not truncate high bits[/+]