コード例 #1
0
ファイル: main.go プロジェクト: sjn1978/go-fuzz
func Fuzz(data []byte) int {
	sdata := string(data)
	mt, params, err := mime.ParseMediaType(sdata)
	if err != nil {
		return 0
	}
	sdata1 := mime.FormatMediaType(mt, params)
	mt1, params1, err := mime.ParseMediaType(sdata1)
	if err != nil {
		if err.Error() == "mime: no media type" {
			// https://github.com/golang/go/issues/11289
			return 0
		}
		if err.Error() == "mime: invalid media parameter" {
			// https://github.com/golang/go/issues/11290
			return 0
		}
		fmt.Printf("%q(%q, %+v) -> %q\n", sdata, mt, params, sdata1)
		panic(err)
	}
	if !fuzz.DeepEqual(mt, mt1) {
		fmt.Printf("%q -> %q\n", mt, mt1)
		panic("mediatype changed")
	}
	if !fuzz.DeepEqual(params, params1) {
		fmt.Printf("%+v -> %+v\n", params, params1)
		panic("params changed")
	}
	return 1
}
コード例 #2
0
ファイル: main.go プロジェクト: sjn1978/go-fuzz
func FuzzPKCS(data []byte) int {
	score := 0
	if k, err := x509.ParsePKCS1PrivateKey(data); err == nil {
		score = 1
		data1 := x509.MarshalPKCS1PrivateKey(k)
		k1, err := x509.ParsePKCS1PrivateKey(data1)
		if err != nil {
			panic(err)
		}
		if !fuzz.DeepEqual(k, k1) {
			panic("keys are not equal")
		}
	}
	if k0, err := x509.ParsePKCS8PrivateKey(data); err == nil {
		score = 1
		if k, ok := k0.(*rsa.PrivateKey); ok {
			data1 := x509.MarshalPKCS1PrivateKey(k)
			k1, err := x509.ParsePKCS1PrivateKey(data1)
			if err != nil {
				panic(err)
			}
			if !fuzz.DeepEqual(k, k1) {
				panic("keys are not equal")
			}
		}
	}
	return score
}
コード例 #3
0
ファイル: gif.go プロジェクト: rlmcpherson/go-fuzz
func FuzzAll(data []byte) int {
	cfg, err := gif.DecodeConfig(bytes.NewReader(data))
	if err != nil {
		return 0
	}
	if cfg.Width*cfg.Height > 1e6 {
		return 0
	}
	img, err := gif.DecodeAll(bytes.NewReader(data))
	if err != nil {
		return 0
	}
	w := new(bytes.Buffer)
	err = gif.EncodeAll(w, img)
	if err != nil {
		panic(err)
	}
	img1, err := gif.DecodeAll(w)
	if err != nil {
		panic(err)
	}
	if img.LoopCount == 0 && img1.LoopCount == -1 {
		// https://github.com/golang/go/issues/11287
		img1.LoopCount = 0
	}
	// https://github.com/golang/go/issues/11288
	img1.Disposal = img.Disposal
	if !fuzz.DeepEqual(img, img1) {
		fmt.Printf("gif0: %#v\n", img)
		fmt.Printf("gif1: %#v\n", img1)
		panic("gif changed")
	}
	return 1
}
コード例 #4
0
ファイル: asn1.go プロジェクト: rlmcpherson/go-fuzz
func Fuzz(data []byte) int {
	ctors := []func() interface{}{
		func() interface{} { return new(int) },
		func() interface{} { return new(int32) },
		func() interface{} { return new(int64) },
		func() interface{} { return new(*big.Int) },
		func() interface{} { return new(asn1.BitString) },
		func() interface{} { return new([]byte) },
		func() interface{} { return new(asn1.ObjectIdentifier) },
		func() interface{} { return new(asn1.Enumerated) },
		func() interface{} { return new(interface{}) },
		func() interface{} { return new(string) },
		func() interface{} { return new(time.Time) },
		func() interface{} { return new([]interface{}) },
		func() interface{} { return new(X) },
	}
	score := 0
	for _, ctor := range ctors {
		v := ctor()
		_, err := asn1.Unmarshal(data, v)
		if err != nil {
			continue
		}
		score = 1
		x := reflect.ValueOf(v).Elem().Interface()
		if x == nil {
			continue // https://github.com/golang/go/issues/11127
		}
		data1, err := asn1.Marshal(x)
		if err != nil {
			panic(err)
		}
		v1 := ctor()
		rest, err := asn1.Unmarshal(data1, v1)
		if err != nil {
			panic(err)
		}
		if len(rest) != 0 {
			fmt.Printf("data: %q\n", rest)
			panic("leftover data")
		}
		if !fuzz.DeepEqual(v, v1) {
			fmt.Printf("v0: %#v\n", reflect.ValueOf(v).Elem().Interface())
			fmt.Printf("v1: %#v\n", reflect.ValueOf(v1).Elem().Interface())
			panic(fmt.Sprintf("not equal %T", x))
		}
	}
	return score
}
コード例 #5
0
ファイル: main.go プロジェクト: sjn1978/go-fuzz
func Fuzz(data []byte) int {
	score := 0

	r := csv.NewReader(bytes.NewReader(data))
	r.Comment = '#'
	r.LazyQuotes = true
	r.TrimLeadingSpace = true
	rec, err := r.ReadAll()
	if err != nil {
		if rec != nil {
			panic("rec is not nil on error")
		}
	} else {
		score = 1
	}

	r = csv.NewReader(bytes.NewReader(data))
	rec, err = r.ReadAll()
	if err != nil {
		if rec != nil {
			panic("rec is not nil on error")
		}
	} else {
		score = 1
		var rec0 [][]string
		for _, r := range rec {
			if len(r) > 0 {
				rec0 = append(rec0)
			}
		}

		buf := new(bytes.Buffer)
		w := csv.NewWriter(buf)
		w.WriteAll(rec0)
		r := csv.NewReader(buf)
		rec1, err := r.ReadAll()
		if err != nil {
			panic(err)
		}
		if !fuzz.DeepEqual(rec0, rec1) {
			fmt.Printf("rec0: %+v\n", rec0)
			fmt.Printf("rec1: %+v\n", rec1)
			panic("records differ")
		}
	}

	return score
}
コード例 #6
0
ファイル: xml.go プロジェクト: rlmcpherson/go-fuzz
func Fuzz(data []byte) int {
	score := 0
	for _, ctor := range []func() interface{}{
		func() interface{} { return nil },
		func() interface{} { return new(string) },
		func() interface{} { return new([]string) },
		func() interface{} { return new(X) },
		func() interface{} { return new([]X) },
	} {
		v0 := ctor()
		valid := false
		dec := xml.NewDecoder(bytes.NewReader(data))
		if dec.Decode(v0) == nil {
			valid = true
		}
		v := ctor()
		dec1 := xml.NewDecoder(bytes.NewReader(data))
		dec1.Strict = false
		dec1.AutoClose = xml.HTMLAutoClose
		dec1.Entity = xml.HTMLEntity
		if dec1.Decode(v) != nil {
			if valid {
				panic("non-strict mode is weaker than strict")
			}
			continue
		}
		score = 1
		data1, err := xml.Marshal(v)
		if err != nil {
			panic(err)
		}

		v1 := ctor()
		dec2 := xml.NewDecoder(bytes.NewReader(data1))
		dec2.Strict = false
		dec2.AutoClose = xml.HTMLAutoClose
		dec2.Entity = xml.HTMLEntity
		if err := dec2.Decode(v1); err != nil {
			panic(err)
		}
		if !fuzz.DeepEqual(v, v1) {
			fmt.Printf("v0: %#v\n", reflect.ValueOf(v).Elem().Interface())
			fmt.Printf("v1: %#v\n", reflect.ValueOf(v1).Elem().Interface())
			panic(fmt.Sprintf("not equal %T", v))
		}
	}
	return score
}
コード例 #7
0
ファイル: main.go プロジェクト: sjn1978/go-fuzz
func FuzzEC(data []byte) int {
	k, err := x509.ParseECPrivateKey(data)
	if err != nil {
		return 0
	}
	data1, err := x509.MarshalECPrivateKey(k)
	if err != nil {
		panic(err)
	}
	k1, err := x509.ParseECPrivateKey(data1)
	if err != nil {
		panic(err)
	}
	if !fuzz.DeepEqual(k, k1) {
		panic("keys are not equal")
	}
	return 1
}
コード例 #8
0
ファイル: json.go プロジェクト: sjn1978/go-fuzz
func Fuzz(data []byte) int {
	score := 0
	for _, ctor := range []func() interface{}{
		func() interface{} { return nil },
		func() interface{} { return new([]interface{}) },
		func() interface{} { m := map[string]string{}; return &m },
		func() interface{} { m := map[string]interface{}{}; return &m },
		func() interface{} { return new(S) },
	} {
		v := ctor()
		if json.Unmarshal(data, v) != nil {
			continue
		}
		score = 1
		if s, ok := v.(*S); ok {
			if len(s.P) == 0 {
				s.P = []byte(`""`)
			}
		}
		data1, err := json.Marshal(v)
		if err != nil {
			panic(err)
		}
		v1 := ctor()
		if json.Unmarshal(data1, v1) != nil {
			continue
		}
		if s, ok := v.(*S); ok {
			// Some additional escaping happens with P.
			s.P = nil
			v1.(*S).P = nil
		}
		if !fuzz.DeepEqual(v, v1) {
			fmt.Printf("v0: %#v\n", v)
			fmt.Printf("v1: %#v\n", v1)
			panic("not equal")
		}
	}
	return score
}
コード例 #9
0
ファイル: main.go プロジェクト: sjn1978/go-fuzz
func FuzzPKIX(data []byte) int {
	key, err := x509.ParsePKIXPublicKey(data)
	if err != nil {
		return 0
	}
	if _, ok := key.(*dsa.PublicKey); ok {
		// Marshalling of DSA keys is not implemented.
		return 1
	}
	data1, err := x509.MarshalPKIXPublicKey(key)
	if err != nil {
		panic(err)
	}
	key1, err := x509.ParsePKIXPublicKey(data1)
	if err != nil {
		panic(err)
	}
	if !fuzz.DeepEqual(key, key1) {
		panic("keys are not equal")
	}
	return 1
}
コード例 #10
0
ファイル: main.go プロジェクト: rlmcpherson/go-fuzz
func Fuzz(data []byte) int {
	score := 0
	for _, ctor := range []func() interface{}{
		func() interface{} { return make(bson.M) },
		func() interface{} { return new(bson.D) },
		func() interface{} { return new(S) },
		func() interface{} { return new(O) },
	} {
		v := ctor()
		if bson.Unmarshal(data, v) != nil {
			continue
		}
		score = 1
		data1, err := bson.Marshal(v)
		if err != nil {
			if strings.HasPrefix(err.Error(), "ObjectIDs must be exactly 12 bytes long") {
				continue
			}
			panic(err)
		}
		v1 := ctor()
		if err := bson.Unmarshal(data1, v1); err != nil {
			// https://github.com/go-mgo/mgo/issues/117
			if err.Error() == "Document is corrupted" {
				continue
			}
			panic(err)
		}
		if !fuzz.DeepEqual(v, v1) {
			fmt.Printf("v0: %#v\n", v)
			fmt.Printf("v1: %#v\n", v1)
			panic("non-idempotent unmarshalling")
		}
	}
	return score
}
コード例 #11
0
ファイル: main.go プロジェクト: sjn1978/go-fuzz
func Fuzz(data []byte) int {
	var t time.Time
	if err := t.UnmarshalText(data); err != nil {
		return 0
	}
	data1, err := t.MarshalText()
	if err != nil {
		panic(err)
	}
	var t1 time.Time
	if err := t1.UnmarshalText(data1); err != nil {
		panic(err)
	}
	if !fuzz.DeepEqual(t, t1) {
		fmt.Printf("t0: %#v\n", t)
		fmt.Printf("t1: %#v\n", t1)
		panic("bad MarshalText")
	}

	data2, err := t.GobEncode()
	if err != nil {
		panic(err)
	}
	var t2 time.Time
	if err := t2.GobDecode(data2); err != nil {
		panic(err)
	}
	if !fuzz.DeepEqual(t, t2) {
		fmt.Printf("t0: %#v\n", t)
		fmt.Printf("t2: %#v\n", t2)
		panic("bad GobEncode")
	}

	data3, err := t.MarshalBinary()
	if err != nil {
		panic(err)
	}
	var t3 time.Time
	if err := t3.UnmarshalBinary(data3); err != nil {
		panic(err)
	}
	if !fuzz.DeepEqual(t, t3) {
		fmt.Printf("t0: %#v\n", t)
		fmt.Printf("t3: %#v\n", t3)
		panic("bad MarshalBinary")
	}

	data4, err := t.MarshalJSON()
	if err != nil {
		panic(err)
	}
	var t4 time.Time
	if err := t4.UnmarshalJSON(data4); err != nil {
		panic(err)
	}
	if !fuzz.DeepEqual(t, t4) {
		fmt.Printf("t0: %#v\n", t)
		fmt.Printf("t4: %#v\n", t4)
		panic("bad MarshalJSON")
	}

	data5, err := t.MarshalText()
	if err != nil {
		panic(err)
	}
	var t5 time.Time
	if err := t5.UnmarshalText(data5); err != nil {
		panic(err)
	}
	if !fuzz.DeepEqual(t, t5) {
		fmt.Printf("t0: %#v\n", t)
		fmt.Printf("t5: %#v\n", t5)
		panic("bad MarshalText")
	}

	data6 := t.Format(time.RFC3339Nano)
	t6, err := time.Parse(time.RFC3339Nano, data6)
	if err != nil {
		panic(err)
	}
	if !fuzz.DeepEqual(t, t6) {
		fmt.Printf("t0: %#v\n", t)
		fmt.Printf("t6: %#v\n", t6)
		panic("bad Format")
	}
	return 1
}
コード例 #12
0
ファイル: main.go プロジェクト: roger2000hk/go-fuzz
func Fuzz(data []byte) int {
	stmt, err := sqlparser.Parse(string(data))
	if err != nil {
		if stmt != nil {
			panic("stmt is not nil on error")
		}
		return 0
	}
	if true {
		data1 := sqlparser.String(stmt)
		stmt1, err := sqlparser.Parse(data1)
		if err != nil {
			fmt.Printf("data0: %q\n", data)
			fmt.Printf("data1: %q\n", data1)
			panic(err)
		}
		if !fuzz.DeepEqual(stmt, stmt1) {
			fmt.Printf("data0: %q\n", data)
			fmt.Printf("data1: %q\n", data1)
			panic("not equal")
		}
	} else {
		sqlparser.String(stmt)
	}
	if sel, ok := stmt.(*sqlparser.Select); ok {
		var nodes []sqlparser.SQLNode
		for _, x := range sel.From {
			nodes = append(nodes, x)
		}
		for _, x := range sel.From {
			nodes = append(nodes, x)
		}
		for _, x := range sel.SelectExprs {
			nodes = append(nodes, x)
		}
		for _, x := range sel.GroupBy {
			nodes = append(nodes, x)
		}
		for _, x := range sel.OrderBy {
			nodes = append(nodes, x)
		}
		nodes = append(nodes, sel.Where)
		nodes = append(nodes, sel.Having)
		nodes = append(nodes, sel.Limit)
		for _, n := range nodes {
			if n == nil {
				continue
			}
			if x, ok := n.(sqlparser.SimpleTableExpr); ok {
				sqlparser.GetTableName(x)
			}
			if x, ok := n.(sqlparser.Expr); ok {
				sqlparser.GetColName(x)
			}
			if x, ok := n.(sqlparser.ValExpr); ok {
				sqlparser.IsValue(x)
			}
			if x, ok := n.(sqlparser.ValExpr); ok {
				sqlparser.IsColName(x)
			}
			if x, ok := n.(sqlparser.ValExpr); ok {
				sqlparser.IsSimpleTuple(x)
			}
			if x, ok := n.(sqlparser.ValExpr); ok {
				sqlparser.AsInterface(x)
			}
			if x, ok := n.(sqlparser.BoolExpr); ok {
				sqlparser.HasINClause([]sqlparser.BoolExpr{x})
			}
		}
	}
	buf := sqlparser.NewTrackedBuffer(nil)
	stmt.Format(buf)
	pq := buf.ParsedQuery()
	vars := map[string]interface{}{
		"A": 42,
		"B": 123123123,
		"C": "",
		"D": "a",
		"E": "foobar",
		"F": 1.1,
	}
	pq.GenerateQuery(vars)
	return 1
}
コード例 #13
0
ファイル: main.go プロジェクト: rlmcpherson/go-fuzz
func Fuzz(data []byte) int {
	// Read in the archive.
	z, err := zip.NewReader(bytes.NewReader(data), int64(len(data)))
	if err != nil {
		if z != nil {
			panic("non nil z")
		}
		return 0
	}
	var headers []*zip.FileHeader
	var contents [][]byte
	for _, f := range z.File {
		r, err := f.Open()
		if err != nil {
			continue
		}
		if f.UncompressedSize64 < 1e6 {
			c, err := ioutil.ReadAll(r)
			if err != nil {
				continue
			}
			if uint64(len(c)) != f.UncompressedSize64 {
				println("bad size:", len(c), f.UncompressedSize64)
				panic("bad size")
			}
			hdr := f.FileHeader
			headers = append(headers, &hdr)
			contents = append(contents, c)
		}
		r.Close()
	}
	if len(headers) == 0 {
		return 1
	}

	// Write a new archive with the same files.
	buf := new(bytes.Buffer)
	w := zip.NewWriter(buf)
	for i, h := range headers {
		w1, err := w.CreateHeader(h)
		if err != nil {
			panic(err)
		}
		n, err := w1.Write(contents[i])
		if err != nil {
			panic(err)
		}
		if n != len(contents[i]) {
			panic("short write")
		}
	}
	err = w.Close()
	if err != nil {
		panic(err)
	}

	// Read in the new archive.
	z1, err := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(len(buf.Bytes())))
	if err != nil {
		panic(err)
	}
	var headers1 []*zip.FileHeader
	var contents1 [][]byte
	for _, f := range z1.File {
		r, err := f.Open()
		if err != nil {
			panic(err)
		}
		if f.UncompressedSize64 >= 1e6 {
			panic("corrupted length")
		}
		c, err := ioutil.ReadAll(r)
		if err != nil {
			panic(err)
		}
		if uint64(len(c)) != f.UncompressedSize64 {
			println("bad size:", len(c), f.UncompressedSize64)
			panic("bad size")
		}
		hdr := f.FileHeader
		headers1 = append(headers1, &hdr)
		contents1 = append(contents1, c)
		r.Close()
	}

	// Compare that we have the same data after compress/decompress.
	for i, h := range headers {
		// These fields are set by archive/zip package.
		h.Flags |= 0x8
		h.CreatorVersion = headers1[i].CreatorVersion
		h.ReaderVersion = headers1[i].ReaderVersion
		// These are not set correctly initially.
		//h.CompressedSize = headers1[i].CompressedSize
		//h.CompressedSize64 = headers1[i].CompressedSize64
		if !fuzz.DeepEqual(h, headers1[i]) {
			fmt.Printf("hdr0: %#v\n", h)
			fmt.Printf("hdr1: %#v\n", headers1[i])
			panic("corrupted header")
		}
		if !fuzz.DeepEqual(contents[i], contents1[i]) {
			panic("corrupted data")
		}
	}
	return 1
}
コード例 #14
0
ファイル: main.go プロジェクト: sjn1978/go-fuzz
func Fuzz(data []byte) int {
	score := 0
	for _, ctor := range []func() interface{}{
		func() interface{} { return nil },
		func() interface{} { return new(int) },
		func() interface{} { return new(string) },
		func() interface{} { return new(float64) },
		func() interface{} { return new([]byte) },
		func() interface{} { return new(interface{}) },
		func() interface{} { return new(complex128) },
		func() interface{} { m := make(map[int]int); return &m },
		func() interface{} { m := make(map[string]interface{}); return &m },
		func() interface{} { return new(X) },
	} {
		v := ctor()
		dec := gob.NewDecoder(bytes.NewReader(data))
		if dec.Decode(v) != nil {
			continue
		}
		dec.Decode(ctor())
		score = 1
		if ctor() == nil {
			continue
		}
		b1 := new(bytes.Buffer)
		if err := gob.NewEncoder(b1).Encode(v); err != nil {
			panic(err)
		}
		v1 := reflect.ValueOf(ctor())
		err := gob.NewDecoder(bytes.NewReader(data)).DecodeValue(v1)
		if err != nil {
			panic(err)
		}
		if !fuzz.DeepEqual(v, v1.Interface()) {
			fmt.Printf("v0: %#v\n", reflect.ValueOf(v).Elem().Interface())
			fmt.Printf("v1: %#v\n", v1.Elem().Interface())
			panic(fmt.Sprintf("values not equal %T", v))
		}
		b2 := new(bytes.Buffer)
		err = gob.NewEncoder(b2).EncodeValue(v1)
		if err != nil {
			panic(err)
		}
		v2 := ctor()
		dec1 := gob.NewDecoder(b1)
		if err := dec1.Decode(v2); err != nil {
			panic(err)
		}
		if err := dec1.Decode(ctor()); err != io.EOF {
			panic(err)
		}
		if vv, ok := v.(*X); ok {
			fix(vv)
		}
		if !fuzz.DeepEqual(v, v2) {
			fmt.Printf("v0: %#v\n", reflect.ValueOf(v).Elem().Interface())
			fmt.Printf("v2: %#v\n", reflect.ValueOf(v2).Elem().Interface())
			panic(fmt.Sprintf("values not equal 2 %T", v))
		}
	}
	return score
}
コード例 #15
0
ファイル: main.go プロジェクト: sjn1978/go-fuzz
func Fuzz(data []byte) int {
	t := tar.NewReader(bytes.NewReader(data))
	var headers []*tar.Header
	var contents [][]byte
	for {
		hdr, err := t.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return 0
		}
		if len(hdr.Name) > 1e6 ||
			len(hdr.Linkname) > 1e6 ||
			len(hdr.Uname) > 1e6 ||
			len(hdr.Gname) > 1e6 ||
			len(hdr.Xattrs) > 1e6 {
			panic("huge header data")
		}
		if hdr.Size > 1e6 {
			panic("huge claimed file size")
		}
		fdata, err := ioutil.ReadAll(t)
		if err != nil {
			return 0
		}
		if int64(len(fdata)) > hdr.Size {
			panic("long read")
		}
		if int64(len(fdata)) < hdr.Size {
			panic("short read")
		}
		hdr1 := *hdr // make a copy to be safe
		headers = append(headers, &hdr1)
		contents = append(contents, fdata)
	}
	buf := new(bytes.Buffer)
	w := tar.NewWriter(buf)
	for i, hdr := range headers {
		err := w.WriteHeader(hdr)
		if err != nil {
			panic(err)
		}
		n, err := w.Write(contents[i])
		if err != nil {
			panic(err)
		}
		if n != len(contents[i]) {
			panic("short write")
		}
	}
	err := w.Close()
	if err != nil {
		panic(err)
	}
	t1 := tar.NewReader(buf)
	for i := 0; ; i++ {
		hdr, err := t1.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			panic(err)
		}
		fdata, err := ioutil.ReadAll(t1)
		if err != nil {
			panic(err)
		}
		if !fuzz.DeepEqual(hdr, headers[i]) {
			panic("headers diffs")
		}
		if !bytes.Equal(fdata, contents[i]) {
			panic("data diffs")
		}
	}
	return 1
}
コード例 #16
0
ファイル: main.go プロジェクト: rlmcpherson/go-fuzz
func Fuzz(data []byte) int {
	const boundary = "dfhjksd23f43242f43fv4b4g2g2g23vf2"
	{
		r := multipart.NewReader(bytes.NewReader(data), boundary)
		f, err := r.ReadForm(1 << 20)
		if err == nil {
			f.RemoveAll()
		}
	}

	r := multipart.NewReader(bytes.NewReader(data), boundary)
	var parts []Part
	for {
		p, err := r.NextPart()
		if err == io.EOF {
			break
		}
		if err != nil {
			return 0
		}
		p.FileName()
		p.FormName()
		pdata, err := ioutil.ReadAll(p)
		if err != nil {
			return 0
		}
		p.Close()
		// The parser is loose here.
		// If data contains \n followed by boundary (but without \r),
		// it parses it as part body. However, when it serializes it back,
		// it writes \r\n followed by boundary, which becomes new part separator.
		if bytes.Contains(pdata, []byte(boundary)) {
			continue
		}
		parts = append(parts, Part{p.Header, pdata})
	}
	if len(parts) == 0 {
		return 0
	}

	buf := new(bytes.Buffer)
	w := multipart.NewWriter(buf)
	w.SetBoundary(boundary)
	for _, p := range parts {
		pw, err := w.CreatePart(p.hdr)
		if err != nil {
			panic(err)
		}
		n, err := pw.Write(p.data)
		if err != nil {
			panic(err)
		}
		if n != len(p.data) {
			panic("partial write")
		}
	}
	w.Close()

	data1 := buf.Bytes()
	r1 := multipart.NewReader(buf, boundary)
	var parts1 []Part
	for {
		p, err := r1.NextPart()
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Printf("parts0: %+v\n", parts)
			fmt.Printf("data0: %q\n", data)
			fmt.Printf("data1: %q\n", data1)
			panic(err)
		}
		p.FileName()
		p.FormName()
		pdata, err := ioutil.ReadAll(p)
		if err != nil {
			panic(err)
		}
		p.Close()
		parts1 = append(parts1, Part{p.Header, pdata})
	}

	if !fuzz.DeepEqual(parts, parts1) {
		fmt.Printf("parts0: %+v\n", parts)
		fmt.Printf("parts1: %+v\n", parts1)
		fmt.Printf("data0: %q\n", data)
		fmt.Printf("data1: %q\n", data1)
		panic("data has changed")
	}
	return 1
}
コード例 #17
0
ファイル: httpreq.go プロジェクト: rlmcpherson/go-fuzz
func Fuzz(data []byte) int {
	r, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(data)))
	if err != nil {
		return 0
	}
	r.ParseMultipartForm(1e6)
	r.ParseForm()
	r.BasicAuth()
	r.Cookies()
	r.FormFile("foo")
	r.FormValue("bar")
	r.PostFormValue("baz")
	r.MultipartReader()
	r.Referer()
	r.UserAgent()

	// Read it in again, because we consumed body.
	r, err = http.ReadRequest(bufio.NewReader(bytes.NewReader(data)))
	if err != nil {
		panic(err)
	}
	if _, err := ioutil.ReadAll(r.Body); err != nil {
		return 0
	}

	// Read it in again, because we consumed body.
	r, err = http.ReadRequest(bufio.NewReader(bytes.NewReader(data)))
	if err != nil {
		panic(err)
	}
	if err := r.Write(ioutil.Discard); err != nil {
		panic(err)
	}

	// Read it in again, because we consumed body.
	r0, err := http.ReadRequest(bufio.NewReader(bytes.NewReader(data)))
	if err != nil {
		panic(err)
	}
	// Write will set these.
	fix := func(r0 *http.Request) {
		if r0.Header.Get("User-Agent") == "" {
			r0.Header.Set("User-Agent", "Go 1.1 package http")
		}
		if len(r0.Header["User-Agent"]) > 1 {
			r0.Header["User-Agent"] = r0.Header["User-Agent"][:1]
		}
		if r0.Method == "" {
			r0.Method = "GET"
		}
		if r0.Method == "CONNECT" {
			// This won't be send on CONNECT.
			r0.URL.User = nil
			r0.URL.Host = ""
		}
		if r0.URL.Scheme != "" && r0.URL.Opaque == "" {
			// User is not sent in such for some reason.
			r0.URL.User = nil
			r0.URL.Path = ""
			r0.URL.Fragment = ""
		}
		if h := r0.URL.Host; len(h) > 0 && h[len(h)-1] == '%' {
			r0.URL.Host = "aaa"
		}
		// https://github.com/golang/go/issues/11208
		r0.Host = strings.Replace(r0.Host, "%", "a", -1)
		r0.URL.Opaque = strings.Replace(r0.URL.Opaque, "%", "a", -1)
		r0.Trailer = nil
		r0.ProtoMajor = 1
		r0.ProtoMinor = 1
		r0.Header.Del("Trailer")
		r0.Header.Del("Connection")
		for k, v := range r0.Header {
			for i := range v {
				// https://github.com/golang/go/issues/11204
				v[i] = strings.Trim(v[i], " \t\r\n")
				// https://github.com/golang/go/issues/11207
				v[i] = strings.Replace(v[i], "\r", " ", -1)
			}
			r0.Header[k] = v
		}
	}
	fix(r0)

	buf := new(bytes.Buffer)
	if err := r0.WriteProxy(buf); err != nil {
		panic(err)
	}
	data1 := buf.Bytes()
	r1, err := http.ReadRequest(bufio.NewReader(buf))
	if err != nil {
		// https://github.com/golang/go/issues/11202
		// https://github.com/golang/go/issues/11203
		if strings.Contains(err.Error(), "invalid URI for request") {
			return 0
		}
		if strings.Contains(err.Error(), "missing protocol scheme") {
			return 0
		}
		// https://github.com/golang/go/issues/11206
		if strings.Contains(err.Error(), "malformed HTTP version") {
			return 0
		}
		fmt.Printf("req0: %q\nURL: %#v\n", data, *r0.URL)
		fmt.Printf("req1: %q\n", data1)
		panic(err)
	}
	// Read it in again, because we consumed body.
	r0, err = http.ReadRequest(bufio.NewReader(bytes.NewReader(data)))
	if err != nil {
		panic(err)
	}
	fix(r0)
	r0.RequestURI = r1.RequestURI
	r0.Proto = r1.Proto
	if r1.Header.Get("Connection") != "" {
		r0.Header.Set("Connection", r1.Header.Get("Connection"))
	} else {
		r0.Header.Del("Connection")
		r1.Header.Del("Connection")
	}
	if r1.Header.Get("Content-Length") != "" {
		r0.Header.Set("Content-Length", r1.Header.Get("Content-Length"))
	} else {
		r0.Header.Del("Content-Length")
		r1.Header.Del("Content-Length")
	}
	if r0.URL.Path == "" && r1.URL.Path == "/" {
		r0.URL.Path = r1.URL.Path
	}
	// Rules for host are too complex.
	r0.Host = ""
	r1.Host = ""
	r0.URL.Host = ""
	r1.URL.Host = ""
	if (r0.URL.Scheme != "" && r0.URL.Opaque != "") || r0.Method == "CONNECT" {
		r0.URL = nil
		r1.URL = nil
	}
	body0, err := ioutil.ReadAll(r0.Body)
	if err != nil {
		panic(err)
	}
	body1, err := ioutil.ReadAll(r1.Body)
	if err != nil {
		panic(err)
	}
	if !bytes.Equal(body0, body1) {
		fmt.Printf("body0: %q\n", body0)
		fmt.Printf("body1: %q\n", body1)
		panic("body changed")
	}
	r0.Body = nil
	r1.Body = nil
	if !fuzz.DeepEqual(r0, r1) {
		fmt.Printf("req0: %#v\n", *r0)
		fmt.Printf("req1: %#v\n", *r1)
		fmt.Printf("url0: %#v\n", *r0.URL)
		fmt.Printf("url1: %#v\n", *r1.URL)
		panic("not equal")
	}
	return 1
}