From 94c5d4d641cd7073fab05991fac2fe132808de88 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 19 May 2024 19:24:37 -0500
Subject: [PATCH] Drop buffers in clear if 'too big'

---
 actix-http/src/h1/big_bytes.rs  | 12 +++++++++++-
 actix-http/src/h1/dispatcher.rs |  2 +-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/actix-http/src/h1/big_bytes.rs b/actix-http/src/h1/big_bytes.rs
index b845d917..04ae8a6c 100644
--- a/actix-http/src/h1/big_bytes.rs
+++ b/actix-http/src/h1/big_bytes.rs
@@ -2,6 +2,9 @@ use std::collections::VecDeque;
 
 use bytes::{Buf, BufMut, Bytes, BytesMut};
 
+// 64KB max capacity (arbitrarily chosen)
+const MAX_CAPACITY: usize = 1024 * 64;
+
 pub(crate) struct BigBytes {
     buffer: BytesMut,
     frozen: VecDeque<Bytes>,
@@ -18,10 +21,17 @@ impl BigBytes {
     }
 
     // Clear the internal queue and buffer, resetting length to zero
-    pub(super) fn clear(&mut self) {
+    //
+    // if the internal buffer capacity exceeds 64KB or new_capacity, whichever is greater, it will
+    // be freed and a new buffer of capacity `new_capacity` will be allocated
+    pub(super) fn clear(&mut self, new_capacity: usize) {
         std::mem::take(&mut self.frozen);
         self.frozen_len = 0;
         self.buffer.clear();
+
+        if self.buffer.capacity() > new_capacity.max(MAX_CAPACITY) {
+            self.buffer = BytesMut::with_capacity(new_capacity);
+        }
     }
 
     // Return a mutable reference to the underlying buffer. This should only be used when dealing
diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs
index 64a5d460..d1bff8db 100644
--- a/actix-http/src/h1/dispatcher.rs
+++ b/actix-http/src/h1/dispatcher.rs
@@ -347,7 +347,7 @@ where
         }
 
         // everything has written to I/O; clear buffer
-        write_buf.clear();
+        write_buf.clear(HW_BUFFER_SIZE);
 
         // flush the I/O and check if get blocked
         io.poll_flush(cx)