Skip to content

Commit

Permalink
Skip invalid elements byte by byte (#145)
Browse files Browse the repository at this point in the history
  • Loading branch information
at-wat authored Feb 16, 2021
1 parent 148d3e6 commit 1d0de7b
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 33 deletions.
10 changes: 6 additions & 4 deletions matroska_official_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,19 @@ func TestMatroskaOfficial(t *testing.T) {
"HeaderStrippingAndStandardBlock": {
filename: "test3.mkv",
},
// "LiveStreamRecording": {
// filename: "test4.mkv",
// },
"LiveStreamRecording": {
filename: "test4.mkv",
opts: []UnmarshalOption{WithIgnoreUnknown(true)},
},
"MultipleAudioSubtitles": {
filename: "test5.mkv",
},
"DifferentEBMLHeadSizesAndCueLessSeeking": {
filename: "test6.mkv",
},
// "ExtraUnknownJunkElementsDamaged": {
// filename: "test7.mkv",
// filename: "test7.mkv",
// opts: []UnmarshalOption{WithIgnoreUnknown(true)},
// },
"AudioGap": {
filename: "test8.mkv",
Expand Down
29 changes: 15 additions & 14 deletions unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,23 @@ func readElement(r0 io.Reader, n int64, vo reflect.Value, depth int, pos uint64,
if nb == 0 && err == io.ErrUnexpectedEOF {
return nil, io.EOF
}
return nil, err
if !options.ignoreUnknown {
return nil, err
}
return nil, nil
}
v, ok := revTable[uint32(e)]
if !ok && !options.ignoreUnknown {
return nil, wrapErrorf(ErrUnknownElement, "unmarshalling element 0x%x", e)
if !ok {
if !options.ignoreUnknown {
return nil, wrapErrorf(ErrUnknownElement, "unmarshalling element 0x%x", e)
}
remain, _ := encodeElementID(e)
r = io.MultiReader(
bytes.NewReader(remain[1:]),
r,
)
pos++
continue
}

size, nb, err := readDataSize(r)
Expand All @@ -113,17 +125,6 @@ func readElement(r0 io.Reader, n int64, vo reflect.Value, depth int, pos uint64,
return nil, err
}

if !ok {
if size == SizeUnknown {
return nil, wrapErrorf(ErrUnknownElement, "unmarshalling unknown size element 0x%x", e)
}
if _, err := readBinary(r, size); err != nil {
return nil, err
}
pos += headerSize + size
continue
}

var vnext reflect.Value
if !mapOut {
if vn, ok := fieldMap[v.e]; ok {
Expand Down
29 changes: 14 additions & 15 deletions unmarshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,9 @@ func TestUnmarshal_Map(t *testing.T) {

func TestUnmarshal_IgnoreUnknown(t *testing.T) {
b := []byte{
0x1A, 0x45, 0xDF, 0xA3, 0x8C,
0x81, 0x82, 0x00, 0x00, // 0x81 is not defined in Matroska v4
0x1A, 0x45, 0xDF, 0xA3, 0x8A,
0x42, 0x82, 0x85, 0x68, 0x6F, 0x67, 0x65, 0x00,
0x81, 0x81, // 0x81 is not defined in Matroska v4
0x18, 0x53, 0x80, 0x67, 0xFF,
0x1F, 0x43, 0xB6, 0x75, 0x80,
0x1F, 0x43, 0xB6, 0x75, 0x80,
Expand All @@ -421,7 +421,7 @@ func TestUnmarshal_IgnoreUnknown(t *testing.T) {
}

if !reflect.DeepEqual(expected, ret) {
t.Errorf("Unmarshal to map differs from expected:\n%#+v\ngot:\n%#+v", expected, ret)
t.Errorf("Unmarshal with IgnoreUnknown differs from expected:\n%#+v\ngot:\n%#+v", expected, ret)
}
}

Expand All @@ -432,12 +432,12 @@ func TestUnmarshal_Error(t *testing.T) {
}
t.Run("NilValue", func(t *testing.T) {
if err := Unmarshal(bytes.NewBuffer([]byte{}), nil); !errs.Is(err, ErrIndefiniteType) {
t.Errorf("Expected error: '%v', got: '%v'\n", ErrIndefiniteType, err)
t.Errorf("Expected error: '%v', got: '%v'", ErrIndefiniteType, err)
}
})
t.Run("NonPtr", func(t *testing.T) {
if err := Unmarshal(bytes.NewBuffer([]byte{}), struct{}{}); !errs.Is(err, ErrIncompatibleType) {
t.Errorf("Expected error: '%v', got: '%v'\n", ErrIncompatibleType, err)
t.Errorf("Expected error: '%v', got: '%v'", ErrIncompatibleType, err)
}
})
t.Run("UnknownElementName", func(t *testing.T) {
Expand All @@ -446,32 +446,32 @@ func TestUnmarshal_Error(t *testing.T) {
} `ebml:"Unknown"`
}{}
if err := Unmarshal(bytes.NewBuffer([]byte{}), input); !errs.Is(err, ErrUnknownElementName) {
t.Errorf("Expected error: '%v', got: '%v'\n", ErrUnknownElementName, err)
t.Errorf("Expected error: '%v', got: '%v'", ErrUnknownElementName, err)
}
})
t.Run("UnknownElement", func(t *testing.T) {
input := &TestEBML{}
b := []byte{0x81}
if err := Unmarshal(bytes.NewBuffer(b), input); !errs.Is(err, ErrUnknownElement) {
t.Errorf("Expected error: '%v', got: '%v'\n", ErrUnknownElement, err)
t.Errorf("Expected error: '%v', got: '%v'", ErrUnknownElement, err)
}
})
t.Run("NonStaticUnknownElementWithIgnoreUnknown", func(t *testing.T) {
input := &TestEBML{}
b := []byte{0x81, 0xFF}
if err := Unmarshal(
bytes.NewBuffer(b), input, WithIgnoreUnknown(true),
); !errs.Is(err, ErrUnknownElement) {
t.Errorf("Expected error: '%v', got: '%v'\n", ErrUnknownElement, err)
); err != nil {
t.Errorf("Unexpected error: '%v'", err)
}
})
t.Run("ShortUnknownElementWithIgnoreUnknown", func(t *testing.T) {
input := &TestEBML{}
b := []byte{0x81, 0x85, 0x00}
if err := Unmarshal(
bytes.NewBuffer(b), input, WithIgnoreUnknown(true),
); !errs.Is(err, io.ErrUnexpectedEOF) {
t.Errorf("Expected error: '%v', got: '%v'\n", io.ErrUnexpectedEOF, err)
); err != nil {
t.Errorf("Unexpected error: '%v'", err)
}
})
t.Run("Short", func(t *testing.T) {
Expand All @@ -489,7 +489,7 @@ func TestUnmarshal_Error(t *testing.T) {
t.Run(name, func(t *testing.T) {
var val TestEBML
if err := Unmarshal(bytes.NewBuffer(b), &val); !errs.Is(err, io.ErrUnexpectedEOF) {
t.Errorf("Expected error: '%v', got: '%v'\n", io.ErrUnexpectedEOF, err)
t.Errorf("Expected error: '%v', got: '%v'", io.ErrUnexpectedEOF, err)
}
})
}
Expand All @@ -510,7 +510,7 @@ func TestUnmarshal_Error(t *testing.T) {
var val TestEBML
r := &delayedBrokenReader{b: b, limit: i}
if err := Unmarshal(r, &val); !errs.Is(err, io.ErrClosedPipe) {
t.Errorf("Error is not propagated from Reader, limit: %d, expected: '%v', got: '%v'\n", i, io.ErrClosedPipe, err)
t.Errorf("Error is not propagated from Reader, limit: %d, expected: '%v', got: '%v'", i, io.ErrClosedPipe, err)
}
}
})
Expand Down Expand Up @@ -582,12 +582,11 @@ func TestUnmarshal_Error(t *testing.T) {
for name, c := range cases {
t.Run(name, func(t *testing.T) {
if err := Unmarshal(bytes.NewBuffer(c.b), c.ret); !errs.Is(err, c.err) {
t.Errorf("Expected error: '%v', got: '%v'\n", c.err, err)
t.Errorf("Expected error: '%v', got: '%v'", c.err, err)
}
})
}
})

}

func BenchmarkUnmarshal(b *testing.B) {
Expand Down

0 comments on commit 1d0de7b

Please sign in to comment.