From c8365b2bddbdb85a983efcab0485cb8587b90bb2 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Mon, 28 Mar 2022 21:59:43 +0100 Subject: buflib: fix bug in handle_table_shrink The way it iterated over the handle table is unsafe if *every* handle is free, leading to an out of bounds access. This is a contrived example, but the bug can be triggered by making several allocations, freeing them out of order so that the handle table remains uncompacted, and then triggering a compaction using buflib_alloc_maximum(). Change-Id: I879e2f0b223e6ca596769610ac46f4edf1107f5c --- firmware/buflib.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'firmware') diff --git a/firmware/buflib.c b/firmware/buflib.c index eccf8b057e..5b837aa439 100644 --- a/firmware/buflib.c +++ b/firmware/buflib.c @@ -247,18 +247,20 @@ union buflib_data* handle_to_block(struct buflib_context* ctx, int handle) /* Shrink the handle table, returning true if its size was reduced, false if * not */ -static inline -bool -handle_table_shrink(struct buflib_context *ctx) +static inline bool handle_table_shrink(struct buflib_context *ctx) { - bool rv; union buflib_data *handle; - for (handle = ctx->last_handle; !(handle->alloc); handle++); + union buflib_data *old_last = ctx->last_handle; + + for (handle = ctx->last_handle; handle != ctx->handle_table; ++handle) + if (handle->alloc) + break; + if (handle > ctx->first_free_handle) ctx->first_free_handle = handle - 1; - rv = handle != ctx->last_handle; + ctx->last_handle = handle; - return rv; + return handle != old_last; } -- cgit v1.2.3