]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Added additional defensive programming to buffer.[ch] functions.
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Sun, 27 Jul 2008 05:31:09 +0000 (05:31 +0000)
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>
Sun, 27 Jul 2008 05:31:09 +0000 (05:31 +0000)
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3128 e7ae566f-a301-0410-adde-c780ea21d3b5

buffer.c
buffer.h

index 0fe9b61fd8298ac573019b16d4890aa1de6f8b00..dfaaaa107e4b32a452ed16f20baaed89236ecde0 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -42,6 +42,12 @@ array_mult_safe (const size_t m1, const size_t m2)
   return (size_t) res;
 }
 
+void
+buf_size_error (size_t size)
+{
+  msg (M_FATAL, "fatal buffer size error, size=%lu", (unsigned long)size);
+}
+
 struct buffer
 #ifdef DMALLOC
 alloc_buf_debug (size_t size, const char *file, int line)
@@ -64,6 +70,8 @@ alloc_buf_gc (size_t size, struct gc_arena *gc)
 #endif
 {
   struct buffer buf;
+  if (!buf_size_valid (size))
+    buf_size_error (size);
   buf.capacity = (int)size;
   buf.offset = 0;
   buf.len = 0;
index 577041cb438ef302fb579471077cba96be032255..2320e4c7c3e5f1a56ce71e19c249b987caf0bc1e 100644 (file)
--- a/buffer.h
+++ b/buffer.h
@@ -28,6 +28,8 @@
 #include "basic.h"
 #include "thread.h"
 
+#define BUF_SIZE_MAX 1000000
+
 /*
  * Define verify_align function, otherwise
  * it will be a noop.
@@ -74,12 +76,12 @@ struct gc_arena
   struct gc_entry *list;
 };
 
-#define BPTR(buf)  ((buf)->data + (buf)->offset)
-#define BEND(buf)  (BPTR(buf) + (buf)->len)
-#define BLAST(buf) (((buf)->data && (buf)->len) ? (BPTR(buf) + (buf)->len - 1) : NULL)
-#define BLEN(buf)  ((buf)->len)
-#define BDEF(buf)  ((buf)->data != NULL)
-#define BSTR(buf)  ((char *)BPTR(buf))
+#define BPTR(buf)  (buf_bptr(buf))
+#define BEND(buf)  (buf_bend(buf))
+#define BLAST(buf) (buf_blast(buf))
+#define BLEN(buf)  (buf_len(buf))
+#define BDEF(buf)  (buf_defined(buf))
+#define BSTR(buf)  (buf_str(buf))
 #define BCAP(buf)  (buf_forward_capacity (buf))
 
 void buf_clear (struct buffer *buf);
@@ -97,6 +99,8 @@ size_t array_mult_safe (const size_t m1, const size_t m2);
 #define PA_BRACKET (1<<0)
 char *print_argv (const char **p, struct gc_arena *gc, const unsigned int flags);
 
+void buf_size_error (const size_t size);
+
 /* for dmalloc debugging */
 
 #ifdef DMALLOC
@@ -136,6 +140,69 @@ bool buf_init_debug (struct buffer *buf, int offset, const char *file, int line)
 
 /* inline functions */
 
+static inline bool
+buf_defined (const struct buffer *buf)
+{
+  return buf->data != NULL;
+}
+
+static inline bool
+buf_valid (const struct buffer *buf)
+{
+  return likely (buf->data != NULL) && likely (buf->len >= 0);
+}
+
+static inline uint8_t *
+buf_bptr (const struct buffer *buf)
+{
+  if (buf_valid (buf))
+    return buf->data + buf->offset;
+  else
+    return NULL;
+}
+
+static int
+buf_len (const struct buffer *buf)
+{
+  if (buf_valid (buf))
+    return buf->len;
+  else
+    return 0;
+}
+
+static inline uint8_t *
+buf_bend (const struct buffer *buf)
+{
+  return buf_bptr (buf) + buf_len (buf);
+}
+
+static inline uint8_t *
+buf_blast (const struct buffer *buf)
+{
+  if (buf_len (buf) > 0)
+    return buf_bptr (buf) + buf_len (buf) - 1;
+  else
+    return NULL;
+}
+
+static inline bool
+buf_size_valid (const size_t size)
+{
+  return likely (size < BUF_SIZE_MAX);
+}
+
+static inline bool
+buf_size_valid_signed (const int size)
+{
+  return likely (size >= -BUF_SIZE_MAX) && likely (size < BUF_SIZE_MAX);
+}
+
+static inline char *
+buf_str (const struct buffer *buf)
+{
+  return (char *)buf_bptr(buf);
+}
+
 static inline void
 buf_reset (struct buffer *buf)
 {
@@ -162,15 +229,11 @@ buf_init_dowork (struct buffer *buf, int offset)
   return true;
 }
 
-static inline bool
-buf_defined (struct buffer *buf)
-{
-  return buf->data != NULL;
-}
-
 static inline void
 buf_set_write (struct buffer *buf, uint8_t *data, int size)
 {
+  if (!buf_size_valid (size))
+    buf_size_error (size);
   buf->len = 0;
   buf->offset = 0;
   buf->capacity = size;
@@ -182,6 +245,8 @@ buf_set_write (struct buffer *buf, uint8_t *data, int size)
 static inline void
 buf_set_read (struct buffer *buf, const uint8_t *data, int size)
 {
+  if (!buf_size_valid (size))
+    buf_size_error (size);
   buf->len = buf->capacity = size;
   buf->offset = 0;
   buf->data = (uint8_t *)data;
@@ -322,38 +387,57 @@ struct buffer buf_sub (struct buffer *buf, int size, bool prepend);
 static inline bool
 buf_safe (const struct buffer *buf, int len)
 {
-  return len >= 0 && buf->offset + buf->len + len <= buf->capacity;
+  return buf_valid (buf) && buf_size_valid (len)
+    && buf->offset + buf->len + len <= buf->capacity;
 }
 
 static inline bool
 buf_safe_bidir (const struct buffer *buf, int len)
 {
-  const int newlen = buf->len + len;
-  return newlen >= 0 && buf->offset + newlen <= buf->capacity;
+  if (buf_valid (buf) && buf_size_valid_signed (len))
+    {
+      const int newlen = buf->len + len;
+      return newlen >= 0 && buf->offset + newlen <= buf->capacity;
+    }
+  else
+    return false;
 }
 
 static inline int
 buf_forward_capacity (const struct buffer *buf)
 {
-  int ret = buf->capacity - (buf->offset + buf->len);
-  if (ret < 0)
-    ret = 0;
-  return ret;
+  if (buf_valid (buf))
+    {
+      int ret = buf->capacity - (buf->offset + buf->len);
+      if (ret < 0)
+       ret = 0;
+      return ret;
+    }
+  else
+    return 0;
 }
 
 static inline int
 buf_forward_capacity_total (const struct buffer *buf)
 {
-  int ret = buf->capacity - buf->offset;
-  if (ret < 0)
-    ret = 0;
-  return ret;
+  if (buf_valid (buf))
+    {
+      int ret = buf->capacity - buf->offset;
+      if (ret < 0)
+       ret = 0;
+      return ret;
+    }
+  else
+    return 0;
 }
 
 static inline int
 buf_reverse_capacity (const struct buffer *buf)
 {
-  return buf->offset;
+  if (buf_valid (buf))
+    return buf->offset;
+  else
+    return 0;
 }
 
 static inline bool
@@ -373,7 +457,7 @@ buf_inc_len (struct buffer *buf, int inc)
 static inline uint8_t *
 buf_prepend (struct buffer *buf, int size)
 {
-  if (size < 0 || size > buf->offset)
+  if (!buf_valid (buf) || size < 0 || size > buf->offset)
     return NULL;
   buf->offset -= size;
   buf->len += size;
@@ -383,7 +467,7 @@ buf_prepend (struct buffer *buf, int size)
 static inline bool
 buf_advance (struct buffer *buf, int size)
 {
-  if (size < 0 || buf->len < size)
+  if (!buf_valid (buf) || size < 0 || buf->len < size)
     return false;
   buf->offset += size;
   buf->len -= size;