@@ -2040,25 +2040,26 @@ func (cs *clientStream) waitForTrailerProcessing(recvErr error) error {
20402040
20412041// applyServerWindowUpdate adds a flow control window increment received from
20422042// the external processor to window, waking a blocked acquirer if the window
2043- // becomes positive. The increment is server-controlled, so it must be
2044- // non-negative and must not overflow the int64 window; an increment that
2045- // violates either is a protocol error and returns one instead of wrapping the
2046- // accounting, matching how HTTP/2 flow control rejects a window update that
2047- // exceeds the maximum. This recv loop is the only writer that grows the
2048- // window, so the compare-and-swap only contends with a concurrent deduction in
2043+ // becomes positive. The increment may be negative: the ext_proc spec allows a
2044+ // server to shrink the window, in which case senders block until later
2045+ // updates bring it back above zero. The increment is server-controlled
2046+ // though, so one that would wrap the int64 window in either direction is a
2047+ // protocol error and returns one instead of corrupting the accounting. This
2048+ // recv loop is the only writer that grows the window, so the compare-and-swap
2049+ // only contends with a concurrent deduction in
20492050// acquire{Downstream,Upstream}ToSidestreamWindow.
20502051func applyServerWindowUpdate (window * atomic.Int64 , positiveUpdateCh chan struct {}, delta int64 ) error {
20512052 if delta == 0 {
20522053 return nil
20532054 }
2054- if delta < 0 {
2055- return fmt .Errorf ("negative window increment %d" , delta )
2056- }
20572055 for {
20582056 previousQuota := window .Load ()
2059- if previousQuota > math .MaxInt64 - delta {
2057+ if delta > 0 && previousQuota > math .MaxInt64 - delta {
20602058 return fmt .Errorf ("window increment %d overflows the current window %d" , delta , previousQuota )
20612059 }
2060+ if delta < 0 && previousQuota < math .MinInt64 - delta {
2061+ return fmt .Errorf ("window increment %d underflows the current window %d" , delta , previousQuota )
2062+ }
20622063 newQuota := previousQuota + delta
20632064 if ! window .CompareAndSwap (previousQuota , newQuota ) {
20642065 continue
0 commit comments