Skip to content

Commit

Permalink
fix: typed const conversion validation (#3117)
Browse files Browse the repository at this point in the history
During preprocessing, validates if typed constants are convertible.
Fixes [issue](#2681)

Typed constants are convertible only in a lossless way.
That means that we can convert floats to integers if the fractional part
of the float is 0.
  • Loading branch information
petar-dambovaliev authored Nov 22, 2024
1 parent 77e6606 commit d0493df
Show file tree
Hide file tree
Showing 6 changed files with 515 additions and 8 deletions.
130 changes: 130 additions & 0 deletions gnovm/pkg/gnolang/gno_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,136 @@ func TestBuiltinIdentifiersShadowing(t *testing.T) {
}
}

func TestConvertTo(t *testing.T) {
t.Parallel()

testFunc := func(source, msg string) {
defer func() {
if len(msg) == 0 {
return
}

r := recover()

if r == nil {
t.Fail()
}

err := r.(*PreprocessError)
c := strings.Contains(err.Error(), msg)
if !c {
t.Fatalf(`expected "%s", got "%s"`, msg, r)
}
}()

m := NewMachine("test", nil)

n := MustParseFile("main.go", source)
m.RunFiles(n)
m.RunMain()
}

type cases struct {
source string
msg string
}

tests := []cases{
{
`package test
func main() {
const a int = -1
println(uint(a))
}`,
`test/main.go:5:13: cannot convert constant of type IntKind to UintKind`,
},
{
`package test
func main() {
const a int = -1
println(uint8(a))
}`,
`test/main.go:5:13: cannot convert constant of type IntKind to Uint8Kind`,
},
{
`package test
func main() {
const a int = -1
println(uint16(a))
}`,
`test/main.go:5:13: cannot convert constant of type IntKind to Uint16Kind`,
},
{
`package test
func main() {
const a int = -1
println(uint32(a))
}`,
`test/main.go:5:13: cannot convert constant of type IntKind to Uint32Kind`,
},
{
`package test
func main() {
const a int = -1
println(uint64(a))
}`,
`test/main.go:5:13: cannot convert constant of type IntKind to Uint64Kind`,
},
{
`package test
func main() {
const a float32 = 1.5
println(int32(a))
}`,
`test/main.go:5:13: cannot convert constant of type Float32Kind to Int32Kind`,
},
{
`package test
func main() {
println(int32(1.5))
}`,
`test/main.go:4:13: cannot convert (const (1.5 <untyped> bigdec)) to integer type`,
},
{
`package test
func main() {
const a float64 = 1.5
println(int64(a))
}`,
`test/main.go:5:13: cannot convert constant of type Float64Kind to Int64Kind`,
},
{
`package test
func main() {
println(int64(1.5))
}`,
`test/main.go:4:13: cannot convert (const (1.5 <untyped> bigdec)) to integer type`,
},
{
`package test
func main() {
const f = float64(1.0)
println(int64(f))
}`,
``,
},
}

for _, tc := range tests {
testFunc(tc.source, tc.msg)
}
}

// run empty main().
func TestRunEmptyMain(t *testing.T) {
t.Parallel()
Expand Down
2 changes: 1 addition & 1 deletion gnovm/pkg/gnolang/op_expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,6 @@ func (m *Machine) doOpFuncLit() {
func (m *Machine) doOpConvert() {
xv := m.PopValue()
t := m.PopValue().GetType()
ConvertTo(m.Alloc, m.Store, xv, t)
ConvertTo(m.Alloc, m.Store, xv, t, false)
m.PushValue(*xv)
}
2 changes: 1 addition & 1 deletion gnovm/pkg/gnolang/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -3656,7 +3656,7 @@ func convertConst(store Store, last BlockNode, cx *ConstExpr, t Type) {
setConstAttrs(cx)
} else if t != nil {
// e.g. a named type or uint8 type to int for indexing.
ConvertTo(nilAllocator, store, &cx.TypedValue, t)
ConvertTo(nilAllocator, store, &cx.TypedValue, t, true)
setConstAttrs(cx)
}
}
Expand Down
2 changes: 1 addition & 1 deletion gnovm/pkg/gnolang/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,7 @@ func (tv *TypedValue) SetInt(n int) {

func (tv *TypedValue) ConvertGetInt() int {
var store Store = nil // not used
ConvertTo(nilAllocator, store, tv, IntType)
ConvertTo(nilAllocator, store, tv, IntType, false)
return tv.GetInt()
}

Expand Down
Loading

0 comments on commit d0493df

Please sign in to comment.