This is an automated email from the ASF dual-hosted git repository.

cmcfarlen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new c0351de280 Avoid stale H2 writes after 100 Continue (#13504)
c0351de280 is described below

commit c0351de28011cbbb54597cd5ce564344e7ac6642
Author: Brian Neradt <[email protected]>
AuthorDate: Fri Aug 7 12:14:09 2026 -0500

    Avoid stale H2 writes after 100 Continue (#13504)
    
    HttpSM owns the write buffer attached to an HTTP/2 stream. After
    WRITE_COMPLETE it may release the buffer while a connection-level
    write-ready event can restart the stream through the non-owning
    _send_reader alias. This leaves restart_sending vulnerable to a
    use-after-free.
    
    Clear _send_reader before delivering WRITE_COMPLETE to HttpSM, and
    check completed write VIOs before inspecting the reader during
    connection restarts. This preserves zero-byte completion processing,
    including END_STREAM.
    
    Co-authored-by: bneradt <[email protected]>
---
 src/proxy/http2/Http2Stream.cc | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/proxy/http2/Http2Stream.cc b/src/proxy/http2/Http2Stream.cc
index 6be67db03b..611e8b6a4e 100644
--- a/src/proxy/http2/Http2Stream.cc
+++ b/src/proxy/http2/Http2Stream.cc
@@ -807,12 +807,12 @@ Http2Stream::restart_sending()
     }
   }
 
-  IOBufferReader *reader = this->get_data_reader_for_send();
-  if (reader && !reader->is_read_avail_more_than(0)) {
+  if (this->write_vio.mutex && this->write_vio.ntodo() <= 0) {
     return;
   }
 
-  if (this->write_vio.mutex && this->write_vio.ntodo() == 0) {
+  IOBufferReader *reader = this->get_data_reader_for_send();
+  if (reader && !reader->is_read_avail_more_than(0)) {
     return;
   }
 
@@ -970,6 +970,11 @@ Http2Stream::signal_write_event(int event, bool 
call_update)
         write_event = nullptr;
       }
       _timeout.update_inactivity();
+      if (event == VC_EVENT_WRITE_COMPLETE) {
+        // HttpSM owns the write buffer and may release it while handling this
+        // event. Drop the unowned alias before transferring control.
+        _send_reader = nullptr;
+      }
       this->write_vio.cont->handleEvent(event, &this->write_vio);
     } else {
       if (this->_write_vio_event) {

Reply via email to