Skip to content

generalListDecoder panics when iterator timeout on decoding message #19

@xnslong

Description

@xnslong

When decoding a message, the Decoder.Decode method is called. (the following code snippet)

Line 24 (L24) tries to decode the message, and it will check the error of iter on decoding finished (L25). However, the L24 may panic (instead of return normally). When the L24 panics, the whole method will panic, not returning the expected error.

go/decoder.go

Lines 16 to 29 in 9b5a675

func (decoder *Decoder) Decode(val interface{}) error {
cfg := decoder.cfg
valType := reflect.TypeOf(val)
valDecoder := cfg.getGenDecoder(valType)
if valDecoder == nil {
valDecoder = cfg.decoderOf(valType)
cfg.addGenDecoder(valType, valDecoder)
}
valDecoder.Decode(val, decoder.iter)
if decoder.iter.Error() != nil {
return decoder.iter.Error()
}
return nil
}

Following is the method where panic may occur.

The underlying Reader of iter may read from a TCP connection (L13). But TCP connection can run timeout, then the underlying Reader will get an error. When such error occurs, the iter will return zero values and set an error. (thus elemType == TypeStop && length == 0 && iter.Error() != nil) When trying to get the generalReaderOf(TypeStop) (L14), this method will panic (See the code snippet, go/general/decode.go#L31).

func (decoder *generalListDecoder) Decode(val interface{}, iter spi.Iterator) {
*val.(*List) = readList(iter).(List)
}
func readList(iter spi.Iterator) interface{} {
elemType, length := iter.ReadListHeader()
generalReader := generalReaderOf(elemType)
var generalList List
for i := 0; i < length; i++ {
generalList = append(generalList, generalReader(iter))
}
return generalList
}

go/general/decode.go

Lines 8 to 33 in 9b5a675

func generalReaderOf(ttype protocol.TType) func(iter spi.Iterator) interface{} {
switch ttype {
case protocol.TypeBool:
return readBool
case protocol.TypeI08:
return readInt8
case protocol.TypeI16:
return readInt16
case protocol.TypeI32:
return readInt32
case protocol.TypeI64:
return readInt64
case protocol.TypeString:
return readString
case protocol.TypeDouble:
return readFloat64
case protocol.TypeList:
return readList
case protocol.TypeMap:
return readMap
case protocol.TypeStruct:
return readStruct
default:
panic("unsupported type")
}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions