diff options
Diffstat (limited to 'vendor/golang.org/x/net/http2')
| -rw-r--r-- | vendor/golang.org/x/net/http2/flow.go | 2 | ||||
| -rw-r--r-- | vendor/golang.org/x/net/http2/frame.go | 11 | ||||
| -rw-r--r-- | vendor/golang.org/x/net/http2/hpack/hpack.go | 81 | ||||
| -rw-r--r-- | vendor/golang.org/x/net/http2/server.go | 20 | ||||
| -rw-r--r-- | vendor/golang.org/x/net/http2/transport.go | 2 | 
5 files changed, 78 insertions, 38 deletions
| diff --git a/vendor/golang.org/x/net/http2/flow.go b/vendor/golang.org/x/net/http2/flow.go index 750ac52f2..b7dbd1869 100644 --- a/vendor/golang.org/x/net/http2/flow.go +++ b/vendor/golang.org/x/net/http2/flow.go @@ -18,7 +18,7 @@ type inflow struct {  	unsent int32  } -// set sets the initial window. +// init sets the initial window.  func (f *inflow) init(n int32) {  	f.avail = n  } diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go index 184ac45fe..c1f6b90dc 100644 --- a/vendor/golang.org/x/net/http2/frame.go +++ b/vendor/golang.org/x/net/http2/frame.go @@ -662,6 +662,15 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {  // It is the caller's responsibility not to violate the maximum frame size  // and to not call other Write methods concurrently.  func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error { +	if err := f.startWriteDataPadded(streamID, endStream, data, pad); err != nil { +		return err +	} +	return f.endWrite() +} + +// startWriteDataPadded is WriteDataPadded, but only writes the frame to the Framer's internal buffer. +// The caller should call endWrite to flush the frame to the underlying writer. +func (f *Framer) startWriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {  	if !validStreamID(streamID) && !f.AllowIllegalWrites {  		return errStreamID  	} @@ -691,7 +700,7 @@ func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []by  	}  	f.wbuf = append(f.wbuf, data...)  	f.wbuf = append(f.wbuf, pad...) -	return f.endWrite() +	return nil  }  // A SettingsFrame conveys configuration parameters that affect how diff --git a/vendor/golang.org/x/net/http2/hpack/hpack.go b/vendor/golang.org/x/net/http2/hpack/hpack.go index ebdfbee96..7a1d97669 100644 --- a/vendor/golang.org/x/net/http2/hpack/hpack.go +++ b/vendor/golang.org/x/net/http2/hpack/hpack.go @@ -211,7 +211,7 @@ func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {  	return dt.ents[dt.len()-(int(i)-staticTable.len())], true  } -// Decode decodes an entire block. +// DecodeFull decodes an entire block.  //  // TODO: remove this method and make it incremental later? This is  // easier for debugging now. @@ -359,6 +359,7 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {  	var hf HeaderField  	wantStr := d.emitEnabled || it.indexed() +	var undecodedName undecodedString  	if nameIdx > 0 {  		ihf, ok := d.at(nameIdx)  		if !ok { @@ -366,15 +367,27 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {  		}  		hf.Name = ihf.Name  	} else { -		hf.Name, buf, err = d.readString(buf, wantStr) +		undecodedName, buf, err = d.readString(buf)  		if err != nil {  			return err  		}  	} -	hf.Value, buf, err = d.readString(buf, wantStr) +	undecodedValue, buf, err := d.readString(buf)  	if err != nil {  		return err  	} +	if wantStr { +		if nameIdx <= 0 { +			hf.Name, err = d.decodeString(undecodedName) +			if err != nil { +				return err +			} +		} +		hf.Value, err = d.decodeString(undecodedValue) +		if err != nil { +			return err +		} +	}  	d.buf = buf  	if it.indexed() {  		d.dynTab.add(hf) @@ -459,46 +472,52 @@ func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {  	return 0, origP, errNeedMore  } -// readString decodes an hpack string from p. +// readString reads an hpack string from p.  // -// wantStr is whether s will be used. If false, decompression and -// []byte->string garbage are skipped if s will be ignored -// anyway. This does mean that huffman decoding errors for non-indexed -// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server -// is returning an error anyway, and because they're not indexed, the error -// won't affect the decoding state. -func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) { +// It returns a reference to the encoded string data to permit deferring decode costs +// until after the caller verifies all data is present. +func (d *Decoder) readString(p []byte) (u undecodedString, remain []byte, err error) {  	if len(p) == 0 { -		return "", p, errNeedMore +		return u, p, errNeedMore  	}  	isHuff := p[0]&128 != 0  	strLen, p, err := readVarInt(7, p)  	if err != nil { -		return "", p, err +		return u, p, err  	}  	if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) { -		return "", nil, ErrStringLength +		// Returning an error here means Huffman decoding errors +		// for non-indexed strings past the maximum string length +		// are ignored, but the server is returning an error anyway +		// and because the string is not indexed the error will not +		// affect the decoding state. +		return u, nil, ErrStringLength  	}  	if uint64(len(p)) < strLen { -		return "", p, errNeedMore -	} -	if !isHuff { -		if wantStr { -			s = string(p[:strLen]) -		} -		return s, p[strLen:], nil +		return u, p, errNeedMore  	} +	u.isHuff = isHuff +	u.b = p[:strLen] +	return u, p[strLen:], nil +} -	if wantStr { -		buf := bufPool.Get().(*bytes.Buffer) -		buf.Reset() // don't trust others -		defer bufPool.Put(buf) -		if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil { -			buf.Reset() -			return "", nil, err -		} +type undecodedString struct { +	isHuff bool +	b      []byte +} + +func (d *Decoder) decodeString(u undecodedString) (string, error) { +	if !u.isHuff { +		return string(u.b), nil +	} +	buf := bufPool.Get().(*bytes.Buffer) +	buf.Reset() // don't trust others +	var s string +	err := huffmanDecode(buf, d.maxStrLen, u.b) +	if err == nil {  		s = buf.String() -		buf.Reset() // be nice to GC  	} -	return s, p[strLen:], nil +	buf.Reset() // be nice to GC +	bufPool.Put(buf) +	return s, err  } diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index b624dc0a7..8cb14f3c9 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -843,8 +843,13 @@ type frameWriteResult struct {  // and then reports when it's done.  // At most one goroutine can be running writeFrameAsync at a time per  // serverConn. -func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) { -	err := wr.write.writeFrame(sc) +func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) { +	var err error +	if wd == nil { +		err = wr.write.writeFrame(sc) +	} else { +		err = sc.framer.endWrite() +	}  	sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err}  } @@ -1251,9 +1256,16 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {  		sc.writingFrameAsync = false  		err := wr.write.writeFrame(sc)  		sc.wroteFrame(frameWriteResult{wr: wr, err: err}) +	} else if wd, ok := wr.write.(*writeData); ok { +		// Encode the frame in the serve goroutine, to ensure we don't have +		// any lingering asynchronous references to data passed to Write. +		// See https://go.dev/issue/58446. +		sc.framer.startWriteDataPadded(wd.streamID, wd.endStream, wd.p, nil) +		sc.writingFrameAsync = true +		go sc.writeFrameAsync(wr, wd)  	} else {  		sc.writingFrameAsync = true -		go sc.writeFrameAsync(wr) +		go sc.writeFrameAsync(wr, nil)  	}  } @@ -2192,7 +2204,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r  		tlsState = sc.tlsState  	} -	needsContinue := rp.header.Get("Expect") == "100-continue" +	needsContinue := httpguts.HeaderValuesContainsToken(rp.header["Expect"], "100-continue")  	if needsContinue {  		rp.header.Del("Expect")  	} diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index b43ec10cf..05ba23d3d 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -1569,7 +1569,7 @@ func (cs *clientStream) cleanupWriteRequest(err error) {  	close(cs.donec)  } -// awaitOpenSlotForStream waits until len(streams) < maxConcurrentStreams. +// awaitOpenSlotForStreamLocked waits until len(streams) < maxConcurrentStreams.  // Must hold cc.mu.  func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error {  	for { | 
