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) {