Skip to content

Commit 89fc7d1

Browse files
author
James Crasta
committed
Fuzz Fix: decoding enums that are out of range
Fix panic when decoding enums with inputs out of range (should only happen with corrupt input). Add a regression test case.
1 parent a7edd34 commit 89fc7d1

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

datum_reader.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ func (reader sDatumReader) mapEnum(field Schema, dec Decoder) (reflect.Value, er
324324
enumIndex, err := dec.ReadEnum()
325325
if err != nil {
326326
return reflect.ValueOf(enumIndex), err
327+
} else if enumIndex < 0 {
328+
return reflect.ValueOf(enumIndex), fmt.Errorf("Enum index %d < 0 in enum %s", enumIndex, field.GetName())
327329
}
328330

329331
schema := field.(*EnumSchema)
@@ -337,6 +339,10 @@ func (reader sDatumReader) mapEnum(field Schema, dec Decoder) (reflect.Value, er
337339
}
338340
enumSymbolsToIndexCacheLock.Unlock()
339341

342+
if int(enumIndex) >= len(schema.Symbols) {
343+
return reflect.Value{}, fmt.Errorf("Enum index %d too high for enum %s", enumIndex, field.GetName())
344+
}
345+
340346
enum := &GenericEnum{
341347
Symbols: schema.Symbols,
342348
symbolsToIndex: symbolsToIndex,
@@ -400,7 +406,9 @@ func (this sDatumReader) fillRecord(field Schema, record reflect.Value, dec Deco
400406
recordSchema := field.(*RecordSchema)
401407
//ri := record.Interface()
402408
for i := 0; i < len(recordSchema.Fields); i++ {
403-
this.findAndSet(record, recordSchema.Fields[i], dec)
409+
if err := this.findAndSet(record, recordSchema.Fields[i], dec); err != nil {
410+
return err
411+
}
404412
}
405413
}
406414
return nil
@@ -551,6 +559,8 @@ func (reader *GenericDatumReader) mapEnum(field Schema, dec Decoder) (*GenericEn
551559
enumIndex, err := dec.ReadEnum()
552560
if err != nil {
553561
return nil, err
562+
} else if enumIndex < 0 {
563+
return nil, fmt.Errorf("Enum index %d < 0 in schema %s", enumIndex, field.GetName())
554564
}
555565

556566
schema := field.(*EnumSchema)

datum_reader_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,37 @@ func enumRaceTest(t *testing.T, schemas []Schema) {
615615

616616
}
617617

618+
func TestEnumNegativeRegression(t *testing.T) {
619+
var playingCard struct {
620+
Type *GenericEnum
621+
}
622+
var genericDest = NewGenericRecord(schemaEnumA)
623+
reader := NewDatumReader(schemaEnumA)
624+
625+
///////////
626+
// Scenario 1: negative index
627+
628+
var buf = []byte{0x7} // This is the encoding of the varint -4
629+
// Before this fix, this panicked.
630+
err := reader.Read(genericDest, NewBinaryDecoder(buf))
631+
assert(t, err.Error(), "Enum index -4 < 0 in schema Type")
632+
633+
err = reader.Read(&playingCard, NewBinaryDecoder(buf))
634+
//assert(t, err.Error(), "Enum index -4 < 0 in schema Type")
635+
636+
///////////
637+
// Scenario 2: too-large positive index
638+
639+
buf = []byte{0x78} // This is the encoding of the varint 60
640+
err = reader.Read(genericDest, NewBinaryDecoder(buf))
641+
assert(t, err.Error(), "Enum index invalid!")
642+
643+
playingCard.Type = nil
644+
err = reader.Read(&playingCard, NewBinaryDecoder(buf))
645+
assert(t, err.Error(), "Enum index 60 too high for enum Type")
646+
647+
}
648+
618649
func parallelF(numRoutines, numLoops int, f func(routine, loop int)) {
619650
var wg sync.WaitGroup
620651
wg.Add(numRoutines)

0 commit comments

Comments
 (0)