zclconf / go-cty

A type system for dynamic values in Go applications
MIT License
345 stars 69 forks source link

function/stdlib: the Modulo function panics if the first argument is an infinity #90

Open apparentlymart opened 3 years ago

apparentlymart commented 3 years ago

Need to decide whether this ought to succeed with another infinity or return an error, but either way it shouldn't generate a null pointer panic:

panic: runtime error: invalid memory address or nil pointer dereference
            goroutine 57 [running]:
            runtime/debug.Stack(0xc0002170d0, 0x82fca0, 0xbd29b0)
                ~/.goenv/versions/1.16.0/src/runtime/debug/stack.go:24 +0x9f
            github.com/zclconf/go-cty/cty/function.errorForPanic(...)
                ~/go/1.16.0/pkg/mod/github.com/zclconf/go-cty@v1.8.0/cty/function/error.go:44
            github.com/zclconf/go-cty/cty/function.Function.Call.func1(0xc0002178d8, 0xc0002178f8)
                ~/go/1.16.0/pkg/mod/github.com/zclconf/go-cty@v1.8.0/cty/function/function.go:291 +0x93
            panic(0x82fca0, 0xbd29b0)
                ~/.goenv/versions/1.16.0/src/runtime/panic.go:965 +0x1b9
            github.com/zclconf/go-cty/cty/function/stdlib.glob..func58.1(0xc0002176d0, 0xc0002176f0)
                ~/go/1.16.0/pkg/mod/github.com/zclconf/go-cty@v1.8.0/cty/function/stdlib/number.go:187 +0x110
            panic(0x82fca0, 0xbd29b0)
                ~/.goenv/versions/1.16.0/src/runtime/panic.go:965 +0x1b9
            math/big.(*Int).BitLen(...)
                ~/.goenv/versions/1.16.0/src/math/big/int.go:473
            math/big.(*Float).SetInt(0xc0001ffd40, 0x0, 0xc0001ffd40)
                ~/.goenv/versions/1.16.0/src/math/big/float.go:596 +0x26
            github.com/zclconf/go-cty/cty.Value.Modulo(0x9218e8, 0xc0000161d9, 0x888560, 0xc0001ffc80, 0x9218e8, 0xc0000161d9, 0x888560, 0xc0001ff410, 0x88ac7a, 0x1, ...)
                ~/go/1.16.0/pkg/mod/github.com/zclconf/go-cty@v1.8.0/cty/value_ops.go:694 +0x625
            github.com/zclconf/go-cty/cty/function/stdlib.glob..func58(0xc0001cb240, 0x2, 0x2, 0x9218e8, 0xc0000161d9, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
                ~/go/1.16.0/pkg/mod/github.com/zclconf/go-cty@v1.8.0/cty/function/stdlib/number.go:192 +0x106
            github.com/zclconf/go-cty/cty/function.Function.Call(0xc0000738f0, 0xc0001cb240, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
            ...
apparentlymart commented 3 years ago

I've narrowed down the cause of this to actually be inside Value.Modulo rather than in the modulo function. Specifically it seems to originate here:

https://github.com/zclconf/go-cty/blob/47a79612085e043d528fab49f8687ec6bd6a77e5/cty/value_ops.go#L693-L694

There's apparently some input that makes Divide return an infinity here, which then causes big.Float.Int to return nil, which in turn panics later on while trying to make use of that int.

Value.Modulo is already trying to catch and handle all of the situations that might make Divide return zero, so I don't have a reproduction case with which to understand what input it isn't catching, and so I'm hesitant to just patch over it without knowing what the intended operation was and thus what the result ought to have been.