diff --git a/go.mod b/go.mod index 9e5e712..e4adbbb 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,6 @@ go 1.12 require ( github.com/google/go-cmp v0.5.3 github.com/mdlayher/netlink v1.1.1 - golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 + golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect + golang.org/x/sys v0.0.0-20201118182958-a01c418693c7 ) diff --git a/go.sum b/go.sum index 05b7933..e30d544 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= @@ -24,6 +25,8 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjut golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -35,8 +38,8 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201118182958-a01c418693c7 h1:Z991aAXPjz0tLnj74pVXW3eWJ5lHMIBvbRfMq4M2jHA= +golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/internal/unix/types_linux.go b/internal/unix/types_linux.go index 52b1a7d..9c747ad 100644 --- a/internal/unix/types_linux.go +++ b/internal/unix/types_linux.go @@ -65,6 +65,9 @@ const ( IFLA_XDP_FLAGS = linux.IFLA_XDP_FLAGS IFLA_XDP_PROG_ID = linux.IFLA_XDP_PROG_ID IFLA_XDP_EXPECTED_FD = linux.IFLA_XDP_EXPECTED_FD + LWTUNNEL_ENCAP_MPLS = linux.LWTUNNEL_ENCAP_MPLS + MPLS_IPTUNNEL_DST = linux.MPLS_IPTUNNEL_DST + MPLS_IPTUNNEL_TTL = linux.MPLS_IPTUNNEL_TTL NDA_UNSPEC = linux.NDA_UNSPEC NDA_DST = linux.NDA_DST NDA_LLADDR = linux.NDA_LLADDR @@ -72,6 +75,8 @@ const ( NDA_IFINDEX = linux.NDA_IFINDEX RTA_UNSPEC = linux.RTA_UNSPEC RTA_DST = linux.RTA_DST + RTA_ENCAP = linux.RTA_ENCAP + RTA_ENCAP_TYPE = linux.RTA_ENCAP_TYPE RTA_PREFSRC = linux.RTA_PREFSRC RTA_GATEWAY = linux.RTA_GATEWAY RTA_OIF = linux.RTA_OIF diff --git a/internal/unix/types_other.go b/internal/unix/types_other.go index 76f1bf4..3fbd62b 100644 --- a/internal/unix/types_other.go +++ b/internal/unix/types_other.go @@ -61,6 +61,9 @@ const ( IFLA_XDP_FLAGS = 0x3 IFLA_XDP_PROG_ID = 0x4 IFLA_XDP_EXPECTED_FD = 0x8 + LWTUNNEL_ENCAP_MPLS = 0x1 + MPLS_IPTUNNEL_DST = 0x1 + MPLS_IPTUNNEL_TTL = 0x2 NDA_UNSPEC = 0x0 NDA_DST = 0x1 NDA_LLADDR = 0x2 @@ -68,6 +71,8 @@ const ( NDA_IFINDEX = 0x8 RTA_UNSPEC = 0x0 RTA_DST = 0x1 + RTA_ENCAP = 0x16 + RTA_ENCAP_TYPE = 0x15 RTA_PREFSRC = 0x7 RTA_GATEWAY = 0x5 RTA_OIF = 0x4 diff --git a/route.go b/route.go index 7be1885..4eaf2f0 100644 --- a/route.go +++ b/route.go @@ -1,6 +1,7 @@ package rtnetlink import ( + "encoding/binary" "errors" "net" "unsafe" @@ -348,8 +349,9 @@ type RTNextHop struct { // NextHop wraps struct rtnexthop to provide access to nested attributes type NextHop struct { - Hop RTNextHop // a rtnexthop struct - Gateway net.IP // that struct's nested Gateway attribute + Hop RTNextHop // a rtnexthop struct + Gateway net.IP // that struct's nested Gateway attribute + MPLS []MPLSNextHop // Any MPLS next hops for a route. } func (a *RouteAttributes) encodeMultipath() ([]byte, error) { @@ -359,11 +361,18 @@ func (a *RouteAttributes) encodeMultipath() ([]byte, error) { // compute the length of each (rtnexthop, attributes) pair. ae := netlink.NewAttributeEncoder() - if a.Gateway != nil { + if nh.Gateway != nil { // TODO(mdlayher): more validation. ae.Bytes(unix.RTA_GATEWAY, nh.Gateway) } + if len(nh.MPLS) > 0 { + // TODO(mdlayher): validation over different encapsulation types, + // and ensure that only one can be set. + ae.Uint16(unix.RTA_ENCAP_TYPE, unix.LWTUNNEL_ENCAP_MPLS) + ae.Nested(unix.RTA_ENCAP, nh.encodeEncap) + } + ab, err := ae.Encode() if err != nil { return nil, err @@ -417,16 +426,26 @@ func (a *RouteAttributes) parseMultipath(b []byte) error { return mpp.Err() } -// rtnexthop payload is at least one nested attribute RTA_GATEWAY -// possibly others? +// decode decodes netlink attribute values into a NextHop. func (nh *NextHop) decode(ad *netlink.AttributeDecoder) error { if ad == nil { // Invalid decoder, do nothing. return nil } + // If encapsulation is present, we won't know how to deal with it until we + // identify the right type and then later parse the nested attribute bytes. + var ( + encapType uint16 + encapBuf []byte + ) + for ad.Next() { switch ad.Type() { + case unix.RTA_ENCAP: + encapBuf = ad.Bytes() + case unix.RTA_ENCAP_TYPE: + encapType = ad.Uint16() case unix.RTA_GATEWAY: l := len(ad.Bytes()) if l != 4 && l != 16 { @@ -437,6 +456,103 @@ func (nh *NextHop) decode(ad *netlink.AttributeDecoder) error { } } + if err := ad.Err(); err != nil { + return err + } + + if encapType != 0 && encapBuf != nil { + // Found encapsulation, start decoding it from the buffer. + return nh.decodeEncap(encapType, encapBuf) + } + + return nil +} + +// An MPLSNextHop is a route next hop using MPLS encapsulation. +type MPLSNextHop struct { + Label int + TrafficClass int + BottomOfStack bool + TTL uint8 +} + +// TODO(mdlayher): MPLSNextHop TTL vs MPLS_IPTUNNEL_TTL. What's the difference? + +// encodeEncap encodes netlink attribute values related to encapsulation from +// a NextHop. +func (nh *NextHop) encodeEncap(ae *netlink.AttributeEncoder) error { + // TODO: this only handles MPLS encapsulation as that is all we support. + + // Allocate enough space for an MPLS label stack. + var ( + i int + b = make([]byte, 4*len(nh.MPLS)) + ) + + for _, mnh := range nh.MPLS { + // Pack the following: + // - label: 20 bits + // - traffic class: 3 bits + // - bottom-of-stack: 1 bit + // - TTL: 8 bits + binary.BigEndian.PutUint32(b[i:i+4], uint32(mnh.Label)<<12) + + b[i+2] |= byte(mnh.TrafficClass) << 1 + + if mnh.BottomOfStack { + b[i+2] |= 1 + } + + b[i+3] = mnh.TTL + + // Advance in the buffer to begin storing the next label. + i += 4 + } + + // Finally store the output bytes. + ae.Bytes(unix.MPLS_IPTUNNEL_DST, b) + return nil +} + +// decodeEncap decodes netlink attribute values related to encapsulation into a +// NextHop. +func (nh *NextHop) decodeEncap(typ uint16, b []byte) error { + if typ != unix.LWTUNNEL_ENCAP_MPLS { + // TODO: handle other encapsulation types as needed. + return nil + } + + // MPLS labels are stored as big endian bytes. + ad, err := netlink.NewAttributeDecoder(b) + if err != nil { + return err + } + + for ad.Next() { + switch ad.Type() { + case unix.MPLS_IPTUNNEL_DST: + // Every 4 bytes stores another MPLS label, so make sure the stored + // bytes are divisible by exactly 4. + b := ad.Bytes() + if len(b)%4 != 0 { + return errInvalidRouteMessageAttr + } + + for i := 0; i < len(b); i += 4 { + n := binary.BigEndian.Uint32(b[i : i+4]) + + // For reference, see: + // https://en.wikipedia.org/wiki/Multiprotocol_Label_Switching#Operation + nh.MPLS = append(nh.MPLS, MPLSNextHop{ + Label: int(n) >> 12, + TrafficClass: int(n & 0xe00 >> 9), + BottomOfStack: n&0x100 != 0, + TTL: uint8(n & 0xff), + }) + } + } + } + return ad.Err() } diff --git a/route_test.go b/route_test.go index 77b315c..d68c1fd 100644 --- a/route_test.go +++ b/route_test.go @@ -204,6 +204,96 @@ func TestRouteMessageMarshalUnmarshalBinary(t *testing.T) { } } +func TestRouteMessageMarshalRoundTrip(t *testing.T) { + skipBigEndian(t) + + // The above tests begin with unmarshaling raw bytes and are more + // comprehensive, but due to the complexity of nested route message + // attributes and structures, it has become rather difficult to maintain + // over time. These tests will focus on a subset of that functionality to + // ensure that marshaling and unmarshaling perform symmetrical operations + // given a proper Go type as input, rather than raw bytes. + + tests := []struct { + name string + m *RouteMessage + }{ + { + name: "multipath MPLS", + m: &RouteMessage{ + Attributes: RouteAttributes{ + Multipath: []NextHop{ + { + Hop: RTNextHop{ + Length: 48, + IfIndex: 1, + }, + Gateway: net.IPv4(10, 0, 0, 2), + MPLS: []MPLSNextHop{{ + Label: 1, + TrafficClass: 1, + BottomOfStack: true, + TTL: 1, + }}, + }, + { + Hop: RTNextHop{ + Length: 52, + IfIndex: 2, + }, + Gateway: net.IPv4(10, 0, 0, 3), + MPLS: []MPLSNextHop{ + { + Label: 1, + TrafficClass: 1, + TTL: 1, + }, + { + Label: 2, + TrafficClass: 2, + BottomOfStack: true, + TTL: 2, + }, + }, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // First do a marshaling and unmarshaling round trip to ensure + // the inputs and outputs are identical. + b1, err := tt.m.MarshalBinary() + if err != nil { + t.Fatalf("failed to marshal test message: %v", err) + } + + var m RouteMessage + if err := m.UnmarshalBinary(b1); err != nil { + t.Fatalf("failed to unmarshal: %v", err) + } + + if diff := cmp.Diff(tt.m, &m); diff != "" { + t.Fatalf("unexpected RouteMessage after round-trip (-want +got):\n%s", diff) + } + + // Then compare the results of the first marshaled bytes against + // the newly marshaled bytes. + b2, err := m.MarshalBinary() + if err != nil { + t.Fatalf("failed to marshal parsed message: %v", err) + } + + if diff := cmp.Diff(b1, b2); diff != "" { + t.Fatalf("unexpected final raw byte output (-want +got):\n%s", diff) + } + }) + } +} + func TestRouteMessageUnmarshalBinaryErrors(t *testing.T) { skipBigEndian(t) diff --git a/testdata/corpus/015234b16d15fc9a8d0087ebcbabf42ed76c0812-38 b/testdata/corpus/015234b16d15fc9a8d0087ebcbabf42ed76c0812-38 new file mode 100644 index 0000000..52ac625 Binary files /dev/null and b/testdata/corpus/015234b16d15fc9a8d0087ebcbabf42ed76c0812-38 differ diff --git a/testdata/corpus/049f49dc2b6c163d5faf1ded2c621fd1a28c9747-38 b/testdata/corpus/049f49dc2b6c163d5faf1ded2c621fd1a28c9747-38 new file mode 100644 index 0000000..cc4bdb4 Binary files /dev/null and b/testdata/corpus/049f49dc2b6c163d5faf1ded2c621fd1a28c9747-38 differ diff --git a/testdata/corpus/082652416315336b5ba00681f7a743ccbbcbdd71-39 b/testdata/corpus/082652416315336b5ba00681f7a743ccbbcbdd71-39 new file mode 100644 index 0000000..8cfaa68 Binary files /dev/null and b/testdata/corpus/082652416315336b5ba00681f7a743ccbbcbdd71-39 differ diff --git a/testdata/corpus/1820dbf6107ca7b5c9a0467c4d9303de5d983334-36 b/testdata/corpus/1820dbf6107ca7b5c9a0467c4d9303de5d983334-36 new file mode 100644 index 0000000..dfe5553 Binary files /dev/null and b/testdata/corpus/1820dbf6107ca7b5c9a0467c4d9303de5d983334-36 differ diff --git a/testdata/corpus/22050367926486cb43405d88b376404852959eb0-37 b/testdata/corpus/22050367926486cb43405d88b376404852959eb0-37 new file mode 100644 index 0000000..34f1dc4 Binary files /dev/null and b/testdata/corpus/22050367926486cb43405d88b376404852959eb0-37 differ diff --git a/testdata/corpus/2b10146eb2804173932f2f25df49dcde84bd5422-39 b/testdata/corpus/2b10146eb2804173932f2f25df49dcde84bd5422-39 new file mode 100644 index 0000000..16b1d04 Binary files /dev/null and b/testdata/corpus/2b10146eb2804173932f2f25df49dcde84bd5422-39 differ diff --git a/testdata/corpus/2bf9c12550df885e9b2f0066bdaa24d693ba358b-38 b/testdata/corpus/2bf9c12550df885e9b2f0066bdaa24d693ba358b-38 new file mode 100644 index 0000000..b095271 Binary files /dev/null and b/testdata/corpus/2bf9c12550df885e9b2f0066bdaa24d693ba358b-38 differ diff --git a/testdata/corpus/2e9520c3b8fd2b783473a53ce62ed06a80684085-39 b/testdata/corpus/2e9520c3b8fd2b783473a53ce62ed06a80684085-39 new file mode 100644 index 0000000..b0efdd3 Binary files /dev/null and b/testdata/corpus/2e9520c3b8fd2b783473a53ce62ed06a80684085-39 differ diff --git a/testdata/corpus/3dc09ec53e9c6aaee007fa6d1bc15e94fffbc71d-40 b/testdata/corpus/3dc09ec53e9c6aaee007fa6d1bc15e94fffbc71d-40 new file mode 100644 index 0000000..eaf2ed3 Binary files /dev/null and b/testdata/corpus/3dc09ec53e9c6aaee007fa6d1bc15e94fffbc71d-40 differ diff --git a/testdata/corpus/5171ca7f61ac7a502d3d95b7939f6484604d76a4-36 b/testdata/corpus/5171ca7f61ac7a502d3d95b7939f6484604d76a4-36 new file mode 100644 index 0000000..1fcc726 Binary files /dev/null and b/testdata/corpus/5171ca7f61ac7a502d3d95b7939f6484604d76a4-36 differ diff --git a/testdata/corpus/579d7e8d1b834c1665bf8d262f3db3ef0d15f768-41 b/testdata/corpus/579d7e8d1b834c1665bf8d262f3db3ef0d15f768-41 new file mode 100644 index 0000000..56aa1fb Binary files /dev/null and b/testdata/corpus/579d7e8d1b834c1665bf8d262f3db3ef0d15f768-41 differ diff --git a/testdata/corpus/57c84d561021cf943fbe5f8e16fb4779a0f28565-39 b/testdata/corpus/57c84d561021cf943fbe5f8e16fb4779a0f28565-39 new file mode 100644 index 0000000..d66a431 Binary files /dev/null and b/testdata/corpus/57c84d561021cf943fbe5f8e16fb4779a0f28565-39 differ diff --git a/testdata/corpus/62b920726253e633e85f93860b81a7cbb9a9d2d2-44 b/testdata/corpus/62b920726253e633e85f93860b81a7cbb9a9d2d2-44 new file mode 100644 index 0000000..f99b00b Binary files /dev/null and b/testdata/corpus/62b920726253e633e85f93860b81a7cbb9a9d2d2-44 differ diff --git a/testdata/corpus/6e7731a90348ac8f9a9b796a36b0d0b69626c649-40 b/testdata/corpus/6e7731a90348ac8f9a9b796a36b0d0b69626c649-40 new file mode 100644 index 0000000..ae4a057 Binary files /dev/null and b/testdata/corpus/6e7731a90348ac8f9a9b796a36b0d0b69626c649-40 differ diff --git a/testdata/corpus/793b71b44e38d3dd13bac21a7122660593abe93e-40 b/testdata/corpus/793b71b44e38d3dd13bac21a7122660593abe93e-40 new file mode 100644 index 0000000..fbff56c Binary files /dev/null and b/testdata/corpus/793b71b44e38d3dd13bac21a7122660593abe93e-40 differ diff --git a/testdata/corpus/7c9c703ad40808292786df199ad7b19c9e62ef41-37 b/testdata/corpus/7c9c703ad40808292786df199ad7b19c9e62ef41-37 new file mode 100644 index 0000000..3292cb8 Binary files /dev/null and b/testdata/corpus/7c9c703ad40808292786df199ad7b19c9e62ef41-37 differ diff --git a/testdata/corpus/7d3d6e6c965f90001b7c070c3b0a13b6eaf7a7b2-38 b/testdata/corpus/7d3d6e6c965f90001b7c070c3b0a13b6eaf7a7b2-38 new file mode 100644 index 0000000..df21428 Binary files /dev/null and b/testdata/corpus/7d3d6e6c965f90001b7c070c3b0a13b6eaf7a7b2-38 differ diff --git a/testdata/corpus/897184d5d21106fd90c7fb106e3b6bc2a82cc747-42 b/testdata/corpus/897184d5d21106fd90c7fb106e3b6bc2a82cc747-42 new file mode 100644 index 0000000..f2d1353 Binary files /dev/null and b/testdata/corpus/897184d5d21106fd90c7fb106e3b6bc2a82cc747-42 differ diff --git a/testdata/corpus/8b3a1a36b36ef5bc3b65aec5ac39b6147bdd7827-36 b/testdata/corpus/8b3a1a36b36ef5bc3b65aec5ac39b6147bdd7827-36 new file mode 100644 index 0000000..d0ca030 Binary files /dev/null and b/testdata/corpus/8b3a1a36b36ef5bc3b65aec5ac39b6147bdd7827-36 differ diff --git a/testdata/corpus/8c17bb9286605de46b6821387afce1ec5deb05eb-43 b/testdata/corpus/8c17bb9286605de46b6821387afce1ec5deb05eb-43 new file mode 100644 index 0000000..251c045 Binary files /dev/null and b/testdata/corpus/8c17bb9286605de46b6821387afce1ec5deb05eb-43 differ diff --git a/testdata/corpus/8f433f0523d2446a2d89543e110eb2e4d9c32574-45 b/testdata/corpus/8f433f0523d2446a2d89543e110eb2e4d9c32574-45 new file mode 100644 index 0000000..59ce170 Binary files /dev/null and b/testdata/corpus/8f433f0523d2446a2d89543e110eb2e4d9c32574-45 differ diff --git a/testdata/corpus/91be8558028512ff8b8347a5cb2f1fc3d638d2a5-37 b/testdata/corpus/91be8558028512ff8b8347a5cb2f1fc3d638d2a5-37 new file mode 100644 index 0000000..da188a0 Binary files /dev/null and b/testdata/corpus/91be8558028512ff8b8347a5cb2f1fc3d638d2a5-37 differ diff --git a/testdata/corpus/92d4fec98c3d3bfa639ee7b8eef2cc053ce28371-40 b/testdata/corpus/92d4fec98c3d3bfa639ee7b8eef2cc053ce28371-40 new file mode 100644 index 0000000..f905ce3 Binary files /dev/null and b/testdata/corpus/92d4fec98c3d3bfa639ee7b8eef2cc053ce28371-40 differ diff --git a/testdata/corpus/9995561d583953138ccfd0e503281ceb1ce41303-43 b/testdata/corpus/9995561d583953138ccfd0e503281ceb1ce41303-43 new file mode 100644 index 0000000..809d65a Binary files /dev/null and b/testdata/corpus/9995561d583953138ccfd0e503281ceb1ce41303-43 differ diff --git a/testdata/corpus/a19f5e2491ee591b9b56a677774959ba11cc3904-41 b/testdata/corpus/a19f5e2491ee591b9b56a677774959ba11cc3904-41 new file mode 100644 index 0000000..5d9d538 Binary files /dev/null and b/testdata/corpus/a19f5e2491ee591b9b56a677774959ba11cc3904-41 differ diff --git a/testdata/corpus/ae8252330686905fb5ca04487bcce1495d049916-39 b/testdata/corpus/ae8252330686905fb5ca04487bcce1495d049916-39 new file mode 100644 index 0000000..c6bbd50 Binary files /dev/null and b/testdata/corpus/ae8252330686905fb5ca04487bcce1495d049916-39 differ diff --git a/testdata/corpus/ba740bcd54cbcd72e1ee257b491e12b0393688f7-37 b/testdata/corpus/ba740bcd54cbcd72e1ee257b491e12b0393688f7-37 new file mode 100644 index 0000000..980a27f Binary files /dev/null and b/testdata/corpus/ba740bcd54cbcd72e1ee257b491e12b0393688f7-37 differ diff --git a/testdata/corpus/bf2de846441c88778157887d19dd31dcfec04275-41 b/testdata/corpus/bf2de846441c88778157887d19dd31dcfec04275-41 new file mode 100644 index 0000000..ac17c03 Binary files /dev/null and b/testdata/corpus/bf2de846441c88778157887d19dd31dcfec04275-41 differ diff --git a/testdata/corpus/c786db5f13f18bdf03cdf0a0960633d80228f1ba-45 b/testdata/corpus/c786db5f13f18bdf03cdf0a0960633d80228f1ba-45 new file mode 100644 index 0000000..77d2748 Binary files /dev/null and b/testdata/corpus/c786db5f13f18bdf03cdf0a0960633d80228f1ba-45 differ diff --git a/testdata/corpus/c9fa1541d79005ea684b524b509412ac99bf0922-37 b/testdata/corpus/c9fa1541d79005ea684b524b509412ac99bf0922-37 new file mode 100644 index 0000000..252a41d Binary files /dev/null and b/testdata/corpus/c9fa1541d79005ea684b524b509412ac99bf0922-37 differ diff --git a/testdata/corpus/ce8e84d605fbd5e56c4228047ebb0df33d419f9a-44 b/testdata/corpus/ce8e84d605fbd5e56c4228047ebb0df33d419f9a-44 new file mode 100644 index 0000000..2155d4b Binary files /dev/null and b/testdata/corpus/ce8e84d605fbd5e56c4228047ebb0df33d419f9a-44 differ diff --git a/testdata/corpus/d90dbd3bc30144653fa216693e1da2371b75e35c-37 b/testdata/corpus/d90dbd3bc30144653fa216693e1da2371b75e35c-37 new file mode 100644 index 0000000..f94f262 Binary files /dev/null and b/testdata/corpus/d90dbd3bc30144653fa216693e1da2371b75e35c-37 differ diff --git a/testdata/corpus/e9f13f887905c098392e3e07bb1c1e0dec1adb72-42 b/testdata/corpus/e9f13f887905c098392e3e07bb1c1e0dec1adb72-42 new file mode 100644 index 0000000..f4b095e Binary files /dev/null and b/testdata/corpus/e9f13f887905c098392e3e07bb1c1e0dec1adb72-42 differ diff --git a/testdata/corpus/f1a6fc940fa8898d872272a80983757b5c0d7022-43 b/testdata/corpus/f1a6fc940fa8898d872272a80983757b5c0d7022-43 new file mode 100644 index 0000000..26c907d Binary files /dev/null and b/testdata/corpus/f1a6fc940fa8898d872272a80983757b5c0d7022-43 differ diff --git a/testdata/corpus/fe9fabd89fb613484e6ba2c4cf7126497ec94718-36 b/testdata/corpus/fe9fabd89fb613484e6ba2c4cf7126497ec94718-36 new file mode 100644 index 0000000..7979934 Binary files /dev/null and b/testdata/corpus/fe9fabd89fb613484e6ba2c4cf7126497ec94718-36 differ