summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@cvs.openbsd.org>2022-04-23 08:57:53 +0000
committerTobias Stoeckmann <tobias@cvs.openbsd.org>2022-04-23 08:57:53 +0000
commit61e697b9f27beeed025e086558ed79ad05fae595 (patch)
tree3852d358be58486a571840d5541c76a98135c9f5 /lib
parentf1150915c1d18b3476ae27cc0fabc2af5f1cef6f (diff)
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
Diffstat (limited to 'lib')
-rw-r--r--lib/libutil/imsg-buffer.c18
1 files changed, 14 insertions, 4 deletions
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 <henning@openbsd.org>
@@ -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 {