aboutsummaryrefslogtreecommitdiff
path: root/src/buffer.c
diff options
context:
space:
mode:
authorXi Wang <xi.wang@gmail.com>2011-11-28 04:42:54 -0500
committerAndreas Schneider <asn@cryptomilk.org>2012-11-14 17:36:19 +0100
commitad5f306884eee6c83437defe082d57e6ca4da69a (patch)
treeb2a2715d00108a6d841ff0df644a7bf45f02b5b2 /src/buffer.c
parent5ffb8c7cde24fd5a7a1749b4d2b9b08ea893bddc (diff)
downloadlibssh-ad5f306884eee6c83437defe082d57e6ca4da69a.tar.gz
libssh-ad5f306884eee6c83437defe082d57e6ca4da69a.tar.xz
libssh-ad5f306884eee6c83437defe082d57e6ca4da69a.zip
CVE-2012-4562: Fix multiple integer overflows in buffer-related functions.
Diffstat (limited to 'src/buffer.c')
-rw-r--r--src/buffer.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/src/buffer.c b/src/buffer.c
index e68f16f1..3de4f3e3 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -21,6 +21,7 @@
* MA 02111-1307, USA.
*/
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -181,6 +182,11 @@ int buffer_reinit(struct ssh_buffer_struct *buffer) {
*/
int buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) {
buffer_verify(buffer);
+
+ if (buffer->used + len < len) {
+ return -1;
+ }
+
if (buffer->allocated < (buffer->used + len)) {
if(buffer->pos > 0)
buffer_shift(buffer);
@@ -319,6 +325,10 @@ int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
return 0;
}
/* pos isn't high enough */
+ if (buffer->used - buffer->pos + len < len) {
+ return -1;
+ }
+
if (buffer->allocated < (buffer->used - buffer->pos + len)) {
if (realloc_buffer(buffer, buffer->used - buffer->pos + len) < 0) {
return -1;
@@ -430,8 +440,11 @@ uint32_t buffer_get_rest_len(struct ssh_buffer_struct *buffer){
*/
uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer);
- if(buffer->used < buffer->pos+len)
+
+ if (buffer->pos + len < len || buffer->used < buffer->pos + len) {
return 0;
+ }
+
buffer->pos+=len;
/* if the buffer is empty after having passed the whole bytes into it, we can clean it */
if(buffer->pos==buffer->used){
@@ -455,8 +468,11 @@ uint32_t buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){
*/
uint32_t buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){
buffer_verify(buffer);
- if(buffer->used < buffer->pos + len)
- return 0;
+
+ if (buffer->used < len) {
+ return 0;
+ }
+
buffer->used-=len;
buffer_verify(buffer);
return len;
@@ -549,7 +565,7 @@ struct ssh_string_struct *buffer_get_ssh_string(struct ssh_buffer_struct *buffer
}
hostlen = ntohl(stringlen);
/* verify if there is enough space in buffer to get it */
- if ((buffer->pos + hostlen) > buffer->used) {
+ if (buffer->pos + hostlen < hostlen || buffer->pos + hostlen > buffer->used) {
return NULL; /* it is indeed */
}
str = ssh_string_new(hostlen);
@@ -586,7 +602,7 @@ struct ssh_string_struct *buffer_get_mpint(struct ssh_buffer_struct *buffer) {
}
bits = ntohs(bits);
len = (bits + 7) / 8;
- if ((buffer->pos + len) > buffer->used) {
+ if (buffer->pos + len < len || buffer->pos + len > buffer->used) {
return NULL;
}
str = ssh_string_new(len);