Skip to content

Commit 45c1ae7

Browse files
committed
Add int overflow checks
1 parent 1a5df77 commit 45c1ae7

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

checker/checker.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,9 +1039,11 @@ func traverseAndReplaceIntegerNodesWithIntegerNodes(node *ast.Node, newType refl
10391039
case *ast.IntegerNode:
10401040
(*node).SetType(newType)
10411041
case *ast.UnaryNode:
1042+
(*node).SetType(newType)
10421043
unaryNode := (*node).(*ast.UnaryNode)
10431044
traverseAndReplaceIntegerNodesWithIntegerNodes(&unaryNode.Node, newType)
10441045
case *ast.BinaryNode:
1046+
// TODO: Binary node return type is dependent on the type of the operands. We can't just change the type of the node.
10451047
binaryNode := (*node).(*ast.BinaryNode)
10461048
switch binaryNode.Operator {
10471049
case "+", "-", "*":

compiler/compiler.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package compiler
22

33
import (
44
"fmt"
5+
"math"
56
"reflect"
67
"regexp"
78

@@ -329,22 +330,49 @@ func (c *compiler) IntegerNode(node *ast.IntegerNode) {
329330
case reflect.Int:
330331
c.emitPush(node.Value)
331332
case reflect.Int8:
333+
if node.Value > math.MaxInt8 || node.Value < math.MinInt8 {
334+
panic(fmt.Sprintf("constant %d overflows int8", node.Value))
335+
}
332336
c.emitPush(int8(node.Value))
333337
case reflect.Int16:
338+
if node.Value > math.MaxInt16 || node.Value < math.MinInt16 {
339+
panic(fmt.Sprintf("constant %d overflows int16", node.Value))
340+
}
334341
c.emitPush(int16(node.Value))
335342
case reflect.Int32:
343+
if node.Value > math.MaxInt32 || node.Value < math.MinInt32 {
344+
panic(fmt.Sprintf("constant %d overflows int32", node.Value))
345+
}
336346
c.emitPush(int32(node.Value))
337347
case reflect.Int64:
348+
if node.Value > math.MaxInt64 || node.Value < math.MinInt64 {
349+
panic(fmt.Sprintf("constant %d overflows int64", node.Value))
350+
}
338351
c.emitPush(int64(node.Value))
339352
case reflect.Uint:
353+
if node.Value < 0 {
354+
panic(fmt.Sprintf("constant %d overflows uint", node.Value))
355+
}
340356
c.emitPush(uint(node.Value))
341357
case reflect.Uint8:
358+
if node.Value > math.MaxUint8 || node.Value < 0 {
359+
panic(fmt.Sprintf("constant %d overflows uint8", node.Value))
360+
}
342361
c.emitPush(uint8(node.Value))
343362
case reflect.Uint16:
363+
if node.Value > math.MaxUint16 || node.Value < 0 {
364+
panic(fmt.Sprintf("constant %d overflows uint16", node.Value))
365+
}
344366
c.emitPush(uint16(node.Value))
345367
case reflect.Uint32:
368+
if node.Value > math.MaxUint32 || node.Value < 0 {
369+
panic(fmt.Sprintf("constant %d overflows uint32", node.Value))
370+
}
346371
c.emitPush(uint32(node.Value))
347372
case reflect.Uint64:
373+
if node.Value < 0 {
374+
panic(fmt.Sprintf("constant %d overflows uint64", node.Value))
375+
}
348376
c.emitPush(uint64(node.Value))
349377
default:
350378
c.emitPush(node.Value)

expr_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2645,3 +2645,17 @@ func TestIssue_570(t *testing.T) {
26452645
require.NoError(t, err)
26462646
require.IsType(t, nil, out)
26472647
}
2648+
2649+
func TestIssue_integer_truncated_by_compiler(t *testing.T) {
2650+
env := map[string]any{
2651+
"fn": func(x byte) byte {
2652+
return x
2653+
},
2654+
}
2655+
2656+
_, err := expr.Compile("fn(255)", expr.Env(env))
2657+
require.NoError(t, err)
2658+
2659+
_, err = expr.Compile("fn(256)", expr.Env(env))
2660+
require.Error(t, err)
2661+
}

0 commit comments

Comments
 (0)