Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 5405: Large uploads fill request buffer and die (#1887)
maybeMakeSpaceAvailable: request buffer full ReadNow: ... size 0, retval 0, errno 0 terminateAll: 1/1 after ERR_CLIENT_GONE/WITH_CLIENT %Ss=TCP_MISS_ABORTED This bug is triggered by a combination of the following two conditions: * HTTP client upload fills Squid request buffer faster than it is drained by an origin server, cache_peer, or REQMOD service. The buffer accumulates 576 KB (default 512 KB client_request_buffer_max_size + 64 KB internal "pipe" buffer). * The affected server or service consumes a few bytes after the critical accumulation is reached. In other words, the bug cannot be triggered if nothing is consumed after the first condition above is met. Comm::ReadNow() must not be called with a full buffer: Related FD_READ_METHOD() code cannot distinguish "received EOF" from "had no buffer space" outcomes. Server::readSomeData() tried to prevent such calls, but the corresponding check had two problems: * The check had an unsigned integer underflow bug[^1] that made it ineffective when inBuf length exceeded Config.maxRequestBufferSize. That length could exceed the limit due to reconfiguration and when inBuf space size first grew outside of maybeMakeSpaceAvailable() protections (e.g., during an inBuf.c_str() call) and then got filled with newly read data. That growth started happening after 2020 commit 1dfbca0 optimized SBuf::cow() to merge leading and trailing space. Prior to that commit, Bug 5405 could probably only affect Squid reconfigurations that lower client_request_buffer_max_size. * The check was separated from the ReadNow() call it was meant to protect. While ConnStateData was waiting for the socket to become ready for reading, various asynchronous events could alter inBuf or Config.maxRequestBufferSize. This change fixes both problems. This change also fixes Squid Bug 5214. [^1]: That underflow bug was probably introduced in 2015 commit 4d1376d while trying to emulate the original "do not read less than two bytes" ConnStateData::In::maybeMakeSpaceAvailable() condition. That condition itself looks like a leftover from manual zero-terminated input buffer days that ended with 2014 commit e728762. It is now removed.
- Loading branch information