mirror of
https://github.com/wader/fq.git
synced 2024-09-11 12:05:39 +03:00
decode,interp: Make fuzzing work again and cleanup fatal/error code
This commit is contained in:
parent
f9f866000e
commit
b66ed32614
7
Makefile
7
Makefile
@ -90,3 +90,10 @@ update-gomod:
|
||||
GOPROXY=direct go get -d github.com/wader/readline@fq
|
||||
GOPROXY=direct go get -d github.com/wader/gojq@fq
|
||||
go mod tidy
|
||||
|
||||
# TODO: as decode recovers panic and "repanics" unrecoverable errors this is a bit hacky at the moment
|
||||
# fuzz code is not suppose to print to stderr so log to file
|
||||
.PHONY: fuzz
|
||||
fuzz:
|
||||
# in other terminal: tail -f /tmp/repanic
|
||||
REPANIC_LOG=/tmp/repanic gotip test -tags fuzz -v -fuzz=Fuzz ./format/
|
||||
|
@ -92,7 +92,7 @@ func gzDecode(d *decode.D, in interface{}) interface{} {
|
||||
uncompressed := &bytes.Buffer{}
|
||||
crc32W := crc32.NewIEEE()
|
||||
if _, err := decode.Copy(d, io.MultiWriter(uncompressed, crc32W), deflateR); err != nil {
|
||||
d.Invalid(err.Error())
|
||||
d.Fatal(err.Error())
|
||||
}
|
||||
// calculatedCRC32 := crc32W.Sum(nil)
|
||||
uncompressedBB := bitio.NewBufferFromBytes(uncompressed.Bytes(), -1)
|
||||
|
@ -143,7 +143,7 @@ func fieldFormatLabel(d *decode.D, name string) {
|
||||
}
|
||||
jumpCount++
|
||||
if jumpCount > maxJumps {
|
||||
d.Invalid(fmt.Sprintf("label has more than %d jumps", maxJumps))
|
||||
d.Fatal(fmt.Sprintf("label has more than %d jumps", maxJumps))
|
||||
}
|
||||
d.SeekAbs(int64(pointer) * 8)
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ func elfDecode(d *decode.D, in interface{}) interface{} {
|
||||
case BIG_ENDIAN:
|
||||
d.Endian = decode.BigEndian
|
||||
default:
|
||||
d.Invalid("unknown endian")
|
||||
d.Fatal("unknown endian")
|
||||
}
|
||||
|
||||
// TODO: hex functions?
|
||||
|
@ -78,7 +78,7 @@ func utf8Uint(d *decode.D) uint64 {
|
||||
n = n<<6 | d.U8()&0x3f
|
||||
}
|
||||
default:
|
||||
d.Invalid("invalid UTF8Uint")
|
||||
d.Error("invalid UTF8Uint")
|
||||
}
|
||||
return n
|
||||
}
|
||||
@ -164,7 +164,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
switch sampleRateBits {
|
||||
case 0:
|
||||
if inStreamInfo == nil {
|
||||
d.Invalid("streaminfo required for sample rate")
|
||||
d.Fatal("streaminfo required for sample rate")
|
||||
}
|
||||
return decode.Scalar{Actual: sampleRateBits, Sym: inStreamInfo.SampleRate, Description: "streaminfo"}
|
||||
case 0b0001:
|
||||
@ -256,7 +256,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
return decode.Scalar{Actual: v, Sym: ch, Description: desc}
|
||||
})
|
||||
if channels == 0 {
|
||||
d.Invalid("unknown number of channels")
|
||||
d.Fatal("unknown number of channels")
|
||||
}
|
||||
|
||||
// <3> Sample size in bits:
|
||||
@ -274,7 +274,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
switch sampleSizeBits {
|
||||
case 0b000:
|
||||
if inStreamInfo == nil {
|
||||
d.Invalid("streaminfo required for bit per sample")
|
||||
d.Fatal("streaminfo required for bit per sample")
|
||||
}
|
||||
sampleSize = int(inStreamInfo.BitPerSample)
|
||||
s.Description = "streaminfo"
|
||||
@ -394,7 +394,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
|
||||
subframeSampleSize := sampleSize - wastedBitsK
|
||||
if subframeSampleSize < 0 {
|
||||
d.Invalid(fmt.Sprintf("negative subframeSampleSize %d", subframeSampleSize))
|
||||
d.Fatal(fmt.Sprintf("negative subframeSampleSize %d", subframeSampleSize))
|
||||
}
|
||||
// if channel is side, add en extra sample bit
|
||||
// https://github.com/xiph/flac/blob/37e675b777d4e0de53ac9ff69e2aea10d92e729c/src/libFLAC/stream_decoder.c#L2040
|
||||
@ -405,7 +405,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
|
||||
decodeWarmupSamples := func(samples []int64, n int, sampleSize int) {
|
||||
if len(samples) < n {
|
||||
d.Invalid("decodeWarmupSamples outside block size")
|
||||
d.Fatal("decodeWarmupSamples outside block size")
|
||||
}
|
||||
|
||||
d.FieldArray("warmup_samples", func(d *decode.D) {
|
||||
@ -473,7 +473,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
riceParameter := int(d.FieldU("rice_parameter", riceBits))
|
||||
|
||||
if samplesLen < n+count {
|
||||
d.Invalid("decodeResiduals outside block size")
|
||||
d.Fatal("decodeResiduals outside block size")
|
||||
}
|
||||
|
||||
if riceParameter == riceEscape {
|
||||
@ -559,7 +559,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
// <5> Quantized linear predictor coefficient shift needed in bits (NOTE: this number is signed two's-complement).
|
||||
shift := d.FieldS5("shift")
|
||||
if shift < 0 {
|
||||
d.Invalid(fmt.Sprintf("negative LPC shift %d", shift))
|
||||
d.Fatal(fmt.Sprintf("negative LPC shift %d", shift))
|
||||
}
|
||||
// <n> Unencoded predictor coefficients (n = qlp coeff precision * lpc order) (NOTE: the coefficients are signed two's-complement).
|
||||
var coeffs []int64
|
||||
@ -594,7 +594,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
streamSamples := len(channelSamples[0])
|
||||
for j := 0; j < len(channelSamples); j++ {
|
||||
if streamSamples > len(channelSamples[j]) {
|
||||
d.Invalid(fmt.Sprintf("different amount of samples in channels %d != %d", streamSamples, len(channelSamples[j])))
|
||||
d.Fatal(fmt.Sprintf("different amount of samples in channels %d != %d", streamSamples, len(channelSamples[j])))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ func metadatablockDecode(d *decode.D, in interface{}) interface{} {
|
||||
case MetadataBlockStreaminfo:
|
||||
flacStreaminfoOut, ok := d.Format(flacStreaminfoFormat, nil).(format.FlacStreaminfoOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected FlacStreaminfoOut, got %#+v", flacStreaminfoOut))
|
||||
panic(fmt.Sprintf("expected FlacStreaminfoOut, got %#+v", flacStreaminfoOut))
|
||||
}
|
||||
hasStreamInfo = true
|
||||
streamInfo = flacStreaminfoOut.StreamInfo
|
||||
|
@ -28,10 +28,10 @@ func metadatablocksDecode(d *decode.D, in interface{}) interface{} {
|
||||
|
||||
isLastBlock := false
|
||||
for !isLastBlock {
|
||||
_, flacMetadatablockOutAny := d.FieldFormat("metadatablock", flacMetadatablockForamt, nil)
|
||||
flacMetadatablockOut, ok := flacMetadatablockOutAny.(format.FlacMetadatablockOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected FlacMetadatablocksOut, got %#+v", flacMetadatablockOut))
|
||||
v, dv := d.FieldFormat("metadatablock", flacMetadatablockForamt, nil)
|
||||
flacMetadatablockOut, ok := dv.(format.FlacMetadatablockOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected FlacMetadatablocksOut, got %#+v", flacMetadatablockOut))
|
||||
}
|
||||
isLastBlock = flacMetadatablockOut.IsLastBlock
|
||||
if flacMetadatablockOut.HasStreamInfo {
|
||||
|
@ -1,4 +1,4 @@
|
||||
//go:build gofuzzbeta
|
||||
//go:build fuzz
|
||||
|
||||
package format_test
|
||||
|
||||
@ -6,19 +6,36 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
_ "github.com/wader/fq/format/all"
|
||||
"github.com/wader/fq/pkg/interp"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
_ "github.com/wader/fq/format/all"
|
||||
"github.com/wader/fq/format/registry"
|
||||
"github.com/wader/fq/pkg/interp"
|
||||
)
|
||||
|
||||
type fuzzFS struct{}
|
||||
|
||||
func (fuzzFS) Open(name string) (fs.File, error) {
|
||||
return nil, fmt.Errorf("%s: file not found", name)
|
||||
}
|
||||
|
||||
type fuzzTest struct {
|
||||
b []byte
|
||||
}
|
||||
|
||||
type fuzzTestInput struct {
|
||||
interp.FileReader
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (fuzzTestInput) IsTerminal() bool { return false }
|
||||
func (fuzzTestInput) Size() (int, int) { return 120, 25 }
|
||||
|
||||
type fuzzTestOutput struct {
|
||||
io.Writer
|
||||
}
|
||||
@ -26,18 +43,20 @@ type fuzzTestOutput struct {
|
||||
func (o fuzzTestOutput) Size() (int, int) { return 120, 25 }
|
||||
func (o fuzzTestOutput) IsTerminal() bool { return false }
|
||||
|
||||
func (ft *fuzzTest) Stdin() io.Reader { return bytes.NewBuffer(ft.b) } // TODO: special file?
|
||||
func (ft *fuzzTest) Stdin() interp.Input {
|
||||
return fuzzTestInput{FileReader: interp.FileReader{R: bytes.NewBuffer(ft.b)}}
|
||||
}
|
||||
func (ft *fuzzTest) Stdout() interp.Output { return fuzzTestOutput{os.Stdout} }
|
||||
func (ft *fuzzTest) Stderr() io.Writer { return os.Stderr }
|
||||
func (ft *fuzzTest) Stderr() interp.Output { return fuzzTestOutput{os.Stderr} }
|
||||
func (ft *fuzzTest) InterruptChan() chan struct{} { return nil }
|
||||
func (ft *fuzzTest) Environ() []string { return nil }
|
||||
func (ft *fuzzTest) Args() []string {
|
||||
return []string{}
|
||||
}
|
||||
func (ft *fuzzTest) ConfigDir() (string, error) { return "/config", nil }
|
||||
func (ft *fuzzTest) Open(name string) (io.ReadSeeker, error) {
|
||||
return nil, fmt.Errorf("%s: file not found", name)
|
||||
}
|
||||
func (ft *fuzzTest) FS() fs.FS { return fuzzFS{} }
|
||||
func (ft *fuzzTest) History() ([]string, error) { return nil, nil }
|
||||
|
||||
func (ft *fuzzTest) Readline(prompt string, complete func(line string, pos int) (newLine []string, shared int)) (string, error) {
|
||||
return "", io.EOF
|
||||
}
|
||||
@ -67,15 +86,15 @@ func FuzzFormats(f *testing.F) {
|
||||
|
||||
f.Fuzz(func(t *testing.T, b []byte) {
|
||||
fz := &fuzzTest{b: b}
|
||||
q, err := interp.New(fz, all.Registry)
|
||||
q, err := interp.New(fz, registry.Default)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = q.Main(context.Background(), fz.Stdout(), "dev")
|
||||
if err != nil {
|
||||
// TODO: expect error
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = q.Main(context.Background(), fz.Stdout(), "dev")
|
||||
// if err != nil {
|
||||
// // TODO: expect error
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
})
|
||||
}
|
||||
|
@ -142,6 +142,8 @@ func gifDecode(d *decode.D, in interface{}) interface{} {
|
||||
}
|
||||
})
|
||||
})
|
||||
default:
|
||||
d.Fatal("unknown block")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -106,7 +106,7 @@ func gzDecode(d *decode.D, in interface{}) interface{} {
|
||||
deflateR := flate.NewReader(compressedBB)
|
||||
uncompressed := &bytes.Buffer{}
|
||||
if _, err := decode.Copy(d, io.MultiWriter(uncompressed, crc32W), deflateR); err != nil {
|
||||
d.Invalid(err.Error())
|
||||
d.Fatal(err.Error())
|
||||
}
|
||||
uncompressedBB := bitio.NewBufferFromBytes(uncompressed.Bytes(), -1)
|
||||
dv, _, _ := d.FieldTryFormatBitBuf("uncompressed", uncompressedBB, probeFormat, nil)
|
||||
|
@ -21,7 +21,7 @@ func id3v1Decode(d *decode.D, in interface{}) interface{} {
|
||||
d.AssertAtLeastBitsLeft(128 * 8)
|
||||
d.FieldUTF8("magic", 3, d.AssertStr("TAG"))
|
||||
if d.PeekBits(8) == uint64('+') {
|
||||
d.Invalid("looks like id3v11")
|
||||
d.Error("looks like id3v11")
|
||||
}
|
||||
d.FieldUTF8NullTerminatedLen("song_name", 30)
|
||||
d.FieldUTF8NullTerminatedLen("artist", 30)
|
||||
|
@ -382,6 +382,9 @@ func decodeFrame(d *decode.D, version int) uint64 {
|
||||
}
|
||||
|
||||
size = dataSize + headerLen
|
||||
default:
|
||||
// can't know size
|
||||
d.Fatal("unknown version")
|
||||
}
|
||||
|
||||
// note frame function run inside a SubLenFn so they can use BitLefts and
|
||||
@ -523,7 +526,7 @@ func decodeFrame(d *decode.D, version int) uint64 {
|
||||
idNormalized = "COMM"
|
||||
case id == "TXX", id == "TXXX":
|
||||
idNormalized = "TXXX"
|
||||
case id[0] == 'T':
|
||||
case len(id) > 0 && id[0] == 'T':
|
||||
idNormalized = "T000"
|
||||
}
|
||||
|
||||
@ -578,7 +581,7 @@ func id3v2Decode(d *decode.D, in interface{}) interface{} {
|
||||
version := int(d.FieldU8("version"))
|
||||
versionValid := version == 2 || version == 3 || version == 4
|
||||
if !versionValid {
|
||||
d.Invalid(fmt.Sprintf("unsupported version %d", version))
|
||||
d.Fatal(fmt.Sprintf("unsupported version %d", version))
|
||||
}
|
||||
|
||||
d.FieldU8("revision")
|
||||
|
@ -167,7 +167,7 @@ var markers = decode.UToScalar{
|
||||
func jpegDecode(d *decode.D, in interface{}) interface{} {
|
||||
d.AssertLeastBytesLeft(2)
|
||||
if !bytes.Equal(d.PeekBytes(2), []byte{0xff, SOI}) {
|
||||
d.Invalid("no SOI marker")
|
||||
d.Error("no SOI marker")
|
||||
}
|
||||
|
||||
var extendedXMP []byte
|
||||
@ -268,7 +268,7 @@ func jpegDecode(d *decode.D, in interface{}) interface{} {
|
||||
eoiMarkerFound = true
|
||||
default:
|
||||
if !markerFound {
|
||||
d.Invalid(fmt.Sprintf("unknown marker %x", markerCode))
|
||||
d.Error(fmt.Sprintf("unknown marker %x", markerCode))
|
||||
}
|
||||
|
||||
markerLen := d.FieldU16("length")
|
||||
@ -308,7 +308,7 @@ func jpegDecode(d *decode.D, in interface{}) interface{} {
|
||||
// TODO: redo this? multi reader?
|
||||
chunkBytes, err := chunk.Bytes()
|
||||
if err != nil {
|
||||
d.Invalid(fmt.Sprintf("failed to read xmp chunk: %s", err))
|
||||
d.Fatal(fmt.Sprintf("failed to read xmp chunk: %s", err))
|
||||
}
|
||||
|
||||
if extendedXMP == nil {
|
||||
@ -344,7 +344,7 @@ func jpegDecode(d *decode.D, in interface{}) interface{} {
|
||||
})
|
||||
|
||||
if !soiMarkerFound {
|
||||
d.Invalid("no SOI marker found")
|
||||
d.Error("no SOI marker found")
|
||||
}
|
||||
|
||||
if extendedXMP != nil {
|
||||
|
@ -23,13 +23,13 @@ func decodeJSON(d *decode.D, in interface{}) interface{} {
|
||||
jd := stdjson.NewDecoder(bb)
|
||||
var s decode.Scalar
|
||||
if err := jd.Decode(&s.Actual); err != nil {
|
||||
d.Invalid(err.Error())
|
||||
d.Fatal(err.Error())
|
||||
}
|
||||
switch s.Actual.(type) {
|
||||
case map[string]interface{},
|
||||
[]interface{}:
|
||||
default:
|
||||
d.Invalid("root not object or array")
|
||||
d.Fatal("root not object or array")
|
||||
}
|
||||
// TODO: root not array/struct how to add unknown gaps?
|
||||
// TODO: ranges not end up correct
|
||||
|
@ -160,7 +160,7 @@ func decodeMaster(d *decode.D, bitsLimit int64, tag ebml.Tag, dc *decodeContext)
|
||||
if !ok {
|
||||
a, ok = ebml.Global[n]
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("unknown id %d", n))
|
||||
d.Fatal(fmt.Sprintf("unknown id %d", n))
|
||||
}
|
||||
}
|
||||
return decode.Scalar{Actual: n, DisplayFormat: decode.NumberHex, Sym: a.Name, Description: a.Definition}, nil
|
||||
@ -183,7 +183,7 @@ func decodeMaster(d *decode.D, bitsLimit int64, tag ebml.Tag, dc *decodeContext)
|
||||
(a.Type == ebml.Integer ||
|
||||
a.Type == ebml.Uinteger ||
|
||||
a.Type == ebml.Float) {
|
||||
d.Invalid(fmt.Sprintf("invalid tagSize %d for non-master type", tagSize))
|
||||
d.Fatal(fmt.Sprintf("invalid tagSize %d for non-master type", tagSize))
|
||||
}
|
||||
|
||||
switch a.Type {
|
||||
@ -305,7 +305,7 @@ func decodeMaster(d *decode.D, bitsLimit int64, tag ebml.Tag, dc *decodeContext)
|
||||
func matroskaDecode(d *decode.D, in interface{}) interface{} {
|
||||
ebmlHeaderID := uint64(0x1a45dfa3)
|
||||
if d.PeekBits(32) != ebmlHeaderID {
|
||||
d.Invalid("no EBML header found")
|
||||
d.Error("no EBML header found")
|
||||
}
|
||||
dc := &decodeContext{tracks: []*track{}}
|
||||
decodeMaster(d, d.BitsLeft(), ebml_matroska.Root, dc)
|
||||
@ -360,10 +360,10 @@ func matroskaDecode(d *decode.D, in interface{}) interface{} {
|
||||
t.parentD.RangeFn(t.codecPrivatePos, t.codecPrivateTagSize, func(d *decode.D) {
|
||||
d.FieldStruct("value", func(d *decode.D) {
|
||||
d.FieldUTF8("magic", 4, d.AssertStr("fLaC"))
|
||||
_, v := d.FieldFormat("metadatablocks", flacMetadatablocksFormat, nil)
|
||||
flacMetadatablockOut, ok := v.(format.FlacMetadatablocksOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected FlacMetadatablockOut got %#+v", v))
|
||||
v, dv := d.FieldFormat("metadatablocks", flacMetadatablocksFormat, nil)
|
||||
flacMetadatablockOut, ok := dv.(format.FlacMetadatablocksOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected FlacMetadatablockOut got %#+v", v))
|
||||
}
|
||||
if flacMetadatablockOut.HasStreamInfo {
|
||||
t.formatInArg = format.FlacFrameIn{StreamInfo: flacMetadatablockOut.StreamInfo}
|
||||
@ -371,17 +371,17 @@ func matroskaDecode(d *decode.D, in interface{}) interface{} {
|
||||
})
|
||||
})
|
||||
case "V_MPEG4/ISO/AVC":
|
||||
_, v := t.parentD.FieldFormatRange("value", t.codecPrivatePos, t.codecPrivateTagSize, mpegAVCDCRFormat, nil)
|
||||
avcDcrOut, ok := v.(format.AvcDcrOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected AvcDcrOut got %#+v", v))
|
||||
v, dv := t.parentD.FieldFormatRange("value", t.codecPrivatePos, t.codecPrivateTagSize, mpegAVCDCRFormat, nil)
|
||||
avcDcrOut, ok := dv.(format.AvcDcrOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected AvcDcrOut got %#+v", v))
|
||||
}
|
||||
t.formatInArg = format.AvcIn{LengthSize: avcDcrOut.LengthSize} //nolint:gosimple
|
||||
case "V_MPEGH/ISO/HEVC":
|
||||
_, v := t.parentD.FieldFormatRange("value", t.codecPrivatePos, t.codecPrivateTagSize, mpegHEVCDCRFormat, nil)
|
||||
hevcDcrOut, ok := v.(format.HevcDcrOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected HevcDcrOut got %#+v", v))
|
||||
v, dv := t.parentD.FieldFormatRange("value", t.codecPrivatePos, t.codecPrivateTagSize, mpegHEVCDCRFormat, nil)
|
||||
hevcDcrOut, ok := dv.(format.HevcDcrOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected HevcDcrOut got %#+v", v))
|
||||
}
|
||||
t.formatInArg = format.HevcIn{LengthSize: hevcDcrOut.LengthSize} //nolint:gosimple
|
||||
case "V_AV1":
|
||||
|
@ -70,7 +70,7 @@ func mp3Decode(d *decode.D, in interface{}) interface{} {
|
||||
})
|
||||
// TODO: better validate
|
||||
if validFrames == 0 || (validFrames < 2 && decodeFailures > 0) {
|
||||
d.Invalid("no frames found")
|
||||
d.Error("no frames found")
|
||||
}
|
||||
|
||||
d.SeekAbs(lastValidEnd)
|
||||
|
@ -24,7 +24,7 @@ func xingDecode(d *decode.D, in interface{}) interface{} {
|
||||
case "Info":
|
||||
hasLameExtension = true
|
||||
default:
|
||||
d.Invalid("no xing header found")
|
||||
d.Error("no xing header found")
|
||||
}
|
||||
|
||||
qualityPresent := false
|
||||
|
@ -430,20 +430,20 @@ func init() {
|
||||
})
|
||||
},
|
||||
"avcC": func(ctx *decodeContext, d *decode.D) {
|
||||
_, v := d.FieldFormat("descriptor", mpegAVCDCRFormat, nil)
|
||||
avcDcrOut, ok := v.(format.AvcDcrOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected AvcDcrOut got %#+v", v))
|
||||
v, dv := d.FieldFormat("descriptor", mpegAVCDCRFormat, nil)
|
||||
avcDcrOut, ok := dv.(format.AvcDcrOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected AvcDcrOut got %#+v", v))
|
||||
}
|
||||
if ctx.currentTrack != nil {
|
||||
ctx.currentTrack.formatInArg = format.AvcIn{LengthSize: avcDcrOut.LengthSize} //nolint:gosimple
|
||||
}
|
||||
},
|
||||
"hvcC": func(ctx *decodeContext, d *decode.D) {
|
||||
_, v := d.FieldFormat("descriptor", mpegHEVCDCRFrameFormat, nil)
|
||||
hevcDcrOut, ok := v.(format.HevcDcrOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected HevcDcrOut got %#+v", v))
|
||||
v, dv := d.FieldFormat("descriptor", mpegHEVCDCRFrameFormat, nil)
|
||||
hevcDcrOut, ok := dv.(format.HevcDcrOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected HevcDcrOut got %#+v", v))
|
||||
}
|
||||
if ctx.currentTrack != nil {
|
||||
ctx.currentTrack.formatInArg = format.HevcIn{LengthSize: hevcDcrOut.LengthSize} //nolint:gosimple
|
||||
@ -452,10 +452,10 @@ func init() {
|
||||
"dfLa": func(ctx *decodeContext, d *decode.D) {
|
||||
d.FieldU8("version")
|
||||
d.FieldU24("flags")
|
||||
_, v := d.FieldFormat("descriptor", flacMetadatablocksFormat, nil)
|
||||
flacMetadatablockOut, ok := v.(format.FlacMetadatablocksOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected FlacMetadatablockOut got %#+v", v))
|
||||
v, dv := d.FieldFormat("descriptor", flacMetadatablocksFormat, nil)
|
||||
flacMetadatablockOut, ok := dv.(format.FlacMetadatablocksOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected FlacMetadatablockOut got %#+v", v))
|
||||
}
|
||||
if flacMetadatablockOut.HasStreamInfo {
|
||||
if ctx.currentTrack != nil {
|
||||
@ -477,10 +477,10 @@ func init() {
|
||||
"esds": func(ctx *decodeContext, d *decode.D) {
|
||||
d.FieldU32("version")
|
||||
|
||||
_, v := d.FieldFormat("descriptor", mpegESFormat, nil)
|
||||
mpegEsOut, ok := v.(format.MpegEsOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected mpegEsOut got %#+v", v))
|
||||
v, dv := d.FieldFormat("descriptor", mpegESFormat, nil)
|
||||
mpegEsOut, ok := dv.(format.MpegEsOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected mpegEsOut got %#+v", v))
|
||||
}
|
||||
|
||||
if ctx.currentTrack != nil && len(mpegEsOut.DecoderConfigs) > 0 {
|
||||
|
@ -137,13 +137,13 @@ func mp4Decode(d *decode.D, in interface{}) interface{} {
|
||||
d.AssertLeastBytesLeft(16)
|
||||
size := d.U32()
|
||||
if size < 8 {
|
||||
d.Invalid("first box size too small < 8")
|
||||
d.Fatal("first box size too small < 8")
|
||||
}
|
||||
firstType := d.UTF8(4)
|
||||
switch firstType {
|
||||
case "styp", "ftyp", "free", "moov":
|
||||
default:
|
||||
d.Invalid("no styp, ftyp, free or moov box found")
|
||||
d.Error("no styp, ftyp, free or moov box found")
|
||||
}
|
||||
|
||||
d.SeekRel(-8 * 8)
|
||||
|
@ -32,7 +32,7 @@ func adtsDecoder(d *decode.D, in interface{}) interface{} {
|
||||
}
|
||||
|
||||
if validFrames == 0 {
|
||||
d.Invalid("no valid frames")
|
||||
d.Fatal("no valid frames")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -29,6 +29,7 @@ var protectionAbsentNames = decode.BoolToScalar{
|
||||
}
|
||||
|
||||
func adtsFrameDecoder(d *decode.D, in interface{}) interface{} {
|
||||
|
||||
/*
|
||||
adts_frame() {
|
||||
adts_fixed_header();
|
||||
@ -67,6 +68,7 @@ func adtsFrameDecoder(d *decode.D, in interface{}) interface{} {
|
||||
d.FieldU1("mpeg_version", d.MapUToStr(decode.UToStr{0: "MPEG-4", 1: "MPEG2- AAC"}))
|
||||
d.FieldU2("layer", d.AssertU(0))
|
||||
protectionAbsent := d.FieldBool("protection_absent", d.MapBoolToScalar(protectionAbsentNames))
|
||||
|
||||
// TODO: better sym names
|
||||
objectType := d.FieldUFn("profile", func(d *decode.D) uint64 { return d.U2() + 1 }, d.MapUToStr(format.MPEGAudioObjectTypeNames))
|
||||
d.FieldUScalarFn("sampling_frequency", func(d *decode.D) decode.Scalar {
|
||||
@ -86,20 +88,25 @@ func adtsFrameDecoder(d *decode.D, in interface{}) interface{} {
|
||||
d.FieldU1("copyrighted")
|
||||
d.FieldU1("copyright")
|
||||
frameLength := d.FieldU13("frame_length")
|
||||
dataLength := frameLength - 7
|
||||
dataLength := int64(frameLength - 7)
|
||||
if !protectionAbsent {
|
||||
// TODO: multuple RDBs CRCs
|
||||
dataLength -= 2
|
||||
}
|
||||
|
||||
d.FieldU11("buffer_fullness")
|
||||
numberOfRDBs := d.FieldUFn("number_of_rdbs", func(d *decode.D) uint64 { return d.U2() + 1 })
|
||||
if !protectionAbsent {
|
||||
d.FieldU16("crc")
|
||||
}
|
||||
|
||||
if dataLength < 0 {
|
||||
d.Fatal("dataLength < 0")
|
||||
}
|
||||
|
||||
d.FieldArray("raw_data_blocks", func(d *decode.D) {
|
||||
for i := uint64(0); i < numberOfRDBs; i++ {
|
||||
d.FieldFormatLen("raw_data_block", int64(dataLength)*8, aacFrameFormat, format.AACFrameIn{ObjectType: int(objectType)})
|
||||
d.FieldFormatLen("raw_data_block", dataLength*8, aacFrameFormat, format.AACFrameIn{ObjectType: int(objectType)})
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -26,7 +26,7 @@ func annexBDecode(d *decode.D, _ interface{}, format []*decode.Format) interface
|
||||
currentOffset, currentPrefixLen, err := annexBFindStartCode(d)
|
||||
// TODO: really restrict to 0?
|
||||
if err != nil || currentOffset != 0 {
|
||||
d.Invalid("could not find start code (first)")
|
||||
d.Error("could not find start code (first)")
|
||||
}
|
||||
|
||||
for d.NotEnd() {
|
||||
|
@ -26,7 +26,7 @@ func init() {
|
||||
func avcAUDecode(d *decode.D, in interface{}) interface{} {
|
||||
avcIn, ok := in.(format.AvcIn)
|
||||
if !ok {
|
||||
d.Invalid("avcIn required")
|
||||
d.Fatal("avcIn required")
|
||||
}
|
||||
|
||||
for d.NotEnd() {
|
||||
|
@ -24,7 +24,7 @@ func init() {
|
||||
func hevcAUDecode(d *decode.D, in interface{}) interface{} {
|
||||
hevcIn, ok := in.(format.HevcIn)
|
||||
if !ok {
|
||||
d.Invalid("hevcIn required")
|
||||
d.Error("hevcIn required")
|
||||
}
|
||||
|
||||
for d.NotEnd() {
|
||||
|
@ -159,12 +159,13 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
mpegVersion := d.FieldU2("mpeg_version", d.MapUToScalar(mpegVersionNames))
|
||||
mpegVersionNr = mpegVersionN[mpegVersion]
|
||||
if mpegVersionNr == 0 {
|
||||
d.Invalid("Unsupported mpeg version")
|
||||
d.Error("Unsupported mpeg version")
|
||||
}
|
||||
mpegLayer := d.FieldU2("layer", d.MapUToScalar(mpegLayerNames))
|
||||
mpegLayerNr = mpegLayerN[mpegLayer]
|
||||
if mpegLayerNr != 3 {
|
||||
d.Invalid("Not layer 3")
|
||||
d.Error("Not layer 3")
|
||||
mpegLayerNr = 3
|
||||
}
|
||||
// [mpeg layer][mpeg version]
|
||||
var samplesFrameIndex = map[uint][4]uint{
|
||||
@ -209,7 +210,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
default:
|
||||
i := (mpegVersionNr-1)*3 + (mpegLayerNr - 1)
|
||||
if i >= 9 {
|
||||
d.Invalid("Invalid bitrate index")
|
||||
d.Fatal("Invalid bitrate index")
|
||||
}
|
||||
bitRate = uint64(bitRateIndex[uint(u)][(mpegVersionNr-1)*3+(mpegLayerNr-1)]) * 1000
|
||||
return decode.Scalar{Actual: u, Sym: bitRate}
|
||||
@ -341,7 +342,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
|
||||
}
|
||||
|
||||
if sampleRate == 0 {
|
||||
d.Invalid("zero sample rate")
|
||||
d.Error("zero sample rate")
|
||||
}
|
||||
|
||||
calcFrameBytes := int64(144*bitRate/sampleRate + paddingBytes)
|
||||
|
@ -242,9 +242,9 @@ func odDecodeTag(d *decode.D, edc *esDecodeContext, expectedTagID int, fn func(d
|
||||
switch format.MpegObjectTypeStreamType[objectType] {
|
||||
case format.MPEGStreamTypeAudio:
|
||||
fieldODDecodeTag(d, edc, "decoder_specific_info", -1, func(d *decode.D) {
|
||||
_, v := d.FieldFormat("audio_specific_config", mpegASCFormat, nil)
|
||||
mpegASCout, ok := v.(format.MPEGASCOut)
|
||||
if !ok {
|
||||
v, dv := d.FieldFormat("audio_specific_config", mpegASCFormat, nil)
|
||||
mpegASCout, ok := dv.(format.MPEGASCOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected MPEGASCOut got %#+v", v))
|
||||
}
|
||||
if edc.currentDecoderConfig != nil {
|
||||
|
@ -40,7 +40,7 @@ func pesDecode(d *decode.D, in interface{}) interface{} {
|
||||
|
||||
prefix := d.PeekBits(24)
|
||||
if prefix != 0b0000_0000_0000_0000_0000_0001 {
|
||||
d.Invalid("no pes prefix found")
|
||||
d.Error("no pes prefix found")
|
||||
}
|
||||
|
||||
i := 0
|
||||
|
@ -147,10 +147,10 @@ func decodeOgg(d *decode.D, in interface{}) interface{} {
|
||||
d.FieldU8("minor")
|
||||
d.FieldU16("header_packets")
|
||||
d.FieldUTF8("flac_signature", 4)
|
||||
_, flacMetadatablockOutAny := d.FieldFormat("metadatablock", flacMetadatablockFormat, nil)
|
||||
flacMetadatablockOut, ok := flacMetadatablockOutAny.(format.FlacMetadatablockOut)
|
||||
if !ok {
|
||||
d.Invalid(fmt.Sprintf("expected FlacMetadatablockOut, got %#+v", flacMetadatablockOut))
|
||||
v, dv := d.FieldFormat("metadatablock", flacMetadatablockFormat, nil)
|
||||
flacMetadatablockOut, ok := dv.(format.FlacMetadatablockOut)
|
||||
if v != nil && !ok {
|
||||
panic(fmt.Sprintf("expected FlacMetadatablockOut, got %#+v", flacMetadatablockOut))
|
||||
}
|
||||
s.flacStreamInfo = flacMetadatablockOut.StreamInfo
|
||||
})
|
||||
@ -179,7 +179,7 @@ func decodeOgg(d *decode.D, in interface{}) interface{} {
|
||||
})
|
||||
|
||||
if validPages == 0 {
|
||||
d.Invalid("no pages found")
|
||||
d.Fatal("no pages found")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -43,7 +43,7 @@ func tarDecode(d *decode.D, in interface{}) interface{} {
|
||||
var err error
|
||||
n, err = strconv.ParseUint(ts, 8, 64)
|
||||
if err != nil {
|
||||
d.Invalid(fmt.Sprintf("failed to parse %s number %s: %s", name, ts, err))
|
||||
d.Error(fmt.Sprintf("failed to parse %s number %s: %s", name, ts, err))
|
||||
}
|
||||
}
|
||||
return decode.Scalar{Actual: a, Sym: n}, nil
|
||||
@ -76,7 +76,7 @@ func tarDecode(d *decode.D, in interface{}) interface{} {
|
||||
fieldStr(d, "linkname", 100)
|
||||
magic := fieldStr(d, "magic", 6)
|
||||
if magic != "ustar" {
|
||||
d.Invalid(fmt.Sprintf("invalid magic %s", magic))
|
||||
d.Error(fmt.Sprintf("invalid magic %s", magic))
|
||||
}
|
||||
fieldNumStr(d, "version", 2)
|
||||
fieldStr(d, "uname", 32)
|
||||
@ -104,7 +104,7 @@ func tarDecode(d *decode.D, in interface{}) interface{} {
|
||||
d.FieldRawLen("end_marker", 512*2*8)
|
||||
|
||||
if !foundEndMarker {
|
||||
d.Invalid("no files found")
|
||||
d.Error("no files found")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -188,7 +188,7 @@ func decodeIfd(d *decode.D, s *strips, tagNames map[uint64]string) int64 {
|
||||
case SRATIONAL:
|
||||
fieldSRational(d, "value")
|
||||
default:
|
||||
d.Invalid("unknown type")
|
||||
d.Error("unknown type")
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -214,7 +214,7 @@ func tiffDecode(d *decode.D, in interface{}) interface{} {
|
||||
case bigEndian:
|
||||
d.Endian = decode.BigEndian
|
||||
default:
|
||||
d.Invalid("unknown endian")
|
||||
d.Fatal("unknown endian")
|
||||
}
|
||||
|
||||
d.SeekRel(-4 * 8)
|
||||
|
@ -59,7 +59,7 @@ func vorbisDecode(d *decode.D, in interface{}) interface{} {
|
||||
d.FieldUTF8("magic", 6, d.AssertStr("vorbis"))
|
||||
case packetTypeAudio:
|
||||
default:
|
||||
d.Invalid(fmt.Sprintf("unknown packet type %d", packetType))
|
||||
d.Fatal(fmt.Sprintf("unknown packet type %d", packetType))
|
||||
}
|
||||
|
||||
switch packetType {
|
||||
|
@ -160,7 +160,7 @@ func decodeChunk(d *decode.D, expectedChunkID string, stringData bool) int64 { /
|
||||
return strings.TrimSpace(d.UTF8(4))
|
||||
})
|
||||
if expectedChunkID != "" && trimChunkID != expectedChunkID {
|
||||
d.Invalid(fmt.Sprintf("expected chunk id %q found %q", expectedChunkID, trimChunkID))
|
||||
d.Error(fmt.Sprintf("expected chunk id %q found %q", expectedChunkID, trimChunkID))
|
||||
}
|
||||
const restOfFileLen = 0xffffffff
|
||||
chunkLen := int64(d.FieldUScalarFn("size", func(d *decode.D) decode.Scalar {
|
||||
|
@ -64,7 +64,7 @@ func webpDecode(d *decode.D, in interface{}) interface{} {
|
||||
})
|
||||
})
|
||||
default:
|
||||
d.Invalid("could not find VP8 or VP8L chunk")
|
||||
d.Fatal("could not find VP8 or VP8L chunk")
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -2,6 +2,7 @@ package recoverfn
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
@ -82,10 +83,19 @@ func (r Raw) Frames() []runtime.Frame {
|
||||
}
|
||||
|
||||
func (r Raw) RePanic() {
|
||||
fmt.Fprintf(os.Stderr, "repanic: %v\n", r.RecoverV)
|
||||
var o io.Writer
|
||||
o = os.Stderr
|
||||
if p := os.Getenv("REPANIC_LOG"); p != "" {
|
||||
if f, err := os.Create(p); err == nil {
|
||||
o = f
|
||||
defer f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(o, "repanic: %v\n", r.RecoverV)
|
||||
for _, f := range r.frames(0, 0, 0) {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", f.Function)
|
||||
fmt.Fprintf(os.Stderr, "\t%s:%d\n", f.File, f.Line)
|
||||
fmt.Fprintf(o, "%s\n", f.Function)
|
||||
fmt.Fprintf(o, "\t%s:%d\n", f.File, f.Line)
|
||||
}
|
||||
panic(r.RecoverV)
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func decode(ctx context.Context, bb *bitio.Buffer, formats []*Format, opts Optio
|
||||
for _, f := range formats {
|
||||
cbb, err := bb.BitBufRange(decodeRange.Start, decodeRange.Len)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, IOError{Err: err, Op: "BitBufRange", ReadSize: decodeRange.Len, Pos: decodeRange.Start}
|
||||
}
|
||||
|
||||
d := newDecoder(ctx, f, cbb, opts)
|
||||
@ -215,13 +215,18 @@ func (d *D) FillGaps(r ranges.Range, namePrefix string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid stops decode with a reason
|
||||
func (d *D) Invalid(reason string) {
|
||||
// Error stops decode with a reason unless forced
|
||||
func (d *D) Error(reason string) {
|
||||
if !d.Options.Force {
|
||||
panic(ValidateError{Reason: reason, Pos: d.Pos()})
|
||||
}
|
||||
}
|
||||
|
||||
// Fatal stops decode with a reason regardless of forced
|
||||
func (d *D) Fatal(reason string) {
|
||||
panic(ValidateError{Reason: reason, Pos: d.Pos()})
|
||||
}
|
||||
|
||||
func (d *D) IOPanic(err error) {
|
||||
panic(IOError{Err: err, Pos: d.Pos()})
|
||||
}
|
||||
@ -444,7 +449,7 @@ func (d *D) AddChild(v *Value) {
|
||||
if !fv.IsArray {
|
||||
for _, ff := range *fv.Children {
|
||||
if ff.Name == v.Name {
|
||||
d.Invalid(fmt.Sprintf("%q already exist in struct %s", v.Name, d.Value.Name))
|
||||
d.Fatal(fmt.Sprintf("%q already exist in struct %s", v.Name, d.Value.Name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user