func DeepEqual(x, y any) bool {
if x == nil || y == nil {
return x == y // <------
}
The relevant sonar.go line is:
func serialize(v, v2 interface{}, buf []byte) (n, flags uint8) {
switch vv := v.(type) {
// omit many cases
default:
// Special case: string literal is compared with a variable of
// user type with string underlying type:
// type Name string
// var name Name
// if name == "foo" { ... }
if _, ok := v2.(string); ok {
s := *(*string)((*iface)(unsafe.Pointer(&v)).val) // <--------
if len(s) <= SonarMaxLen {
return uint8(copy(buf[:], s)), SonarString
}
}
// ...
I think this code contains a faulty assumption. If v has an interface type (as with reflect.DeepEqual), it can be compared with a string without itself being a string. The iface conversion is thus unsafe. I believe in this case it is due to a nil interface being compared with a string, causing a nil pointer dereference when reading the iface.val field.
If anyone cares (unlikely), this should be made safer, probably by using reflect.Type.
While fuzzing something, I got this crash:
The relevant reflect.DeepEqual code is:
The relevant sonar.go line is:
I think this code contains a faulty assumption. If v has an interface type (as with reflect.DeepEqual), it can be compared with a string without itself being a string. The iface conversion is thus unsafe. I believe in this case it is due to a nil interface being compared with a string, causing a nil pointer dereference when reading the
iface.val
field.If anyone cares (unlikely), this should be made safer, probably by using reflect.Type.