#define HELPER_MAX_ARGS 64
-/* size of helper read buffer (maximum?). no reason given for this size */
-/* though it has been seen to be too short for some requests */
-/* it is dynamic, so increasng should not have side effects */
-#define BUF_8KB 8192
+
+/** Initial Squid input buffer size. Helper responses may exceed this, and
+ * Squid will grow the input buffer as needed, up to ReadBufMaxSize.
+ */
+const size_t ReadBufMinSize(4*1024);
+
+/** Maximum safe size of a helper-to-Squid response message plus one.
+ * Squid will warn and close the stream if a helper sends a too-big response.
+ * ssl_crtd helper is known to produce responses of at least 10KB in size.
+ * Some undocumented helpers are known to produce responses exceeding 8KB.
+ */
+const size_t ReadBufMaxSize(32*1024);
static IOCB helperHandleRead;
static IOCB helperStatefulHandleRead;
srv->addr = hlp->addr;
srv->rfd = rfd;
srv->wfd = wfd;
- srv->rbuf = (char *)memAllocBuf(BUF_8KB, &srv->rbuf_sz);
+ srv->rbuf = (char *)memAllocBuf(ReadBufMinSize, &srv->rbuf_sz);
srv->wqueue = new MemBuf;
srv->roffset = 0;
srv->requests = (helper_request **)xcalloc(hlp->concurrency ? hlp->concurrency : 1, sizeof(*srv->requests));
srv->addr = hlp->addr;
srv->rfd = rfd;
srv->wfd = wfd;
- srv->rbuf = (char *)memAllocBuf(BUF_8KB, &srv->rbuf_sz);
+ srv->rbuf = (char *)memAllocBuf(ReadBufMinSize, &srv->rbuf_sz);
srv->roffset = 0;
srv->parent = cbdataReference(hlp);
helperReturnBuffer(i, srv, hlp, msg, t);
}
- if (srv->rfd != -1)
- comm_read(fd, srv->rbuf + srv->roffset, srv->rbuf_sz - srv->roffset - 1, helperHandleRead, srv);
+ if (srv->rfd != -1) {
+ int spaceSize = srv->rbuf_sz - srv->roffset - 1;
+ assert(spaceSize >= 0);
+
+ // grow the input buffer if needed and possible
+ if (!spaceSize && srv->rbuf_sz + 4096 <= ReadBufMaxSize) {
+ srv->rbuf = (char *)memReallocBuf(srv->rbuf, srv->rbuf_sz + 4096, &srv->rbuf_sz);
+ debugs(84, 3, HERE << "Grew read buffer to " << srv->rbuf_sz);
+ spaceSize = srv->rbuf_sz - srv->roffset - 1;
+ assert(spaceSize >= 0);
+ }
+
+ // quit reading if there is no space left
+ if (!spaceSize) {
+ debugs(84, DBG_IMPORTANT, "ERROR: Disconnecting from a " <<
+ "helper that overflowed " << srv->rbuf_sz << "-byte " <<
+ "Squid input buffer: " << hlp->id_name << " #" <<
+ (srv->index + 1));
+ srv->closePipesSafely();
+ return;
+ }
+
+ comm_read(fd, srv->rbuf + srv->roffset, spaceSize, helperHandleRead, srv);
+ }
}
static void
helperStatefulReleaseServer(srv);
}
- if (srv->rfd != -1)
- comm_read(srv->rfd, srv->rbuf + srv->roffset, srv->rbuf_sz - srv->roffset - 1,
- helperStatefulHandleRead, srv);
+ if (srv->rfd != -1) {
+ int spaceSize = srv->rbuf_sz - srv->roffset - 1;
+ assert(spaceSize >= 0);
+
+ // grow the input buffer if needed and possible
+ if (!spaceSize && srv->rbuf_sz + 4096 <= ReadBufMaxSize) {
+ srv->rbuf = (char *)memReallocBuf(srv->rbuf, srv->rbuf_sz + 4096, &srv->rbuf_sz);
+ debugs(84, 3, HERE << "Grew read buffer to " << srv->rbuf_sz);
+ spaceSize = srv->rbuf_sz - srv->roffset - 1;
+ assert(spaceSize >= 0);
+ }
+
+ // quit reading if there is no space left
+ if (!spaceSize) {
+ debugs(84, DBG_IMPORTANT, "ERROR: Disconnecting from a " <<
+ "helper that overflowed " << srv->rbuf_sz << "-byte " <<
+ "Squid input buffer: " << hlp->id_name << " #" <<
+ (srv->index + 1));
+ srv->closePipesSafely();
+ return;
+ }
+
+ comm_read(srv->rfd, srv->rbuf + srv->roffset, spaceSize, helperStatefulHandleRead, srv);
+ }
}
static void