Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/net/http2: Spec conformance fails #38647

Closed
nfisher opened this issue Apr 24, 2020 · 2 comments
Closed

x/net/http2: Spec conformance fails #38647

nfisher opened this issue Apr 24, 2020 · 2 comments

Comments

@nfisher
Copy link

nfisher commented Apr 24, 2020

What version of Go are you using (go version)?

$ go version
go version go1.14.2 darwin/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/nfisher/Library/Caches/go-build"
GOENV="/Users/nfisher/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/nfisher/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/96/3dc1j8vj39l7qqhz8bdlk89c0000gn/T/go-build889400283=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I ran h2spec -p 8443 -k -t against a minimal http.ListenAndServeTLS . Will post code once I've cleaned it up for a minimal test case.

Details in go.mod are as follows:

module foo/bar
go 1.14

require golang.org/x/net v0.0.0-20200421231249-e086a090c8fd

main.go (it's basically the echo handler)

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"io"
	"log"
	"math/big"
	"net"
	"net/http"
	"os"
	"time"

	"golang.org/x/net/http2"
)

type capitalizeReader struct {
	r io.Reader
}

func (cr capitalizeReader) Read(p []byte) (n int, err error) {
	n, err = cr.r.Read(p)
	for i, b := range p[:n] {
		if b >= 'a' && b <= 'z' {
			p[i] = b - ('a' - 'A')
		}
	}
	return
}

type flushWriter struct {
	w io.Writer
}

func (fw flushWriter) Write(p []byte) (n int, err error) {
	n, err = fw.w.Write(p)
	if f, ok := fw.w.(http.Flusher); ok {
		f.Flush()
	}
	return
}

func echoCapitalHandler(w http.ResponseWriter, r *http.Request) {
	if f, ok := w.(http.Flusher); ok {
		f.Flush()
	}
	io.Copy(flushWriter{w}, capitalizeReader{r.Body})
}

func main() {
	host := "localhost"
	privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
	if err != nil {
		log.Fatalf("error generating key: %v\n", err)
	}
	writeKey(privateKey, host)

	mux := http.NewServeMux()
	mux.HandleFunc("/", echoCapitalHandler)

	w, err := os.Create("nss.log")
	if err != nil {
		log.Fatal(err)
	}
	cfg := &tls.Config{
		MinVersion:    tls.VersionTLS12,
		Renegotiation: tls.RenegotiateOnceAsClient,
		CipherSuites: []uint16{
			tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
		},
		KeyLogWriter: w,
	}
	srv := &http.Server{
		Addr:      fmt.Sprintf("%s:8443", host),
		Handler:   mux,
		TLSConfig: cfg,
	}

	//ConnState: idleTimeoutHook(),

	http2.VerboseLogs = true
	//http2.ConfigureServer(srv, &http2.Server{})
	log.Printf("binding to listening address %s:8443\n", host)
	log.Fatal(srv.ListenAndServeTLS("cert.pem", "key.pem"))
}

// writeKey converts the rsa.PrivateKey to a PEM key and writes it to disk.
func writeKey(priv *rsa.PrivateKey, host string) {
	var validFor time.Duration = time.Hour * 7 * 24
	notBefore := time.Now()
	notAfter := notBefore.Add(validFor)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		log.Fatalf("Failed to generate serial number: %v", err)
	}

	template := x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Instana Inc."},
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}

	if ip := net.ParseIP(host); ip != nil {
		template.IPAddresses = append(template.IPAddresses, ip)
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		log.Fatalf("Failed to create certificate: %v", err)
	}

	certOut, err := os.Create("cert.pem")
	if err != nil {
		log.Fatalf("Failed to open cert.pem for writing: %v", err)
	}
	if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
		log.Fatalf("Failed to write data to cert.pem: %v", err)
	}
	if err := certOut.Close(); err != nil {
		log.Fatalf("Error closing cert.pem: %v", err)
	}
	log.Print("wrote cert.pem\n")

	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		log.Fatalf("Failed to open key.pem for writing: %v", err)
		return
	}
	privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
	if err != nil {
		log.Fatalf("Unable to marshal private key: %v", err)
	}
	if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
		log.Fatalf("Failed to write data to key.pem: %v", err)
	}
	if err := keyOut.Close(); err != nil {
		log.Fatalf("Error closing key.pem: %v", err)
	}
	log.Print("wrote key.pem\n")
}

What did you expect to see?

All tests to pass.

What did you see instead?

The following summary of failures:

  • 4.2.3: Sends a large size HEADERS frame that exceeds the SETTINGS_MAX_FRAME_SIZE
  • 5.1.2.1: Sends HEADERS frames that causes their advertised concurrent stream limit to be exceeded
  • 8.1.2.2.1: Sends a HEADERS frame that contains the connection-specific header field
  • 8.1.2.2.2: Sends a HEADERS frame that contains the TE header field with any value other than "trailers"

The results summary was 145 tests, 137 passed, 4 skipped, 4 failed

Full output:

h2spec -p 8443 -k -t 
Generic tests for HTTP/2 server
  1. Starting HTTP/2
    ✔ 1: Sends a client connection preface

  2. Streams and Multiplexing
    ✔ 1: Sends a PRIORITY frame on idle stream
    ✔ 2: Sends a WINDOW_UPDATE frame on half-closed (remote) stream
    ✔ 3: Sends a PRIORITY frame on half-closed (remote) stream
    ✔ 4: Sends a RST_STREAM frame on half-closed (remote) stream
    ✔ 5: Sends a PRIORITY frame on closed stream

  3. Frame Definitions
    3.1. DATA
      ✔ 1: Sends a DATA frame
      ✔ 2: Sends multiple DATA frames
      ✔ 3: Sends a DATA frame with padding

    3.2. HEADERS
      ✔ 1: Sends a HEADERS frame
      ✔ 2: Sends a HEADERS frame with padding
      ✔ 3: Sends a HEADERS frame with priority

    3.3. PRIORITY
      ✔ 1: Sends a PRIORITY frame with priority 1
      ✔ 2: Sends a PRIORITY frame with priority 256
      ✔ 3: Sends a PRIORITY frame with stream dependency
      ✔ 4: Sends a PRIORITY frame with exclusive
      ✔ 5: Sends a PRIORITY frame for an idle stream, then send a HEADER frame for a lower stream ID

    3.4. RST_STREAM
      ✔ 1: Sends a RST_STREAM frame

    3.5. SETTINGS
      ✔ 1: Sends a SETTINGS frame

    3.7. PING
      ✔ 1: Sends a PING frame

    3.8. GOAWAY
      ✔ 1: Sends a GOAWAY frame

    3.9. WINDOW_UPDATE
      ✔ 1: Sends a WINDOW_UPDATE frame with stream ID 0
      ✔ 2: Sends a WINDOW_UPDATE frame with stream ID 1

    3.10. CONTINUATION
      ✔ 1: Sends a CONTINUATION frame
      ✔ 2: Sends multiple CONTINUATION frames

  4. HTTP Message Exchanges
    ✔ 1: Sends a GET request
    ✔ 2: Sends a HEAD request
    ✔ 3: Sends a POST request
    ✔ 4: Sends a POST request with trailers

  5. HPACK
    ✔ 1: Sends a indexed header field representation
    ✔ 2: Sends a literal header field with incremental indexing - indexed name
    ✔ 3: Sends a literal header field with incremental indexing - indexed name (with Huffman coding)
    ✔ 4: Sends a literal header field with incremental indexing - new name
    ✔ 5: Sends a literal header field with incremental indexing - new name (with Huffman coding)
    ✔ 6: Sends a literal header field without indexing - indexed name
    ✔ 7: Sends a literal header field without indexing - indexed name (with Huffman coding)
    ✔ 8: Sends a literal header field without indexing - new name
    ✔ 9: Sends a literal header field without indexing - new name (huffman encoded)
    ✔ 10: Sends a literal header field never indexed - indexed name
    ✔ 11: Sends a literal header field never indexed - indexed name (huffman encoded)
    ✔ 12: Sends a literal header field never indexed - new name
    ✔ 13: Sends a literal header field never indexed - new name (huffman encoded)
    ✔ 14: Sends a dynamic table size update
    ✔ 15: Sends multiple dynamic table size update

Hypertext Transfer Protocol Version 2 (HTTP/2)
  3. Starting HTTP/2
    3.5. HTTP/2 Connection Preface
      ✔ 1: Sends client connection preface
      ✔ 2: Sends invalid connection preface

  4. HTTP Frames
    4.1. Frame Format
      ✔ 1: Sends a frame with unknown type
      ✔ 2: Sends a frame with undefined flag
      ✔ 3: Sends a frame with reserved field bit

    4.2. Frame Size
      ✔ 1: Sends a DATA frame with 2^14 octets in length
      ✔ 2: Sends a large size DATA frame that exceeds the SETTINGS_MAX_FRAME_SIZE
      × 3: Sends a large size HEADERS frame that exceeds the SETTINGS_MAX_FRAME_SIZE
        -> The endpoint MUST respond with a connection error of type FRAME_SIZE_ERROR.
           Expected: GOAWAY Frame (Error Code: FRAME_SIZE_ERROR)
                     Connection closed
             Actual: DATA Frame (length:0, flags:0x01, stream_id:1)

    4.3. Header Compression and Decompression
      ✔ 1: Sends invalid header block fragment
      ✔ 2: Sends a PRIORITY frame while sending the header blocks
      ✔ 3: Sends a HEADERS frame to another stream while sending the header blocks

  5. Streams and Multiplexing
    5.1. Stream States
      ✔ 1: idle: Sends a DATA frame
      ✔ 2: idle: Sends a RST_STREAM frame
      ✔ 3: idle: Sends a WINDOW_UPDATE frame
      ✔ 4: idle: Sends a CONTINUATION frame
      ✔ 5: half closed (remote): Sends a DATA frame
      ✔ 6: half closed (remote): Sends a HEADERS frame
      ✔ 7: half closed (remote): Sends a CONTINUATION frame
      ✔ 8: closed: Sends a DATA frame after sending RST_STREAM frame
      ✔ 9: closed: Sends a HEADERS frame after sending RST_STREAM frame
      ✔ 10: closed: Sends a CONTINUATION frame after sending RST_STREAM frame
      ✔ 11: closed: Sends a DATA frame
      ✔ 12: closed: Sends a HEADERS frame
      ✔ 13: closed: Sends a CONTINUATION frame

      5.1.1. Stream Identifiers
        ✔ 1: Sends even-numbered stream identifier
        ✔ 2: Sends stream identifier that is numerically smaller than previous

      5.1.2. Stream Concurrency
        × 1: Sends HEADERS frames that causes their advertised concurrent stream limit to be exceeded
          -> The endpoint MUST treat this as a stream error of type PROTOCOL_ERROR or REFUSED_STREAM.
             Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR)
                       RST_STREAM Frame (Error Code: PROTOCOL_ERROR)
                       GOAWAY Frame (Error Code: REFUSED_STREAM)
                       RST_STREAM Frame (Error Code: REFUSED_STREAM)
                       Connection closed
               Actual: DATA Frame (length:0, flags:0x01, stream_id:85)

    5.3. Stream Priority
      5.3.1. Stream Dependencies
        ✔ 1: Sends HEADERS frame that depends on itself
        ✔ 2: Sends PRIORITY frame that depend on itself

    5.4. Error Handling
      5.4.1. Connection Error Handling
        ✔ 1: Sends an invalid PING frame for connection close

    5.5. Extending HTTP/2
      ✔ 1: Sends an unknown extension frame
      ✔ 2: Sends an unknown extension frame in the middle of a header block

  6. Frame Definitions
    6.1. DATA
      ✔ 1: Sends a DATA frame with 0x0 stream identifier
      ✔ 2: Sends a DATA frame on the stream that is not in "open" or "half-closed (local)" state
      ✔ 3: Sends a DATA frame with invalid pad length

    6.2. HEADERS
      ✔ 1: Sends a HEADERS frame without the END_HEADERS flag, and a PRIORITY frame
      ✔ 2: Sends a HEADERS frame to another stream while sending a HEADERS frame
      ✔ 3: Sends a HEADERS frame with 0x0 stream identifier
      ✔ 4: Sends a HEADERS frame with invalid pad length

    6.3. PRIORITY
      ✔ 1: Sends a PRIORITY frame with 0x0 stream identifier
      ✔ 2: Sends a PRIORITY frame with a length other than 5 octets

    6.4. RST_STREAM
      ✔ 1: Sends a RST_STREAM frame with 0x0 stream identifier
      ✔ 2: Sends a RST_STREAM frame on a idle stream
      ✔ 3: Sends a RST_STREAM frame with a length other than 4 octets

    6.5. SETTINGS
      ✔ 1: Sends a SETTINGS frame with ACK flag and payload
      ✔ 2: Sends a SETTINGS frame with a stream identifier other than 0x0
      ✔ 3: Sends a SETTINGS frame with a length other than a multiple of 6 octets

      6.5.2. Defined SETTINGS Parameters
        ✔ 1: SETTINGS_ENABLE_PUSH (0x2): Sends the value other than 0 or 1
        ✔ 2: SETTINGS_INITIAL_WINDOW_SIZE (0x4): Sends the value above the maximum flow control window size
        ✔ 3: SETTINGS_MAX_FRAME_SIZE (0x5): Sends the value below the initial value
        ✔ 4: SETTINGS_MAX_FRAME_SIZE (0x5): Sends the value above the maximum allowed frame size
        ✔ 5: Sends a SETTINGS frame with unknown identifier

      6.5.3. Settings Synchronization
        1: Sends multiple values of SETTINGS_INITIAL_WINDOW_SIZEZE
        ✔ 2: Sends a SETTINGS frame without ACK flag

    6.7. PING
      ✔ 1: Sends a PING frame
      ✔ 2: Sends a PING frame with ACK
      ✔ 3: Sends a PING frame with a stream identifier field value other than 0x0
      ✔ 4: Sends a PING frame with a length field value other than 8

    6.8. GOAWAY
      ✔ 1: Sends a GOAWAY frame with a stream identifier other than 0x0

    6.9. WINDOW_UPDATE
      ✔ 1: Sends a WINDOW_UPDATE frame with a flow control window increment of 0
      ✔ 2: Sends a WINDOW_UPDATE frame with a flow control window increment of 0 on a stream
      ✔ 3: Sends a WINDOW_UPDATE frame with a length other than 4 octets

      6.9.1. The Flow-Control Window
        1: Sends SETTINGS frame to set the initial window size to 1 and sends HEADERS frameme
        ✔ 2: Sends multiple WINDOW_UPDATE frames increasing the flow control window to above 2^31-1
        ✔ 3: Sends multiple WINDOW_UPDATE frames increasing the flow control window to above 2^31-1 on a stream

      6.9.2. Initial Flow-Control Window Size
        1: Changes SETTINGS_INITIAL_WINDOW_SIZE after sending HEADERS frameme
        2: Sends a SETTINGS frame for window size to be negativeve
        ✔ 3: Sends a SETTINGS_INITIAL_WINDOW_SIZE settings with an exceeded maximum window size value

    6.10. CONTINUATION
      ✔ 1: Sends multiple CONTINUATION frames preceded by a HEADERS frame
      ✔ 2: Sends a CONTINUATION frame followed by any frame other than CONTINUATION
      ✔ 3: Sends a CONTINUATION frame with 0x0 stream identifier
      ✔ 4: Sends a CONTINUATION frame preceded by a HEADERS frame with END_HEADERS flag
      ✔ 5: Sends a CONTINUATION frame preceded by a CONTINUATION frame with END_HEADERS flag
      ✔ 6: Sends a CONTINUATION frame preceded by a DATA frame

  7. Error Codes
    ✔ 1: Sends a GOAWAY frame with unknown error code
    ✔ 2: Sends a RST_STREAM frame with unknown error code

  8. HTTP Message Exchanges
    8.1. HTTP Request/Response Exchange
      ✔ 1: Sends a second HEADERS frame without the END_STREAM flag

      8.1.2. HTTP Header Fields
        ✔ 1: Sends a HEADERS frame that contains the header field name in uppercase letters

        8.1.2.1. Pseudo-Header Fields
          ✔ 1: Sends a HEADERS frame that contains a unknown pseudo-header field
          ✔ 2: Sends a HEADERS frame that contains the pseudo-header field defined for response
          ✔ 3: Sends a HEADERS frame that contains a pseudo-header field as trailers
          ✔ 4: Sends a HEADERS frame that contains a pseudo-header field that appears in a header block after a regular header field

        8.1.2.2. Connection-Specific Header Fields
          × 1: Sends a HEADERS frame that contains the connection-specific header field
            -> The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.
               Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR)
                         RST_STREAM Frame (Error Code: PROTOCOL_ERROR)
                         Connection closed
                 Actual: DATA Frame (length:51, flags:0x01, stream_id:1)
          × 2: Sends a HEADERS frame that contains the TE header field with any value other than "trailers"
            -> The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.
               Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR)
                         RST_STREAM Frame (Error Code: PROTOCOL_ERROR)
                         Connection closed
                 Actual: DATA Frame (length:53, flags:0x01, stream_id:1)

        8.1.2.3. Request Pseudo-Header Fields
          ✔ 1: Sends a HEADERS frame with empty ":path" pseudo-header field
          ✔ 2: Sends a HEADERS frame that omits ":method" pseudo-header field
          ✔ 3: Sends a HEADERS frame that omits ":scheme" pseudo-header field
          ✔ 4: Sends a HEADERS frame that omits ":path" pseudo-header field
          ✔ 5: Sends a HEADERS frame with duplicated ":method" pseudo-header field
          ✔ 6: Sends a HEADERS frame with duplicated ":scheme" pseudo-header field
          ✔ 7: Sends a HEADERS frame with duplicated ":path" pseudo-header field

        8.1.2.6. Malformed Requests and Responses
          ✔ 1: Sends a HEADERS frame with the "content-length" header field which does not equal the DATA frame payload length
          ✔ 2: Sends a HEADERS frame with the "content-length" header field which does not equal the sum of the multiple DATA frames payload length

    8.2. Server Push
      ✔ 1: Sends a PUSH_PROMISE frame

HPACK: Header Compression for HTTP/2
  2. Compression Process Overview
    2.3. Indexing Tables
      2.3.3. Index Address Space
        ✔ 1: Sends a header field representation with invalid index

  4. Dynamic Table Management
    4.2. Maximum Table Size
      ✔ 1: Sends a dynamic table size update at the end of header block

  5. Primitive Type Representations
    5.2. String Literal Representation
      ✔ 1: Sends a Huffman-encoded string literal representation with padding longer than 7 bits
      ✔ 2: Sends a Huffman-encoded string literal representation padded by zero
      ✔ 3: Sends a Huffman-encoded string literal representation containing the EOS symbol

  6. Binary Format
    6.1. Indexed Header Field Representation
      ✔ 1: Sends a indexed header field representation with index 0

    6.3. Dynamic Table Size Update
      ✔ 1: Sends a dynamic table size update larger than the value of SETTINGS_HEADER_TABLE_SIZE

Failures: 

Hypertext Transfer Protocol Version 2 (HTTP/2)
  4. HTTP Frames
    4.2. Frame Size
      × 3: Sends a large size HEADERS frame that exceeds the SETTINGS_MAX_FRAME_SIZE
        -> The endpoint MUST respond with a connection error of type FRAME_SIZE_ERROR.
           Expected: GOAWAY Frame (Error Code: FRAME_SIZE_ERROR)
                     Connection closed
             Actual: DATA Frame (length:0, flags:0x01, stream_id:1)

  5. Streams and Multiplexing
    5.1. Stream States
      5.1.2. Stream Concurrency
        × 1: Sends HEADERS frames that causes their advertised concurrent stream limit to be exceeded
          -> The endpoint MUST treat this as a stream error of type PROTOCOL_ERROR or REFUSED_STREAM.
             Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR)
                       RST_STREAM Frame (Error Code: PROTOCOL_ERROR)
                       GOAWAY Frame (Error Code: REFUSED_STREAM)
                       RST_STREAM Frame (Error Code: REFUSED_STREAM)
                       Connection closed
               Actual: DATA Frame (length:0, flags:0x01, stream_id:85)

  8. HTTP Message Exchanges
    8.1. HTTP Request/Response Exchange
      8.1.2. HTTP Header Fields
        8.1.2.2. Connection-Specific Header Fields
          × 1: Sends a HEADERS frame that contains the connection-specific header field
            -> The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.
               Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR)
                         RST_STREAM Frame (Error Code: PROTOCOL_ERROR)
                         Connection closed
                 Actual: DATA Frame (length:51, flags:0x01, stream_id:1)
          × 2: Sends a HEADERS frame that contains the TE header field with any value other than "trailers"
            -> The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.
               Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR)
                         RST_STREAM Frame (Error Code: PROTOCOL_ERROR)
                         Connection closed
                 Actual: DATA Frame (length:53, flags:0x01, stream_id:1)

Finished in 13.5771 seconds
145 tests, 137 passed, 4 skipped, 4 failed
@ALTree
Copy link
Member

ALTree commented Apr 24, 2020

Thanks for the report.

Overall it seems that of the 4 violations, one is actually not a violation and for the other 3 we already have specific issues tracking them.

@nfisher
Copy link
Author

nfisher commented Apr 24, 2020

Will close this issue thanks!

@nfisher nfisher closed this as completed Apr 24, 2020
@golang golang locked and limited conversation to collaborators Apr 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants