cast icon indicating copy to clipboard operation
cast copied to clipboard

Bug or bad entry ?

Open thierry-f-78 opened this issue 5 months ago • 0 comments

This code:

package main

import "time"
import "github.com/spf13/cast"

func main() {
	var now *time.Time
	var s string
	var err error

	s, err= cast.ToStringE(now)
	println(s, err)
}

Produces a segfault.

I see in the caste.go file, function ToStringE this line, which seems handle this case:

switch s := i.(type) {
	...
	case nil:
		return "", nil
	case fmt.Stringer:
		return s.String(), nil
	...
}

Unfortunately, the nil case is not handled, and the nil *time.Time match the fmt.Stringer prototype. The result is a segfault.

To prevent this behaviour I control the input with this code:

var v reflect.Value

v = reflect.ValueOf(val)
switch v.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice:
	if v.IsNil() {
		return "", nil
	}
}
return cast.ToStringE(UntypedValue(val))

Does the ToStringE need to support this case and the library needs a fix, or I lust control my inputs ? I think It will be better to the function ToStringE accept any kind of inputs, it will be easier to use the function.

It seems there are only two cases of interface dereference:

	case fmt.Stringer:
		return s.String(), nil
	case error:
		return s.Error(), nil

So, a fix could be:

	case fmt.Stringer:
		if s == nil {
				return "", nil
		}
		return s.String(), nil
	case error:
		if s == nil {
				return "", nil
		}
		return s.Error(), nil

Note: I do not look for other cast function to search similar behavior.

thierry-f-78 avatar Sep 23 '24 07:09 thierry-f-78