aerospike / aerospike-client-go

Aerospike Client Go
Apache License 2.0
429 stars 199 forks source link

Panic in GetObject with large number in Map #345

Closed t4110 closed 3 years ago

t4110 commented 3 years ago

Hello

A panic occurs when getting a map with a large integer element by GetObject.

test code

package main

import (
    "fmt"
    "os"

    asc "github.com/aerospike/aerospike-client-go"
)

type Map struct {
    Num int64 `as:"num"`
}

type Test struct {
    Test Map `as:"test"`
}

func exitOnError(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

func main() {
    client, err := asc.NewClient("aerospike", 3000)
    exitOnError(err)

    // success
    key1, err := asc.NewKey("test", "test", "uint32Max")
    exitOnError(err)

    rec1 := Test{}

    err = client.GetObject(nil, key1, &rec1)
    exitOnError(err)

    fmt.Printf("rec1=%+v\n", rec1)

    // failure
    key2, err := asc.NewKey("test", "test", "uint32Max+1")
    exitOnError(err)

    rec2 := Test{}

    err = client.GetObject(nil, key2, &rec2) // panic!
    exitOnError(err)

    fmt.Printf("rec2=%+v\n", rec2)
}

server data

aql> select * from test.test
+---------------+---------------------------+
| PK            | test                      |
+---------------+---------------------------+
| "uint32Max+1" | MAP('{"num":4294967296}') |
| "uint32Max"   | MAP('{"num":4294967295}') |
+---------------+---------------------------+
2 rows in set (0.028 secs)

OK

result

$ go run .
rec1={Test:{Num:4294967295}}
panic: interface conversion: interface {} is uint64, not int

goroutine 1 [running]:
github.com/aerospike/aerospike-client-go.setValue(0x707f60, 0xc000134b90, 0x186, 0x708820, 0xc000134ba0, 0x1, 0x707f60, 0xc000134b90)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/read_command_reflect.go:151 +0x48ed
github.com/aerospike/aerospike-client-go.setStructValue(0x726f40, 0xc000134b90, 0x199, 0xc00011d080, 0x726f01, 0x8022a0, 0x726f40, 0x0, 0x0, 0x0, .
..)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/read_command_reflect.go:460 +0x406
github.com/aerospike/aerospike-client-go.setValue(0x726f40, 0xc000134b90, 0x199, 0x7164a0, 0xc00011d080, 0x1, 0x726f40, 0xc000134b90)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/read_command_reflect.go:425 +0x4033
github.com/aerospike/aerospike-client-go.setObjectField(0xc000206720, 0x726fc0, 0xc000134b90, 0x199, 0xc0001638b8, 0x4, 0x7164a0, 0xc00011d080, 0x1
, 0x0, ...)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/read_command_reflect.go:136 +0xff
github.com/aerospike/aerospike-client-go.parseObject(0xc000144460, 0x1, 0x0, 0xffffffff00000001, 0x1b, 0x1b)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/read_command_reflect.go:90 +0x413
github.com/aerospike/aerospike-client-go.(*readCommand).parseResult(0xc000144460, 0x800ea0, 0xc000144460, 0xc000228140, 0x49, 0x0)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/read_command.go:171 +0x5d1
github.com/aerospike/aerospike-client-go.(*baseCommand).executeAt(0xc000144460, 0x800ea0, 0xc000144460, 0xc00022c100, 0xc00022c101, 0x0, 0x0, 0x0,
0x0, 0x0, ...)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/command.go:2175 +0x9c6
github.com/aerospike/aerospike-client-go.(*baseCommand).execute(0xc000144460, 0x800ea0, 0xc000144460, 0xc000202001, 0x1, 0x1)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/command.go:2038 +0xda
github.com/aerospike/aerospike-client-go.(*readCommand).Execute(...)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/read_command.go:264
github.com/aerospike/aerospike-client-go.(*Client).GetObject(0xc000214140, 0x0, 0xc0001aa000, 0x6fb640, 0xc000134b90, 0x7f0d10, 0xc0001aa000)
        /go/pkg/mod/github.com/aerospike/aerospike-client-go@v4.3.0+incompatible/client_reflect.go:76 +0x2bb
main.main()
        /tmp/astest/main.go:46 +0x273
exit status 2

Is this a bug in the client library?

khaf commented 3 years ago

I can't tell if this is a Go client bug, since I don't know how that data was put in the database. Are you using multiple clients in different languages?

t4110 commented 3 years ago

In this example, I used AQL commands.

INSERT INTO test.test (PK, test) VALUES ("uint32Max", 'JSON{"num":4294967295}')
INSERT INTO test.test (PK, test) VALUES ("uint32Max+1", 'JSON{"num":4294967296}')

Since 4294967296 is a range of signed 64-bit integers, I believe it is supported by Aerospike also in map data types. Is this a correct understanding?

khaf commented 3 years ago

Yes, this is a client bug, although it is a surprise that AQL converts the json numbers to uint64. Will release a fix today.

khaf commented 3 years ago

Fix is released in v4.4.0. Corresponding commit: https://github.com/aerospike/aerospike-client-go/commit/be40447b1071ecee1443e918248a8df39735121a Feel free to close the issue if it is resolved.

t4110 commented 3 years ago

The problem looks fixed. Thanks for your quick action.