-
Dridi Boukelmoune authored
When we take on a new request on a connection from which something was already received, we need to pipeline it and we do so at the beginning of the request workspace. There's a high probability that the pipeline is coming from the same workspace, which is a form of use-after-free only made safe by the workspace implementation details. To avoid the conceptual use-after-free, we defer req workspace rollbacks and perform them during the next HTC_RxInit() call before the pipelining operation. Because HTTP/1 works directly on the session, a worker can safely switch back and forth between sess and req tasks. This means that unless the session goes idle the same workspace is used from one client request to the next, hence the rollback previously happening in Req_Cleanup(). With h2 however there is a disconnect between the session and streams. The connection is received in req0's workspace, and then copied into a stream's req workspace via the pipelining scheme. Rollbacks can be deferred as well, but they need to happen otherwise the session will soon overflow. Independent HTC_RxInit() calls happen for req0 in the h2 session thread, and for h2 streams in the regular request task code path. PROXY Protocol parsing may result in receiving more than the proxy preamble itself and pipelining will happen, whether it is via a req for HTTP/1 or req0 for h2. On the other end of the spectrum when Varnish acts as a client it only sends one HTTP/1 request at a time for a given connection, so we never expect pipelining to occur in fetch task.
5b4f0f1a