1
1
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:
Mattias Wadman 2021-11-16 17:11:26 +01:00
parent f9f866000e
commit b66ed32614
35 changed files with 164 additions and 110 deletions

View File

@ -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/

View File

@ -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)

View File

@ -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)
}

View File

@ -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?

View File

@ -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])))
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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)
// }
})
}

View File

@ -142,6 +142,8 @@ func gifDecode(d *decode.D, in interface{}) interface{} {
}
})
})
default:
d.Fatal("unknown block")
}
}
})

View File

@ -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)

View File

@ -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)

View File

@ -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")

View File

@ -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 {

View File

@ -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

View File

@ -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":

View File

@ -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)

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -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

View File

@ -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)})
}
})

View File

@ -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() {

View File

@ -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() {

View File

@ -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() {

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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 {

View File

@ -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")
}
})

View File

@ -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)
}

View File

@ -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))
}
}
}