diff options
| author | Hauke Mehrtens | 2026-04-23 21:36:45 +0000 |
|---|---|---|
| committer | Hauke Mehrtens | 2026-06-18 22:07:45 +0000 |
| commit | b4a718b6d374f1ac4d8cc7045cf0cca7e5a20dde (patch) | |
| tree | 8163a53a22b2b23fcac6c3a97d0cfca28bccab1a | |
| parent | 1d80ee2fd95f5e62b20f1522487733c2a733e39c (diff) | |
| download | libubox-b4a718b6d374f1ac4d8cc7045cf0cca7e5a20dde.tar.gz | |
blob: fix integer overflow in buffer growth functions
blob_buffer_grow() computed delta and the new buffer size as plain
int additions without checking for overflow. With sufficiently large
inputs the result could wrap around to a small positive value, so
realloc() would shrink the buffer and subsequent writes would
overflow the heap.
blob_buf_grow() suffered from the same issue: '(buf->buflen +
required) > BLOB_ATTR_LEN_MASK' is evaluated after the addition
already wraps, so the bound check could be bypassed.
Reject negative inputs explicitly and rewrite the bound checks so
the arithmetic cannot overflow.
Link: https://github.com/openwrt/libubox/pull/42
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
(cherry picked from commit 40a87f734b940198600324c70df614d537d21e33)
| -rw-r--r-- | blob.c | 16 |
1 files changed, 14 insertions, 2 deletions
@@ -16,13 +16,23 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <limits.h> + #include "blob.h" static bool blob_buffer_grow(struct blob_buf *buf, int minlen) { void *new; - int delta = ((minlen / 256) + 1) * 256; + int delta; + + if (minlen < 0 || minlen > INT_MAX - 256) + return false; + + delta = ((minlen / 256) + 1) * 256; + if (buf->buflen < 0 || delta > INT_MAX - buf->buflen) + return false; + new = realloc(buf->buf, buf->buflen + delta); if (new) { buf->buf = new; @@ -58,7 +68,9 @@ blob_buf_grow(struct blob_buf *buf, int required) { int offset_head = attr_to_offset(buf, buf->head); - if ((buf->buflen + required) > BLOB_ATTR_LEN_MASK) + if (required < 0 || buf->buflen < 0) + return false; + if (required > BLOB_ATTR_LEN_MASK - buf->buflen) return false; if (!buf->grow || !buf->grow(buf, required)) return false; |