summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens2026-04-23 21:36:45 +0000
committerHauke Mehrtens2026-06-18 22:07:45 +0000
commitb4a718b6d374f1ac4d8cc7045cf0cca7e5a20dde (patch)
tree8163a53a22b2b23fcac6c3a97d0cfca28bccab1a
parent1d80ee2fd95f5e62b20f1522487733c2a733e39c (diff)
downloadlibubox-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.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/blob.c b/blob.c
index 735e5d5..3c2dd81 100644
--- a/blob.c
+++ b/blob.c
@@ -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;