go-gorm / gorm

The fantastic ORM library for Golang, aims to be developer friendly
https://gorm.io
MIT License
37.02k stars 3.94k forks source link

Panic saving a struct with nil value field and json serializer #7274

Open mytlogos opened 1 week ago

mytlogos commented 1 week ago

GORM Playground Link

https://github.com/go-gorm/playground/pull/770

Description

When i save a struct with a json serializer field and nil value, gorm panics with this stacktrace:

--- FAIL: TestGORM_failure (0.01s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
        panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x8c5295]

goroutine 53 [running]:
testing.tRunner.func1.2({0xf0dd80, 0x15d6180})
        /usr/local/go/src/testing/testing.go:1631 +0x3f7
testing.tRunner.func1()
        /usr/local/go/src/testing/testing.go:1634 +0x6b6
panic({0xf0dd80?, 0x15d6180?})
        /usr/local/go/src/runtime/panic.go:770 +0x132
gorm.io/gorm/schema.(*Field).setupValuerAndSetter.func17({0x1109750, 0x25cda20}, {0xf5ab00?, 0xc00034b280?, 0x0?}, {0xf15fa0, 0xc000350000})
        /media/MintData/clones/gorm-playground/gorm/schema/field.go:964 +0x1d5
gorm.io/gorm/callbacks.ConvertToAssignments.func2(0xc0000fd400, {0xf15fa0, 0xc000350000})
        /media/MintData/clones/gorm-playground/gorm/callbacks/update.go:149 +0x126
gorm.io/gorm/callbacks.ConvertToAssignments(0xc000450700)
        /media/MintData/clones/gorm-playground/gorm/callbacks/update.go:288 +0x187d
gorm.io/gorm/callbacks.RegisterDefaultCallbacks.Update.func7(0xc000296a80)
        /media/MintData/clones/gorm-playground/gorm/callbacks/update.go:74 +0x326
gorm.io/gorm.(*processor).Execute(0xc000348a00, 0xc000296a80)
        /media/MintData/clones/gorm-playground/gorm/callbacks.go:130 +0xa78
gorm.io/gorm.(*DB).Save(0xc00030dd70, {0xec8c00, 0xc00034b280})
        /media/MintData/clones/gorm-playground/gorm/finisher_api.go:106 +0x9b8
gorm.io/playground.TestGORM_failure(0xc00044eb60?)
        /media/MintData/clones/gorm-playground/main_test.go:29 +0x105
testing.tRunner(0xc00044eb60, 0x10163f0)
        /usr/local/go/src/testing/testing.go:1689 +0x21f
created by testing.(*T).Run in goroutine 1
        /usr/local/go/src/testing/testing.go:1742 +0x826
FAIL    gorm.io/playground      0.177s
FAIL

After debugging it seems that the schema.Field has the Serializer set with a jsonserializer. But when it creates the serializer instance in https://github.com/go-gorm/gorm/blob/deceebfab8c460cfee229233aded2821ac6b08eb/schema/field.go#L494 it uses the field SerializeValuer instead of Serializer. Then it will panic in https://github.com/go-gorm/gorm/blob/deceebfab8c460cfee229233aded2821ac6b08eb/schema/field.go#L964 as it never set Serializer. SerializeValuer is never used again in the codebase.

mytlogos commented 1 week ago

First encountered with 1.25.6, also occurs in 1.25.12 (latest) and master (dev). OS: Linux Mint 22 and Debian 12 Arch: amd64 and arm64 Go: 1.22.0 Driver used: sqlite (though it should be driver-independent)

a631807682 commented 1 week ago

It seems that the Serializer is missing when creating the serializer Are you interested in creating a PR for it?

mytlogos commented 1 week ago

Tbf while i do have a bit of interest into creating an PR, i dont know how i should fix this. My only guess is to use the value in field.Serializer when creating the serializer struct?

edit: Seems like adding it here

return &serializer{
        Field:           field,
        SerializeValuer: s,
        Serializer:      field.Serializer,
        Destination:     v,
        Context:         ctx,
        fieldValue:      value,
}, zero

fixes at least my test case

mytlogos commented 1 week ago

I'll try opening a pr tomorrow