From 61e697b9f27beeed025e086558ed79ad05fae595 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Sat, 23 Apr 2022 08:57:53 +0000 Subject: Verify sizes before arithmetic operations Unsigned overflows are not a bug in C but we have to make sure that requested buffer sizes will be actually available. If not, set errno to ERANGE and return an error value. ok deraadt, millert --- lib/libutil/imsg-buffer.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/libutil/imsg-buffer.c b/lib/libutil/imsg-buffer.c index 4526842bd86..7abea4e0deb 100644 --- a/lib/libutil/imsg-buffer.c +++ b/lib/libutil/imsg-buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg-buffer.c,v 1.13 2021/03/31 17:42:24 eric Exp $ */ +/* $OpenBSD: imsg-buffer.c,v 1.14 2022/04/23 08:57:52 tobias Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -73,7 +73,7 @@ ibuf_realloc(struct ibuf *buf, size_t len) unsigned char *b; /* on static buffers max is eq size and so the following fails */ - if (buf->wpos + len > buf->max) { + if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) { errno = ERANGE; return (-1); } @@ -90,6 +90,11 @@ ibuf_realloc(struct ibuf *buf, size_t len) int ibuf_add(struct ibuf *buf, const void *data, size_t len) { + if (len > SIZE_MAX - buf->wpos) { + errno = ERANGE; + return (-1); + } + if (buf->wpos + len > buf->size) if (ibuf_realloc(buf, len) == -1) return (-1); @@ -104,6 +109,11 @@ ibuf_reserve(struct ibuf *buf, size_t len) { void *b; + if (len > SIZE_MAX - buf->wpos) { + errno = ERANGE; + return (NULL); + } + if (buf->wpos + len > buf->size) if (ibuf_realloc(buf, len) == -1) return (NULL); @@ -117,7 +127,7 @@ void * ibuf_seek(struct ibuf *buf, size_t pos, size_t len) { /* only allowed to seek in already written parts */ - if (pos + len > buf->wpos) + if (len > SIZE_MAX - pos || pos + len > buf->wpos) return (NULL); return (buf->buf + pos); @@ -202,7 +212,7 @@ msgbuf_drain(struct msgbuf *msgbuf, size_t n) for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0; buf = next) { next = TAILQ_NEXT(buf, entry); - if (buf->rpos + n >= buf->wpos) { + if (n >= buf->wpos - buf->rpos) { n -= buf->wpos - buf->rpos; ibuf_dequeue(msgbuf, buf); } else { -- cgit v1.2.3