@ttsc/darwin-x64 0.32.1 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/bin/go/VERSION +2 -2
  2. package/bin/go/bin/go +0 -0
  3. package/bin/go/bin/gofmt +0 -0
  4. package/bin/go/pkg/tool/darwin_amd64/asm +0 -0
  5. package/bin/go/pkg/tool/darwin_amd64/cgo +0 -0
  6. package/bin/go/pkg/tool/darwin_amd64/compile +0 -0
  7. package/bin/go/pkg/tool/darwin_amd64/cover +0 -0
  8. package/bin/go/pkg/tool/darwin_amd64/fix +0 -0
  9. package/bin/go/pkg/tool/darwin_amd64/link +0 -0
  10. package/bin/go/pkg/tool/darwin_amd64/preprofile +0 -0
  11. package/bin/go/pkg/tool/darwin_amd64/vet +0 -0
  12. package/bin/go/src/crypto/internal/fips140/mlkem/cast.go +66 -36
  13. package/bin/go/src/crypto/internal/fips140/mlkem/mlkem768.go +6 -0
  14. package/bin/go/src/crypto/tls/ech.go +18 -4
  15. package/bin/go/src/go.mod +1 -1
  16. package/bin/go/src/go.sum +2 -2
  17. package/bin/go/src/html/template/js.go +8 -3
  18. package/bin/go/src/html/template/transition.go +8 -1
  19. package/bin/go/src/internal/buildcfg/zbootstrap.go +1 -1
  20. package/bin/go/src/internal/godebugs/table.go +1 -0
  21. package/bin/go/src/internal/poll/fd_windows.go +21 -1
  22. package/bin/go/src/internal/runtime/syscall/linux/defs_linux_arm.go +3 -3
  23. package/bin/go/src/internal/runtime/syscall/linux/defs_linux_arm64.go +3 -3
  24. package/bin/go/src/internal/runtime/syscall/linux/defs_linux_loong64.go +2 -2
  25. package/bin/go/src/internal/runtime/syscall/linux/defs_linux_mips64x.go +2 -2
  26. package/bin/go/src/internal/runtime/syscall/linux/defs_linux_mipsx.go +1 -1
  27. package/bin/go/src/internal/runtime/syscall/linux/defs_linux_ppc64x.go +2 -2
  28. package/bin/go/src/internal/runtime/syscall/linux/defs_linux_riscv64.go +2 -2
  29. package/bin/go/src/internal/runtime/syscall/linux/defs_linux_s390x.go +2 -2
  30. package/bin/go/src/internal/syscall/windows/at_windows.go +91 -15
  31. package/bin/go/src/internal/syscall/windows/types_windows.go +8 -1
  32. package/bin/go/src/mime/multipart/formdata.go +4 -5
  33. package/bin/go/src/net/http/fs.go +28 -0
  34. package/bin/go/src/net/http/h2_bundle.go +278 -133
  35. package/bin/go/src/net/http/httputil/reverseproxy.go +15 -0
  36. package/bin/go/src/net/http/server.go +23 -3
  37. package/bin/go/src/net/http/transport.go +6 -1
  38. package/bin/go/src/net/textproto/reader.go +9 -7
  39. package/bin/go/src/os/file_windows.go +7 -3
  40. package/bin/go/src/os/root_openat.go +5 -5
  41. package/bin/go/src/os/root_unix.go +4 -0
  42. package/bin/go/src/os/root_windows.go +8 -2
  43. package/bin/go/src/runtime/metrics/doc.go +5 -0
  44. package/bin/go/src/runtime/netpoll_epoll.go +20 -7
  45. package/bin/go/src/runtime/os_windows.go +23 -0
  46. package/bin/go/src/vendor/modules.txt +1 -1
  47. package/bin/ttsc +0 -0
  48. package/bin/ttsc-cache +0 -0
  49. package/bin/ttscserver +0 -0
  50. package/package.json +2 -1
@@ -41,6 +41,7 @@ import (
41
41
  "os"
42
42
  "reflect"
43
43
  "runtime"
44
+ "slices"
44
45
  "sort"
45
46
  "strconv"
46
47
  "strings"
@@ -1472,6 +1473,9 @@ var (
1472
1473
  // flow control window update.
1473
1474
  const http2inflowMinRefresh = 4 << 10
1474
1475
 
1476
+ // maxFlowWindow is the maximum size of a flow control window.
1477
+ const http2maxFlowWindow = (1 << 31) - 1
1478
+
1475
1479
  // inflow accounts for an inbound flow control window.
1476
1480
  // It tracks both the latest window sent to the peer (used for enforcement)
1477
1481
  // and the accumulated unsent window.
@@ -1536,49 +1540,101 @@ func http2takeInflows(f1, f2 *http2inflow, n uint32) bool {
1536
1540
  return true
1537
1541
  }
1538
1542
 
1539
- // outflow is the outbound flow control window's size.
1543
+ // connOutflow is connection-level outbound flow control.
1544
+ type http2connOutflow struct {
1545
+ initial int32 // SETTINGS_INITIAL_WINDOW_SIZE, changes with settings updates
1546
+ n int32 // connection-level flow control window
1547
+ flowErr bool // set when a flow control error is encountered
1548
+ }
1549
+
1550
+ func (f *http2connOutflow) init() {
1551
+ f.initial = http2initialWindowSize // initial stream window size
1552
+ f.n = http2initialWindowSize // current connection window size
1553
+ }
1554
+
1555
+ func (f *http2connOutflow) changeInitialWindowSize(size int64) bool {
1556
+ if size > http2maxFlowWindow {
1557
+ f.flowErr = true
1558
+ return false
1559
+ }
1560
+ f.initial = int32(size)
1561
+ return true
1562
+ }
1563
+
1564
+ func (f *http2connOutflow) add(n int32) bool {
1565
+ sum := int64(f.n) + int64(n)
1566
+ if sum > http2maxFlowWindow {
1567
+ f.flowErr = true
1568
+ return false
1569
+ }
1570
+ f.n += n
1571
+ return true
1572
+ }
1573
+
1574
+ // outflow is the stream-level outbound flow control window's size.
1540
1575
  type http2outflow struct {
1541
1576
  _ http2incomparable
1542
1577
 
1543
- // n is the number of DATA bytes we're allowed to send.
1544
- // An outflow is kept both on a conn and a per-stream.
1545
- n int32
1578
+ // delta is the difference between the stream's flow control window and
1579
+ // the connection's initial window size (conn.initial).
1580
+ //
1581
+ // Another view is that delta is the number of flow control bytes provided to this
1582
+ // stream in WINDOW_UPDATE frames, less the number of bytes sent on the stream.
1583
+ delta int32
1546
1584
 
1547
1585
  // conn points to the shared connection-level outflow that is
1548
- // shared by all streams on that conn. It is nil for the outflow
1549
- // that's on the conn directly.
1550
- conn *http2outflow
1586
+ // shared by all streams on that conn.
1587
+ conn *http2connOutflow
1551
1588
  }
1552
1589
 
1553
- func (f *http2outflow) setConnFlow(cf *http2outflow) { f.conn = cf }
1554
-
1555
- func (f *http2outflow) available() int32 {
1556
- n := f.n
1557
- if f.conn != nil && f.conn.n < n {
1558
- n = f.conn.n
1590
+ func (f *http2outflow) available() (int32, bool) {
1591
+ if f.conn == nil {
1592
+ return http2maxFlowWindow, true // only happens in tests
1559
1593
  }
1560
- return n
1594
+ if f.conn.flowErr {
1595
+ // Block all sending once any stream observes a flow control error.
1596
+ return 0, false
1597
+ }
1598
+ n := int64(f.conn.initial) + int64(f.delta)
1599
+ if n > http2maxFlowWindow {
1600
+ f.conn.flowErr = true
1601
+ return 0, false
1602
+ }
1603
+ return min(int32(n), f.conn.n), true
1561
1604
  }
1562
1605
 
1563
1606
  func (f *http2outflow) take(n int32) {
1564
- if n > f.available() {
1565
- panic("internal error: took too much")
1607
+ if f.conn == nil {
1608
+ return // only happens in tests
1566
1609
  }
1567
- f.n -= n
1568
- if f.conn != nil {
1569
- f.conn.n -= n
1610
+ avail, _ := f.available()
1611
+ if n > avail {
1612
+ panic("internal error: took too much")
1570
1613
  }
1614
+ f.delta -= n
1615
+ f.conn.n -= n
1571
1616
  }
1572
1617
 
1573
1618
  // add adds n bytes (positive or negative) to the flow control window.
1574
1619
  // It returns false if the sum would exceed 2^31-1.
1575
1620
  func (f *http2outflow) add(n int32) bool {
1576
- sum := f.n + n
1577
- if (sum > n) == (f.n > 0) {
1578
- f.n = sum
1579
- return true
1621
+ if f.conn == nil {
1622
+ return true // only happens in tests
1623
+ }
1624
+ avail := int64(f.conn.initial) + int64(f.delta)
1625
+ if avail > http2maxFlowWindow {
1626
+ // An earlier change to the initial window pushed this stream over the limit.
1627
+ // This is a connection-level flow control error.
1628
+ f.conn.flowErr = true
1629
+ return false
1580
1630
  }
1581
- return false
1631
+ if avail+int64(n) > http2maxFlowWindow {
1632
+ // This update would push the stream over the limit.
1633
+ // This is a stream-level flow control error.
1634
+ return false
1635
+ }
1636
+ f.delta += n
1637
+ return true
1582
1638
  }
1583
1639
 
1584
1640
  const http2frameHeaderLen = 9
@@ -3159,7 +3215,8 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (http2Frame, error)
3159
3215
  mh := &http2MetaHeadersFrame{
3160
3216
  http2HeadersFrame: hf,
3161
3217
  }
3162
- var remainSize = fr.maxHeaderListSize()
3218
+ var headersRemainSize = fr.maxHeaderListSize()
3219
+ var trailersRemainSize = fr.maxHeaderListSize()
3163
3220
  var sawRegular bool
3164
3221
 
3165
3222
  var invalid error // pseudo header field errors
@@ -3191,14 +3248,29 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (http2Frame, error)
3191
3248
  return
3192
3249
  }
3193
3250
 
3194
- size := hf.Size()
3195
- if size > remainSize {
3251
+ var remainSize *uint32
3252
+ var size uint32
3253
+ if hf.Name == "trailer" {
3254
+ remainSize = &trailersRemainSize
3255
+ fieldCount := strings.Count(hf.Value, ",") + 1
3256
+ // Rather than actually constructing hpack.HeaderField for each
3257
+ // trailer field and cumulatively adding its Size, just do the math
3258
+ // manually to avoid unnecessary work. This does make it so
3259
+ // whitespaces after comma are counted against the budget, but that
3260
+ // should be innocuous.
3261
+ size = uint32(len(hf.Value)-fieldCount+1) + uint32(fieldCount)*hpack.HeaderField{}.Size()
3262
+ } else {
3263
+ remainSize = &headersRemainSize
3264
+ size = hf.Size()
3265
+ }
3266
+ if size > *remainSize {
3196
3267
  hdec.SetEmitEnabled(false)
3197
3268
  mh.Truncated = true
3198
- remainSize = 0
3269
+ headersRemainSize = 0
3270
+ trailersRemainSize = 0
3199
3271
  return
3200
3272
  }
3201
- remainSize -= size
3273
+ *remainSize -= size
3202
3274
 
3203
3275
  mh.Fields = append(mh.Fields, hf)
3204
3276
  })
@@ -3214,10 +3286,10 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (http2Frame, error)
3214
3286
  // skip parsing the fragment and close the connection.
3215
3287
  //
3216
3288
  // "Too much" is either any CONTINUATION frame after we've already
3217
- // exceeded the max header list size (in which case remainSize is 0),
3218
- // or a frame whose encoded size is more than twice the remaining
3219
- // header list bytes we're willing to accept.
3220
- if int64(len(frag)) > int64(2*remainSize) {
3289
+ // exceeded the max header list size (if so, both budgets are 0), or a
3290
+ // frame whose encoded size is more than twice the remaining header
3291
+ // list bytes we're willing to accept.
3292
+ if int64(len(frag)) > 2*int64(headersRemainSize+trailersRemainSize) {
3221
3293
  if http2VerboseLogs {
3222
3294
  log.Printf("http2: header list too large")
3223
3295
  }
@@ -4429,7 +4501,6 @@ func (s *http2Server) serveConn(c net.Conn, opts *http2ServeConnOpts, newf func(
4429
4501
  doneServing: make(chan struct{}),
4430
4502
  clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
4431
4503
  advMaxStreams: conf.MaxConcurrentStreams,
4432
- initialStreamSendWindowSize: http2initialWindowSize,
4433
4504
  initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream,
4434
4505
  maxFrameSize: http2initialMaxFrameSize,
4435
4506
  pingTimeout: conf.PingTimeout,
@@ -4463,7 +4534,7 @@ func (s *http2Server) serveConn(c net.Conn, opts *http2ServeConnOpts, newf func(
4463
4534
  // These start at the RFC-specified defaults. If there is a higher
4464
4535
  // configured value for inflow, that will be updated when we send a
4465
4536
  // WINDOW_UPDATE shortly after sending SETTINGS.
4466
- sc.flow.add(http2initialWindowSize)
4537
+ sc.flow.init()
4467
4538
  sc.inflow.init(http2initialWindowSize)
4468
4539
  sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
4469
4540
  sc.hpackEncoder.SetMaxDynamicTableSizeLimit(conf.MaxEncoderHeaderTableSize)
@@ -4579,7 +4650,7 @@ type http2serverConn struct {
4579
4650
  wroteFrameCh chan http2frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
4580
4651
  bodyReadCh chan http2bodyReadMsg // from handlers -> serve
4581
4652
  serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
4582
- flow http2outflow // conn-wide (not stream-specific) outbound flow control
4653
+ flow http2connOutflow // conn-wide (not stream-specific) outbound flow control
4583
4654
  inflow http2inflow // conn-wide inbound flow control
4584
4655
  tlsState *tls.ConnectionState // shared by all handlers, like net/http
4585
4656
  remoteAddrStr string
@@ -4593,6 +4664,9 @@ type http2serverConn struct {
4593
4664
  sawFirstSettings bool // got the initial SETTINGS frame after the preface
4594
4665
  needToSendSettingsAck bool
4595
4666
  unackedSettings int // how many SETTINGS have we sent without ACKs?
4667
+ pendingEncoderTableSize bool // peer changed SETTINGS_HEADER_TABLE_SIZE; apply to hpackEncoder before the next frame write
4668
+ encoderTableSizeMin uint32 // smallest SETTINGS_HEADER_TABLE_SIZE since the last apply
4669
+ encoderTableSize uint32 // latest SETTINGS_HEADER_TABLE_SIZE
4596
4670
  queuedControlFrames int // control frames in the writeSched queue
4597
4671
  clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
4598
4672
  advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
@@ -4603,7 +4677,6 @@ type http2serverConn struct {
4603
4677
  maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
4604
4678
  streams map[uint32]*http2stream
4605
4679
  unstartedHandlers []http2unstartedHandler
4606
- initialStreamSendWindowSize int32
4607
4680
  initialStreamRecvWindowSize int32
4608
4681
  maxFrameSize int32
4609
4682
  peerMaxHeaderListSize uint32 // zero means unknown (default)
@@ -4656,7 +4729,8 @@ type http2stream struct {
4656
4729
  // immutable:
4657
4730
  sc *http2serverConn
4658
4731
  id uint32
4659
- body *http2pipe // non-nil if expecting DATA frames
4732
+ body *http2pipe // non-nil if expecting DATA frames
4733
+ reqBody *http2requestBody
4660
4734
  cw http2closeWaiter // closed wait stream transitions to closed state
4661
4735
  ctx context.Context
4662
4736
  cancelCtx func()
@@ -5310,6 +5384,16 @@ func (sc *http2serverConn) startFrameWrite(wr http2FrameWriteRequest) {
5310
5384
 
5311
5385
  sc.writingFrame = true
5312
5386
  sc.needsFrameFlush = true
5387
+ if sc.pendingEncoderTableSize {
5388
+ // hpackEncoder may be in use by writeFrameAsync, so SETTINGS
5389
+ // changes to it are deferred until no frame is being written.
5390
+ // Replaying the smallest size before the latest one keeps the
5391
+ // encoder's view identical to having applied every change
5392
+ // (RFC 7541, Section 4.2).
5393
+ sc.pendingEncoderTableSize = false
5394
+ sc.hpackEncoder.SetMaxDynamicTableSize(sc.encoderTableSizeMin)
5395
+ sc.hpackEncoder.SetMaxDynamicTableSize(sc.encoderTableSize)
5396
+ }
5313
5397
  if wr.write.staysWithinBuffer(sc.bw.Available()) {
5314
5398
  sc.writingFrameAsync = false
5315
5399
  err := wr.write.writeFrame(sc)
@@ -5409,6 +5493,11 @@ func (sc *http2serverConn) scheduleFrameWrite() {
5409
5493
  }
5410
5494
  sc.inFrameScheduleLoop = true
5411
5495
  for !sc.writingFrameAsync {
5496
+ if sc.flow.flowErr && (!sc.inGoAway || sc.goAwayCode == http2ErrCodeNo) {
5497
+ sc.inGoAway = true
5498
+ sc.needToSendGoAway = true
5499
+ sc.goAwayCode = http2ErrCodeFlowControl
5500
+ }
5412
5501
  if sc.needToSendGoAway {
5413
5502
  sc.needToSendGoAway = false
5414
5503
  sc.startFrameWrite(http2FrameWriteRequest{
@@ -5432,6 +5521,9 @@ func (sc *http2serverConn) scheduleFrameWrite() {
5432
5521
  sc.startFrameWrite(wr)
5433
5522
  continue
5434
5523
  }
5524
+ if sc.flow.flowErr {
5525
+ continue
5526
+ }
5435
5527
  }
5436
5528
  if sc.needsFrameFlush {
5437
5529
  sc.startFrameWrite(http2FrameWriteRequest{write: http2flushFrameWriter{}})
@@ -5662,6 +5754,10 @@ func (sc *http2serverConn) processWindowUpdate(f *http2WindowUpdateFrame) error
5662
5754
  return nil
5663
5755
  }
5664
5756
  if !st.flow.add(int32(f.Increment)) {
5757
+ if st.flow.conn.flowErr {
5758
+ // This is a lazily-detected connection-level flow control error.
5759
+ return sc.countError("bad_flow", http2ConnectionError(http2ErrCodeFlowControl))
5760
+ }
5665
5761
  return sc.countError("bad_flow", http2streamError(f.StreamID, http2ErrCodeFlowControl))
5666
5762
  }
5667
5763
  default: // connection-level flow control
@@ -5720,10 +5816,6 @@ func (sc *http2serverConn) closeStream(st *http2stream, err error) {
5720
5816
  }
5721
5817
  }
5722
5818
  if p := st.body; p != nil {
5723
- // Return any buffered unread bytes worth of conn-level flow control.
5724
- // See golang.org/issue/16481
5725
- sc.sendWindowUpdate(nil, p.Len())
5726
-
5727
5819
  p.CloseWithError(err)
5728
5820
  }
5729
5821
  if e, ok := err.(http2StreamError); ok {
@@ -5777,7 +5869,12 @@ func (sc *http2serverConn) processSetting(s http2Setting) error {
5777
5869
  }
5778
5870
  switch s.ID {
5779
5871
  case http2SettingHeaderTableSize:
5780
- sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
5872
+ // Applied by startFrameWrite; see comment there.
5873
+ if !sc.pendingEncoderTableSize || s.Val < sc.encoderTableSizeMin {
5874
+ sc.encoderTableSizeMin = s.Val
5875
+ }
5876
+ sc.encoderTableSize = s.Val
5877
+ sc.pendingEncoderTableSize = true
5781
5878
  case http2SettingEnablePush:
5782
5879
  sc.pushEnabled = s.Val != 0
5783
5880
  case http2SettingMaxConcurrentStreams:
@@ -5804,28 +5901,14 @@ func (sc *http2serverConn) processSetting(s http2Setting) error {
5804
5901
 
5805
5902
  func (sc *http2serverConn) processSettingInitialWindowSize(val uint32) error {
5806
5903
  sc.serveG.check()
5807
- // Note: val already validated to be within range by
5808
- // processSetting's Valid call.
5809
-
5810
- // "A SETTINGS frame can alter the initial flow control window
5811
- // size for all current streams. When the value of
5812
- // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
5813
- // adjust the size of all stream flow control windows that it
5814
- // maintains by the difference between the new value and the
5815
- // old value."
5816
- old := sc.initialStreamSendWindowSize
5817
- sc.initialStreamSendWindowSize = int32(val)
5818
- growth := int32(val) - old // may be negative
5819
- for _, st := range sc.streams {
5820
- if !st.flow.add(growth) {
5821
- // 6.9.2 Initial Flow Control Window Size
5822
- // "An endpoint MUST treat a change to
5823
- // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
5824
- // control window to exceed the maximum size as a
5825
- // connection error (Section 5.4.1) of type
5826
- // FLOW_CONTROL_ERROR."
5827
- return sc.countError("setting_win_size", http2ConnectionError(http2ErrCodeFlowControl))
5828
- }
5904
+ if !sc.flow.changeInitialWindowSize(int64(val)) {
5905
+ // 6.9.2 Initial Flow Control Window Size
5906
+ // "An endpoint MUST treat a change to
5907
+ // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
5908
+ // control window to exceed the maximum size as a
5909
+ // connection error (Section 5.4.1) of type
5910
+ // FLOW_CONTROL_ERROR."
5911
+ return sc.countError("setting_win_size", http2ConnectionError(http2ErrCodeFlowControl))
5829
5912
  }
5830
5913
  return nil
5831
5914
  }
@@ -6078,7 +6161,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
6078
6161
  if st.reqTrailer != nil {
6079
6162
  st.trailer = make(Header)
6080
6163
  }
6081
- st.body = req.Body.(*http2requestBody).pipe // may be nil
6164
+ st.body = st.reqBody.pipe // may be nil
6082
6165
  st.declBodyBytes = req.ContentLength
6083
6166
 
6084
6167
  handler := sc.handler.ServeHTTP
@@ -6101,7 +6184,7 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
6101
6184
  st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
6102
6185
  }
6103
6186
 
6104
- return sc.scheduleHandler(id, rw, req, handler)
6187
+ return sc.scheduleHandler(st, rw, req, handler)
6105
6188
  }
6106
6189
 
6107
6190
  func (sc *http2serverConn) upgradeRequest(req *Request) {
@@ -6193,7 +6276,6 @@ func (sc *http2serverConn) newStream(id, pusherID uint32, state http2streamState
6193
6276
  }
6194
6277
  st.cw.Init()
6195
6278
  st.flow.conn = &sc.flow // link to conn-level counter
6196
- st.flow.add(sc.initialStreamSendWindowSize)
6197
6279
  st.inflow.init(sc.initialStreamRecvWindowSize)
6198
6280
  if sc.hs.WriteTimeout > 0 {
6199
6281
  st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
@@ -6275,7 +6357,7 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead
6275
6357
  } else {
6276
6358
  req.ContentLength = -1
6277
6359
  }
6278
- req.Body.(*http2requestBody).pipe = &http2pipe{
6360
+ st.reqBody.pipe = &http2pipe{
6279
6361
  b: &http2dataBuffer{expected: req.ContentLength},
6280
6362
  }
6281
6363
  }
@@ -6295,7 +6377,7 @@ func (sc *http2serverConn) newWriterAndRequestNoBody(st *http2stream, rp httpcom
6295
6377
  return nil, nil, sc.countError(res.InvalidReason, http2streamError(st.id, http2ErrCodeProtocol))
6296
6378
  }
6297
6379
 
6298
- body := &http2requestBody{
6380
+ st.reqBody = &http2requestBody{
6299
6381
  conn: sc,
6300
6382
  stream: st,
6301
6383
  needsContinue: res.NeedsContinue,
@@ -6311,7 +6393,7 @@ func (sc *http2serverConn) newWriterAndRequestNoBody(st *http2stream, rp httpcom
6311
6393
  ProtoMinor: 0,
6312
6394
  TLS: tlsState,
6313
6395
  Host: rp.Authority,
6314
- Body: body,
6396
+ Body: st.reqBody,
6315
6397
  Trailer: res.Trailer,
6316
6398
  }).WithContext(st.ctx)
6317
6399
  rw := sc.newResponseWriter(st, req)
@@ -6335,11 +6417,12 @@ type http2unstartedHandler struct {
6335
6417
  rw *http2responseWriter
6336
6418
  req *Request
6337
6419
  handler func(ResponseWriter, *Request)
6420
+ body *http2pipe
6338
6421
  }
6339
6422
 
6340
6423
  // scheduleHandler starts a handler goroutine,
6341
6424
  // or schedules one to start as soon as an existing handler finishes.
6342
- func (sc *http2serverConn) scheduleHandler(streamID uint32, rw *http2responseWriter, req *Request, handler func(ResponseWriter, *Request)) error {
6425
+ func (sc *http2serverConn) scheduleHandler(st *http2stream, rw *http2responseWriter, req *Request, handler func(ResponseWriter, *Request)) error {
6343
6426
  sc.serveG.check()
6344
6427
  maxHandlers := sc.advMaxStreams
6345
6428
  if sc.curHandlers < maxHandlers {
@@ -6351,10 +6434,11 @@ func (sc *http2serverConn) scheduleHandler(streamID uint32, rw *http2responseWri
6351
6434
  return sc.countError("too_many_early_resets", http2ConnectionError(http2ErrCodeEnhanceYourCalm))
6352
6435
  }
6353
6436
  sc.unstartedHandlers = append(sc.unstartedHandlers, http2unstartedHandler{
6354
- streamID: streamID,
6437
+ streamID: st.id,
6355
6438
  rw: rw,
6356
6439
  req: req,
6357
6440
  handler: handler,
6441
+ body: st.body,
6358
6442
  })
6359
6443
  return nil
6360
6444
  }
@@ -6368,6 +6452,10 @@ func (sc *http2serverConn) handlerDone() {
6368
6452
  u := sc.unstartedHandlers[i]
6369
6453
  if sc.streams[u.streamID] == nil {
6370
6454
  // This stream was reset before its goroutine had a chance to start.
6455
+ if u.body != nil {
6456
+ u.body.BreakWithError(http2errClosedBody)
6457
+ sc.sendWindowUpdate(nil, u.body.Len())
6458
+ }
6371
6459
  continue
6372
6460
  }
6373
6461
  if sc.curHandlers >= maxHandlers {
@@ -6389,6 +6477,12 @@ func (sc *http2serverConn) runHandler(rw *http2responseWriter, req *Request, han
6389
6477
  didPanic := true
6390
6478
  defer func() {
6391
6479
  rw.rws.stream.cancelCtx()
6480
+ if b := rw.rws.stream.reqBody; b != nil {
6481
+ // Closing the body refunds flow control credit for any unconsumed data.
6482
+ // (reqBody is nil for Upgrade: h2c requests, but those do not use flow
6483
+ // control for the request body.)
6484
+ b.Close()
6485
+ }
6392
6486
  if req.MultipartForm != nil {
6393
6487
  req.MultipartForm.RemoveAll()
6394
6488
  }
@@ -6487,7 +6581,7 @@ func (sc *http2serverConn) noteBodyReadFromHandler(st *http2stream, n int, err e
6487
6581
  func (sc *http2serverConn) noteBodyRead(st *http2stream, n int) {
6488
6582
  sc.serveG.check()
6489
6583
  sc.sendWindowUpdate(nil, n) // conn-level
6490
- if st.state != http2stateHalfClosedRemote && st.state != http2stateClosed {
6584
+ if st != nil && st.state != http2stateHalfClosedRemote && st.state != http2stateClosed {
6491
6585
  // Don't send this WINDOW_UPDATE if the stream is closed
6492
6586
  // remotely.
6493
6587
  sc.sendWindowUpdate(st, n)
@@ -6535,6 +6629,9 @@ func (b *http2requestBody) Close() error {
6535
6629
  b.closeOnce.Do(func() {
6536
6630
  if b.pipe != nil {
6537
6631
  b.pipe.BreakWithError(http2errClosedBody)
6632
+ if unread := b.pipe.Len(); unread > 0 {
6633
+ b.conn.noteBodyReadFromHandler(nil, unread, http2errClosedBody)
6634
+ }
6538
6635
  }
6539
6636
  })
6540
6637
  return nil
@@ -6552,9 +6649,6 @@ func (b *http2requestBody) Read(p []byte) (n int, err error) {
6552
6649
  if err == io.EOF {
6553
6650
  b.sawEOF = true
6554
6651
  }
6555
- if b.conn == nil {
6556
- return
6557
- }
6558
6652
  b.conn.noteBodyReadFromHandler(b.stream, n, err)
6559
6653
  return
6560
6654
  }
@@ -7615,11 +7709,11 @@ type http2ClientConn struct {
7615
7709
  idleTimeout time.Duration // or 0 for never
7616
7710
  idleTimer *time.Timer
7617
7711
 
7618
- mu sync.Mutex // guards following
7619
- cond *sync.Cond // hold mu; broadcast on flow/closed changes
7620
- flow http2outflow // our conn-level flow control quota (cs.outflow is per stream)
7621
- inflow http2inflow // peer's conn-level flow control
7622
- doNotReuse bool // whether conn is marked to not be reused for any future requests
7712
+ mu sync.Mutex // guards following
7713
+ cond *sync.Cond // hold mu; broadcast on flow/closed changes
7714
+ flow http2connOutflow // our conn-level flow control quota (cs.outflow is per stream)
7715
+ inflow http2inflow // peer's conn-level flow control
7716
+ doNotReuse bool // whether conn is marked to not be reused for any future requests
7623
7717
  closing bool
7624
7718
  closed bool
7625
7719
  closedOnIdle bool // true if conn was closed for idleness
@@ -7641,7 +7735,6 @@ type http2ClientConn struct {
7641
7735
  maxConcurrentStreams uint32
7642
7736
  peerMaxHeaderListSize uint64
7643
7737
  peerMaxHeaderTableSize uint32
7644
- initialWindowSize uint32
7645
7738
  initialStreamRecvWindowSize int32
7646
7739
  readIdleTimeout time.Duration
7647
7740
  pingTimeout time.Duration
@@ -8087,7 +8180,6 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool, internalState
8087
8180
  readerDone: make(chan struct{}),
8088
8181
  nextStreamID: 1,
8089
8182
  maxFrameSize: 16 << 10, // spec default
8090
- initialWindowSize: 65535, // spec default
8091
8183
  initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream,
8092
8184
  maxConcurrentStreams: http2initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings.
8093
8185
  strictMaxConcurrentStreams: conf.StrictMaxConcurrentRequests,
@@ -8112,7 +8204,7 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool, internalState
8112
8204
  }
8113
8205
 
8114
8206
  cc.cond = sync.NewCond(&cc.mu)
8115
- cc.flow.add(int32(http2initialWindowSize))
8207
+ cc.flow.init()
8116
8208
 
8117
8209
  // TODO: adjust this writer size to account for frame size +
8118
8210
  // MTU + crypto/tls record padding.
@@ -8529,6 +8621,33 @@ func (cc *http2ClientConn) sendGoAway() error {
8529
8621
  return nil
8530
8622
  }
8531
8623
 
8624
+ func (cc *http2ClientConn) goAwayAndClose(code http2ErrCode) {
8625
+ cc.mu.Lock()
8626
+ closed := cc.closed
8627
+ cc.closing = true
8628
+ cc.closed = true
8629
+ cc.mu.Unlock()
8630
+ if closed {
8631
+ return
8632
+ }
8633
+ if f := cc.fr.countError; f != nil {
8634
+ f(fmt.Sprintf("conn_close_error_%s", code.stringToken()))
8635
+ }
8636
+ done := make(chan struct{})
8637
+ go func() {
8638
+ defer close(done)
8639
+ cc.wmu.Lock()
8640
+ cc.fr.WriteGoAway(0, code, nil)
8641
+ cc.bw.Flush()
8642
+ cc.wmu.Unlock()
8643
+ }()
8644
+ select {
8645
+ case <-done:
8646
+ case <-time.After(250 * time.Millisecond):
8647
+ }
8648
+ cc.closeForError(fmt.Errorf("http2: closing connection with %v", code))
8649
+ }
8650
+
8532
8651
  // closes the client connection immediately. In-flight requests are interrupted.
8533
8652
  // err is sent to streams.
8534
8653
  func (cc *http2ClientConn) closeForError(err error) {
@@ -8975,7 +9094,9 @@ func (cs *http2clientStream) cleanupWriteRequest(err error) {
8975
9094
  }
8976
9095
  if err != nil {
8977
9096
  cs.abortStream(err) // possibly redundant, but harmless
8978
- if cs.sentHeaders {
9097
+ if ce, ok := err.(http2ConnectionError); ok {
9098
+ cc.goAwayAndClose(http2ErrCode(ce))
9099
+ } else if cs.sentHeaders {
8979
9100
  if se, ok := err.(http2StreamError); ok {
8980
9101
  if se.Cause != http2errFromPeer {
8981
9102
  cc.writeStreamReset(cs.ID, se.Code, false, err)
@@ -9305,8 +9426,12 @@ func (cs *http2clientStream) awaitFlowControl(maxBytes int) (taken int32, err er
9305
9426
  return 0, http2errRequestCanceled
9306
9427
  default:
9307
9428
  }
9308
- if a := cs.flow.available(); a > 0 {
9309
- take := a
9429
+ avail, ok := cs.flow.available()
9430
+ if !ok {
9431
+ return 0, http2ConnectionError(http2ErrCodeFlowControl)
9432
+ }
9433
+ if avail > 0 {
9434
+ take := avail
9310
9435
  if int(take) > maxBytes {
9311
9436
 
9312
9437
  take = int32(maxBytes) // can't truncate int; take is int32
@@ -9367,8 +9492,7 @@ type http2resAndError struct {
9367
9492
 
9368
9493
  // requires cc.mu be held.
9369
9494
  func (cc *http2ClientConn) addStreamLocked(cs *http2clientStream) {
9370
- cs.flow.add(int32(cc.initialWindowSize))
9371
- cs.flow.setConnFlow(&cc.flow)
9495
+ cs.flow.conn = &cc.flow
9372
9496
  cs.inflow.init(cc.initialStreamRecvWindowSize)
9373
9497
  cs.ID = cc.nextStreamID
9374
9498
  cc.nextStreamID += 2
@@ -9765,18 +9889,42 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http
9765
9889
  return nil, nil
9766
9890
  }
9767
9891
 
9892
+ // Delete various headers that might mess up framing for HTTP/1. This is
9893
+ // not a problem for HTTP/2, but someone might use HTTP/2 transport as a
9894
+ // reverse proxy which forwards the response to an HTTP/1 client. Our
9895
+ // HTTP/1 client transport will properly reject improper headers such as
9896
+ // multiple conflicting Content-Length headers, but other implementations
9897
+ // might not.
9898
+ // TODO: just reject such responses? We deleted them for compatibility
9899
+ // since this was done in a security fix (go.dev/issue/81115). However,
9900
+ // rejecting them seems entirely reasonable and relatively safe.
9901
+
9902
+ // Connection-specific header fields must not appear in an HTTP/2 message,
9903
+ // and any message containing them is malformed. RFC 9113, Section 8.2.2.
9904
+ for _, k := range http2connHeaders {
9905
+ delete(res.Header, k)
9906
+ }
9768
9907
  res.ContentLength = -1
9769
- if clens := res.Header["Content-Length"]; len(clens) == 1 {
9770
- if cl, err := strconv.ParseUint(clens[0], 10, 63); err == nil {
9771
- res.ContentLength = int64(cl)
9908
+ if clens, ok := res.Header["Content-Length"]; ok {
9909
+ // Repeated Content-Length values may be collapsed into one only if
9910
+ // they are identical per RFC 9110 Section 8.6.
9911
+ // No need to trim whitespace, HTTP/2 header values must not have
9912
+ // extraneous whitespace per RFC 9113 Section 8.2.1.
9913
+ // Non-canonical headers are already rejected by our framer at this
9914
+ // point.
9915
+ conflicting := slices.ContainsFunc(clens[1:], func(clen string) bool {
9916
+ return clen != clens[0]
9917
+ })
9918
+ cl, err := strconv.ParseUint(clens[0], 10, 63)
9919
+ if conflicting || err != nil {
9920
+ delete(res.Header, "Content-Length")
9772
9921
  } else {
9773
- // TODO: care? unlike http/1, it won't mess up our framing, so it's
9774
- // more safe smuggling-wise to ignore.
9922
+ res.Header["Content-Length"] = clens[:1]
9923
+ res.ContentLength = int64(cl)
9775
9924
  }
9776
- } else if len(clens) > 1 {
9777
- // TODO: care? unlike http/1, it won't mess up our framing, so it's
9778
- // more safe smuggling-wise to ignore.
9779
- } else if f.StreamEnded() && !cs.isHead {
9925
+ }
9926
+
9927
+ if res.ContentLength < 0 && f.StreamEnded() && !cs.isHead {
9780
9928
  res.ContentLength = 0
9781
9929
  }
9782
9930
 
@@ -10071,6 +10219,11 @@ func (rl *http2clientConnReadLoop) endStreamError(cs *http2clientStream, err err
10071
10219
  cs.abortStream(err)
10072
10220
  }
10073
10221
 
10222
+ func (rl *http2clientConnReadLoop) endStreamErrorLocked(cs *http2clientStream, err error) {
10223
+ cs.readAborted = true
10224
+ cs.abortStreamLocked(err)
10225
+ }
10226
+
10074
10227
  // Constants passed to streamByID for documentation purposes.
10075
10228
  const (
10076
10229
  http2headerOrDataFrame = true
@@ -10082,6 +10235,10 @@ const (
10082
10235
  func (rl *http2clientConnReadLoop) streamByID(id uint32, headerOrData bool) *http2clientStream {
10083
10236
  rl.cc.mu.Lock()
10084
10237
  defer rl.cc.mu.Unlock()
10238
+ return rl.streamByIDLocked(id, headerOrData)
10239
+ }
10240
+
10241
+ func (rl *http2clientConnReadLoop) streamByIDLocked(id uint32, headerOrData bool) *http2clientStream {
10085
10242
  if headerOrData {
10086
10243
  // Work around an unfortunate gRPC behavior.
10087
10244
  // See comment on ClientConn.rstStreamPingsBlocked for details.
@@ -10164,24 +10321,10 @@ func (rl *http2clientConnReadLoop) processSettingsNoWrite(f *http2SettingsFrame)
10164
10321
  case http2SettingMaxHeaderListSize:
10165
10322
  cc.peerMaxHeaderListSize = uint64(s.Val)
10166
10323
  case http2SettingInitialWindowSize:
10167
- // Values above the maximum flow-control
10168
- // window size of 2^31-1 MUST be treated as a
10169
- // connection error (Section 5.4.1) of type
10170
- // FLOW_CONTROL_ERROR.
10171
- if s.Val > math.MaxInt32 {
10324
+ if !cc.flow.changeInitialWindowSize(int64(s.Val)) {
10172
10325
  return http2ConnectionError(http2ErrCodeFlowControl)
10173
10326
  }
10174
-
10175
- // Adjust flow control of currently-open
10176
- // frames by the difference of the old initial
10177
- // window size and this one.
10178
- delta := int32(s.Val) - int32(cc.initialWindowSize)
10179
- for _, cs := range cc.streams {
10180
- cs.flow.add(delta)
10181
- }
10182
10327
  cc.cond.Broadcast()
10183
-
10184
- cc.initialWindowSize = s.Val
10185
10328
  case http2SettingHeaderTableSize:
10186
10329
  cc.henc.SetMaxDynamicTableSize(s.Val)
10187
10330
  cc.peerMaxHeaderTableSize = s.Val
@@ -10223,29 +10366,30 @@ func (rl *http2clientConnReadLoop) processSettingsNoWrite(f *http2SettingsFrame)
10223
10366
 
10224
10367
  func (rl *http2clientConnReadLoop) processWindowUpdate(f *http2WindowUpdateFrame) error {
10225
10368
  cc := rl.cc
10226
- cs := rl.streamByID(f.StreamID, http2notHeaderOrDataFrame)
10227
- if f.StreamID != 0 && cs == nil {
10228
- return nil
10229
- }
10230
-
10231
10369
  cc.mu.Lock()
10232
10370
  defer cc.mu.Unlock()
10233
-
10234
- fl := &cc.flow
10235
- if cs != nil {
10236
- fl = &cs.flow
10237
- }
10238
- if !fl.add(int32(f.Increment)) {
10239
- // For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR
10240
- if cs != nil {
10241
- rl.endStreamError(cs, http2StreamError{
10371
+ if f.StreamID == 0 {
10372
+ if !cc.flow.add(int32(f.Increment)) {
10373
+ return http2ConnectionError(http2ErrCodeFlowControl)
10374
+ }
10375
+ } else {
10376
+ cs := rl.streamByIDLocked(f.StreamID, http2notHeaderOrDataFrame)
10377
+ if cs == nil {
10378
+ return nil
10379
+ }
10380
+ if !cs.flow.add(int32(f.Increment)) {
10381
+ if cs.flow.conn.flowErr {
10382
+ // This is a lazily-detected connection-level flow control error.
10383
+ return http2ConnectionError(http2ErrCodeFlowControl)
10384
+ }
10385
+ // For stream, the sender sends RST_STREAM with
10386
+ // an error code of FLOW_CONTROL_ERROR.
10387
+ rl.endStreamErrorLocked(cs, http2StreamError{
10242
10388
  StreamID: f.StreamID,
10243
10389
  Code: http2ErrCodeFlowControl,
10244
10390
  })
10245
10391
  return nil
10246
10392
  }
10247
-
10248
- return http2ConnectionError(http2ErrCodeFlowControl)
10249
10393
  }
10250
10394
  cc.cond.Broadcast()
10251
10395
  return nil
@@ -11232,10 +11376,11 @@ func (wr http2FrameWriteRequest) Consume(n int32) (http2FrameWriteRequest, http2
11232
11376
  }
11233
11377
 
11234
11378
  // Might need to split after applying limits.
11235
- allowed := wr.stream.flow.available()
11236
- if n < allowed {
11237
- allowed = n
11379
+ avail, ok := wr.stream.flow.available()
11380
+ if !ok {
11381
+ return empty, empty, 0
11238
11382
  }
11383
+ allowed := min(n, avail)
11239
11384
  if wr.stream.sc.maxFrameSize < allowed {
11240
11385
  allowed = wr.stream.sc.maxFrameSize
11241
11386
  }