sijms / go-ora

Pure go oracle client
MIT License
800 stars 177 forks source link

rows.Next will panic when some special data #431

Closed Ranxy closed 1 year ago

Ranxy commented 1 year ago

version in use go 1.21.0 github.com/sijms/go-ora/v2 v2.7.14

panic stack

encoding/binary.bigEndian.Uint16(...)
        /home/test/src/go/go/src/encoding/binary/binary.go:139
github.com/sijms/go-ora/v2/converters.(*StringConverter).Decode(0xc004c1e420, {0xc0096ed480, 0x3, 0x40})
        /home/test/go/pkg/mod/github.com/sijms/go-ora/v2@v2.7.14/converters/string_conversion.go:210 +0x8e7
github.com/sijms/go-ora/v2.(*ParameterInfo).decodePrimValue(0xc004bc6db0, 0xc000427180, 0x0)
        /home/test/go/pkg/mod/github.com/sijms/go-ora/v2@v2.7.14/parameter.go:972 +0x722
github.com/sijms/go-ora/v2.(*ParameterInfo).decodeColumnValue(0xc004bc6db0?, 0x47d229?, 0x2?)
        /home/test/go/pkg/mod/github.com/sijms/go-ora/v2@v2.7.14/parameter.go:1293 +0x3ae
github.com/sijms/go-ora/v2.(*defaultStmt).calculateColumnValue(0xc01d4f9800?, 0x1?, 0x20?)
        /home/test/go/pkg/mod/github.com/sijms/go-ora/v2@v2.7.14/command.go:1357 +0x126
github.com/sijms/go-ora/v2.(*defaultStmt).read(0xc004bbe0a0, 0xc004760fc0)
        /home/test/go/pkg/mod/github.com/sijms/go-ora/v2@v2.7.14/command.go:778 +0x101e
github.com/sijms/go-ora/v2.(*defaultStmt)._fetch(0xc004bbe0a0, 0x5?)
        /home/test/go/pkg/mod/github.com/sijms/go-ora/v2@v2.7.14/command.go:625 +0x165
github.com/sijms/go-ora/v2.(*defaultStmt).fetch(0x1000000442388?, 0x7f8beb54d3f0?)
        /home/test/go/pkg/mod/github.com/sijms/go-ora/v2@v2.7.14/command.go:568 +0x59
github.com/sijms/go-ora/v2.(*DataSet).Next(0xc004760fc0, {0xc004761170, 0x9, 0x0?})
        /home/test/go/pkg/mod/github.com/sijms/go-ora/v2@v2.7.14/data_set.go:317 +0x202
database/sql.(*Rows).nextLocked(0xc004761050)
        /home/test/src/go/go/src/database/sql/sql.go:3019 +0x107
database/sql.(*Rows).Next.func1()
        /home/test/src/go/go/src/database/sql/sql.go:2994 +0x29
database/sql.withLock({0x2b53af8, 0xc004761088}, 0xc00430d108)
        /home/test/src/go/go/src/database/sql/sql.go:3502 +0x82
database/sql.(*Rows).Next(0xc004761050)
        /home/test/src/go/go/src/database/sql/sql.go:2993 +0x85

row.rowsi.data.Cols

[]github.com/sijms/go-ora/v2.ParameterInfo len: 9, cap: 9, [{Name: "OWNER", TypeName: "", Direction: 0, IsNull: false, AllowNull: false, ColAlias: "", DataType: NCHAR (1), IsXmlType: false, Flag: 128, Precision: 0, Scale: 0, MaxLen: 30, MaxCharLen: 30, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 852, CharsetForm: 1, BValue: []uint8 len: 3, cap: 64, [67,82,66], Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value(string) *(*"database/sql/driver.Value")(0xc0004435d8), OutputVarPtr: interface {} nil, getDataFromServer: false, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil},{Name: "TABLE_NAME", TypeName: "", Direction: 0, IsNull: false, AllowNull: false, ColAlias: "", DataType: NCHAR (1), IsXmlType: false, Flag: 128, Precision: 0, Scale: 0, MaxLen: 30, MaxCharLen: 30, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 852, CharsetForm: 1, BValue: []uint8 len: 16, cap: 64, [79,68,83,95,67,82,95,78,67,67,95,67,72,69,67,75], Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value(string) *(*"database/sql/driver.Value")(0xc0004436e8), OutputVarPtr: interface {} nil, getDataFromServer: false, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil},{Name: "COLUMN_NAME", TypeName: "", Direction: 0, IsNull: false, AllowNull: false, ColAlias: "", DataType: NCHAR (1), IsXmlType: false, Flag: 128, Precision: 0, Scale: 0, MaxLen: 30, MaxCharLen: 30, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 852, CharsetForm: 1, BValue: []uint8 len: 4, cap: 64, [78,67,73,68], Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value(string) *(*"database/sql/driver.Value")(0xc0004437f8), OutputVarPtr: interface {} nil, getDataFromServer: false, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil},{Name: "COMMENTS", TypeName: "", Direction: 0, IsNull: false, AllowNull: true, ColAlias: "", DataType: NCHAR (1), IsXmlType: false, Flag: 128, Precision: 0, Scale: 0, MaxLen: 4000, MaxCharLen: 4000, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 852, CharsetForm: 1, BValue: []uint8 len: 3, cap: 64, [191,191,191], Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value nil, OutputVarPtr: interface {} nil, getDataFromServer: true, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil},{Name: "DATA_TYPE", TypeName: "", Direction: 0, IsNull: false, AllowNull: true, ColAlias: "", DataType: NCHAR (1), IsXmlType: false, Flag: 128, Precision: 0, Scale: 0, MaxLen: 106, MaxCharLen: 106, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 852, CharsetForm: 1, BValue: []uint8 len: 6, cap: 64, [78,85,77,66,69,82], Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value(string) *(*"database/sql/driver.Value")(0xc000443a18), OutputVarPtr: interface {} nil, getDataFromServer: false, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil},{Name: "DATA_LENGTH", TypeName: "", Direction: 0, IsNull: false, AllowNull: false, ColAlias: "", DataType: NUMBER (2), IsXmlType: false, Flag: 0, Precision: 38, Scale: 255, MaxLen: 22, MaxCharLen: 0, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 0, CharsetForm: 0, BValue: []uint8 len: 2, cap: 64, [193,23], Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value(float64) *(*"database/sql/driver.Value")(0xc000443b28), OutputVarPtr: interface {} nil, getDataFromServer: false, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil},{Name: "COLUMN_ID", TypeName: "", Direction: 0, IsNull: false, AllowNull: true, ColAlias: "", DataType: NUMBER (2), IsXmlType: false, Flag: 0, Precision: 38, Scale: 255, MaxLen: 22, MaxCharLen: 0, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 0, CharsetForm: 0, BValue: []uint8 len: 2, cap: 64, [193,2], Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value(float64) *(*"database/sql/driver.Value")(0xc000443c38), OutputVarPtr: interface {} nil, getDataFromServer: false, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil},{Name: "DATA_DEFAULT", TypeName: "", Direction: 0, IsNull: false, AllowNull: true, ColAlias: "", DataType: LONG (8), IsXmlType: false, Flag: 128, Precision: 0, Scale: 0, MaxLen: 0, MaxCharLen: 0, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 852, CharsetForm: 1, BValue: []uint8 len: 0, cap: 0, nil, Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value nil, OutputVarPtr: interface {} nil, getDataFromServer: true, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil},{Name: "NULLABLE", TypeName: "", Direction: 0, IsNull: false, AllowNull: true, ColAlias: "", DataType: NCHAR (1), IsXmlType: false, Flag: 128, Precision: 0, Scale: 0, MaxLen: 1, MaxCharLen: 1, MaxNoOfArrayElements: 0, ContFlag: 0, ToID: []uint8 len: 0, cap: 0, nil, Version: 0, CharsetID: 852, CharsetForm: 1, BValue: []uint8 len: 1, cap: 64, [78], Value: database/sql/driver.Value nil, iPrimValue: database/sql/driver.Value nil, oPrimValue: database/sql/driver.Value(string) *(*"database/sql/driver.Value")(0xc000443e58), OutputVarPtr: interface {} nil, getDataFromServer: false, oaccollid: 0, cusType: *github.com/sijms/go-ora/v2.customType nil}]

The problem seems to be when encountering special data like this BValue: []uint8 len: 3, cap: 64, [191,191,191] https://github.com/sijms/go-ora/blob/v2.7.14/converters/string_conversion.go#L204-L208 will panic the binary.BigEndian.Uint16(input[index:]) need two byte but if index+1 > len(input)can only guarantee at least one byte

sijms commented 1 year ago

would you please write an example code that produce the error

sijms commented 1 year ago

yes you are correct it should be if index + 1 >= Len(input)

sijms commented 1 year ago

I add a fix in v2.7.17 would you please test if issue is solved?

Ranxy commented 1 year ago

Sorry for not following this weekend. It seems that this fix doesn't handle the code for V2 https://github.com/sijms/go-ora/blob/v2.7.17/v2/converters/string_conversion.go#L206-L211