Skip to content

Bug or bad entry ? #227

@thierry-f-78

Description

@thierry-f-78

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions