Skip to content

Commit 4f21a5a

Browse files
committed
fix(vm): only promote to int64/uint64 when both operands match signedness
Avoid mixed-sign regression where int64 + uint64 would incorrectly promote to uint64, causing wrong results for negative values.
1 parent 9c6cc31 commit 4f21a5a

3 files changed

Lines changed: 174 additions & 166 deletions

File tree

expr_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -805,11 +805,11 @@ func TestExpr(t *testing.T) {
805805
},
806806
{
807807
`Uint64 + 0`,
808-
uint64(0),
808+
0,
809809
},
810810
{
811811
`Uint64 + Int64`,
812-
uint64(0),
812+
0,
813813
},
814814
{
815815
`Int32 + Int64`,

vm/runtime/helpers/main.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ func cases(op string, xs ...[]string) string {
7272
echo(`switch y := b.(type) {`)
7373
for _, b := range types {
7474
t := "int"
75-
if isInt64(a) || isInt64(b) {
75+
if (isInt64(a) || isInt64(b)) && isSigned(a) && isSigned(b) {
7676
t = "int64"
7777
}
78-
if isUint64(a) || isUint64(b) {
78+
if (isUint64(a) || isUint64(b)) && isUnsigned(a) && isUnsigned(b) {
7979
t = "uint64"
8080
}
8181
if isDuration(a) || isDuration(b) {
@@ -147,6 +147,14 @@ func isUint64(t string) bool {
147147
return t == "uint64"
148148
}
149149

150+
func isSigned(t string) bool {
151+
return t == "int" || t == "int8" || t == "int16" || t == "int32" || t == "int64"
152+
}
153+
154+
func isUnsigned(t string) bool {
155+
return t == "uint" || t == "uint8" || t == "uint16" || t == "uint32" || t == "uint64"
156+
}
157+
150158
func isDuration(t string) bool {
151159
return t == "time.Duration"
152160
}

0 commit comments

Comments
 (0)