diff options
author | Tobias Stoeckmann <tobias@cvs.openbsd.org> | 2022-04-23 08:57:53 +0000 |
---|---|---|
committer | Tobias Stoeckmann <tobias@cvs.openbsd.org> | 2022-04-23 08:57:53 +0000 |
commit | 61e697b9f27beeed025e086558ed79ad05fae595 (patch) | |
tree | 3852d358be58486a571840d5541c76a98135c9f5 /lib | |
parent | f1150915c1d18b3476ae27cc0fabc2af5f1cef6f (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.c | 18 |
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 { |