From a3c5e8927de8ba8c763230c7e1015bf7fad83ebc Mon Sep 17 00:00:00 2001 From: Craig Barnes Date: Wed, 2 Mar 2022 01:55:25 +0000 Subject: [PATCH] osc: grow OSC buffer exponentially instead of by fixed increments of 128 With fixed increments of 128 bytes, an OSC 52 copy operation could end up doing thousands or tens of thousands of realloc(3) calls just to copy a few MB. --- osc.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/osc.c b/osc.c index 9c3b326a..94b6892c 100644 --- a/osc.c +++ b/osc.c @@ -902,11 +902,20 @@ osc_dispatch(struct terminal *term) bool osc_ensure_size(struct terminal *term, size_t required_size) { - if (required_size <= term->vt.osc.size) + if (likely(required_size <= term->vt.osc.size)) return true; - size_t new_size = (required_size + 127) / 128 * 128; - xassert(new_size > 0); + const size_t pow2_max = ~(SIZE_MAX >> 1); + if (unlikely(required_size > pow2_max)) { + LOG_ERR("required OSC buffer size (%zu) exceeds limit (%zu)", + required_size, pow2_max); + return false; + } + + size_t new_size = max(term->vt.osc.size, 4096); + while (new_size < required_size) { + new_size <<= 1; + } uint8_t *new_data = realloc(term->vt.osc.data, new_size); if (new_data == NULL) { @@ -914,6 +923,7 @@ osc_ensure_size(struct terminal *term, size_t required_size) return false; } + LOG_DBG("resized OSC buffer: %zu", new_size); term->vt.osc.data = new_data; term->vt.osc.size = new_size; return true;