Skip to content

database/sql: possible new panic doing reflect-based conversions #46730

Closed
@josharian

Description

@josharian

Go 1.17 adds conversions from []T to *[N]T, including via the reflect package. Such conversions may panic if N is larger than the slice length. Whether reflection-based conversion is possible without panicking is thus now no longer a function only of the types involved. As a result, even if v.Type().ConvertibleTo(w.Type()) returns true, v.Convert(w.Type()) may panic. This is documented in package reflect.

database/sql/convert.go contains code that appears to rely on that now-broken invariant:

func convertAssignRows(dest, src interface{}, rows *Rows) error {
	// ...
	if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
		dv.Set(sv.Convert(dv.Type()))
		return nil
	}
	// ...
}

(text/template has similar code, but it is guarded with a check that the types are int-like.)

This sv.Convert call couldn't panic in 1.16; now it can.

What should we do here?

  • (a) recover from the panic and return an error saying the conversion failed
  • (b) panic
  • (c) recover from the panic and continue as if the types weren't convertible

(a) seems like the clearest error output. (b) is simple. It also matches the handling in the standard library of reflect.Type.Comparable: In a few places, we check reflect.Type.Comparable and then blindly use ==, even though that can panic. (c) most closely preserves the 1.16 behavior.

I lean towards (a) but would like to discuss. And if we do (a) or (c), should we give reflect.Type.Comparable/== the same treatment?

Marking as a 1.17 release-blocker, pending a decision about severity and how we want to proceed.

cc @dsnet @ianlancetaylor @mdempsky @OneOfOne

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.release-blocker

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions