From 624f18ad90e3784878e6d303858f59651af68f61 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Mon, 10 Jan 2022 21:17:17 +0100 Subject: [PATCH] withBuffer: Make sure to hit the stack protector --- src/libutil/util.hh | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 407505be9..e2192987c 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -671,15 +671,28 @@ template overloaded(Ts...) -> overloaded; std::string showBytes(uint64_t bytes); +/** + `withBuffer(size, fun)` applies `fun` to a temporary `char` array of size `size`. + The array will be allocated either on the stack or on the heap depending on its size +*/ template -inline auto withBuffer(size_t size, Fn fun) +inline auto withBuffer(size_t n, Fn fun) -> std::invoke_result_t { - if (size < 0x10000) { - T buf[size]; + // Large stack allocations can skip past the stack protection page. + const size_t stack_protection_size = 4096; + // We reduce the max stack allocated buffer by an extra amount to increase + // the chance of hitting it, even when `fun`'s first access is some distance + // into its *further* stack frame, particularly if the call was inlined and + // therefore not writing a frame pointer. + const size_t play = 64 * sizeof(char *); // 512B on 64b archs + size_t size_bytes = n * sizeof(T); + + if (size_bytes < stack_protection_size - play) { + T buf[n]; return fun(buf); } else { - auto buf = std::unique_ptr(new T[size]); + auto buf = std::unique_ptr(new T[n]); return fun(buf.get()); } }