Browse code

Added additional defensive programming to buffer.[ch] functions.

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@3128 e7ae566f-a301-0410-adde-c780ea21d3b5

james authored on 2008/07/27 14:31:09
Showing 2 changed files
... ...
@@ -42,6 +42,12 @@ array_mult_safe (const size_t m1, const size_t m2)
42 42
   return (size_t) res;
43 43
 }
44 44
 
45
+void
46
+buf_size_error (size_t size)
47
+{
48
+  msg (M_FATAL, "fatal buffer size error, size=%lu", (unsigned long)size);
49
+}
50
+
45 51
 struct buffer
46 52
 #ifdef DMALLOC
47 53
 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)
64 64
 #endif
65 65
 {
66 66
   struct buffer buf;
67
+  if (!buf_size_valid (size))
68
+    buf_size_error (size);
67 69
   buf.capacity = (int)size;
68 70
   buf.offset = 0;
69 71
   buf.len = 0;
... ...
@@ -28,6 +28,8 @@
28 28
 #include "basic.h"
29 29
 #include "thread.h"
30 30
 
31
+#define BUF_SIZE_MAX 1000000
32
+
31 33
 /*
32 34
  * Define verify_align function, otherwise
33 35
  * it will be a noop.
... ...
@@ -74,12 +76,12 @@ struct gc_arena
74 74
   struct gc_entry *list;
75 75
 };
76 76
 
77
-#define BPTR(buf)  ((buf)->data + (buf)->offset)
78
-#define BEND(buf)  (BPTR(buf) + (buf)->len)
79
-#define BLAST(buf) (((buf)->data && (buf)->len) ? (BPTR(buf) + (buf)->len - 1) : NULL)
80
-#define BLEN(buf)  ((buf)->len)
81
-#define BDEF(buf)  ((buf)->data != NULL)
82
-#define BSTR(buf)  ((char *)BPTR(buf))
77
+#define BPTR(buf)  (buf_bptr(buf))
78
+#define BEND(buf)  (buf_bend(buf))
79
+#define BLAST(buf) (buf_blast(buf))
80
+#define BLEN(buf)  (buf_len(buf))
81
+#define BDEF(buf)  (buf_defined(buf))
82
+#define BSTR(buf)  (buf_str(buf))
83 83
 #define BCAP(buf)  (buf_forward_capacity (buf))
84 84
 
85 85
 void buf_clear (struct buffer *buf);
... ...
@@ -97,6 +99,8 @@ size_t array_mult_safe (const size_t m1, const size_t m2);
97 97
 #define PA_BRACKET (1<<0)
98 98
 char *print_argv (const char **p, struct gc_arena *gc, const unsigned int flags);
99 99
 
100
+void buf_size_error (const size_t size);
101
+
100 102
 /* for dmalloc debugging */
101 103
 
102 104
 #ifdef DMALLOC
... ...
@@ -136,6 +140,69 @@ bool buf_init_debug (struct buffer *buf, int offset, const char *file, int line)
136 136
 
137 137
 /* inline functions */
138 138
 
139
+static inline bool
140
+buf_defined (const struct buffer *buf)
141
+{
142
+  return buf->data != NULL;
143
+}
144
+
145
+static inline bool
146
+buf_valid (const struct buffer *buf)
147
+{
148
+  return likely (buf->data != NULL) && likely (buf->len >= 0);
149
+}
150
+
151
+static inline uint8_t *
152
+buf_bptr (const struct buffer *buf)
153
+{
154
+  if (buf_valid (buf))
155
+    return buf->data + buf->offset;
156
+  else
157
+    return NULL;
158
+}
159
+
160
+static int
161
+buf_len (const struct buffer *buf)
162
+{
163
+  if (buf_valid (buf))
164
+    return buf->len;
165
+  else
166
+    return 0;
167
+}
168
+
169
+static inline uint8_t *
170
+buf_bend (const struct buffer *buf)
171
+{
172
+  return buf_bptr (buf) + buf_len (buf);
173
+}
174
+
175
+static inline uint8_t *
176
+buf_blast (const struct buffer *buf)
177
+{
178
+  if (buf_len (buf) > 0)
179
+    return buf_bptr (buf) + buf_len (buf) - 1;
180
+  else
181
+    return NULL;
182
+}
183
+
184
+static inline bool
185
+buf_size_valid (const size_t size)
186
+{
187
+  return likely (size < BUF_SIZE_MAX);
188
+}
189
+
190
+static inline bool
191
+buf_size_valid_signed (const int size)
192
+{
193
+  return likely (size >= -BUF_SIZE_MAX) && likely (size < BUF_SIZE_MAX);
194
+}
195
+
196
+static inline char *
197
+buf_str (const struct buffer *buf)
198
+{
199
+  return (char *)buf_bptr(buf);
200
+}
201
+
139 202
 static inline void
140 203
 buf_reset (struct buffer *buf)
141 204
 {
... ...
@@ -162,15 +229,11 @@ buf_init_dowork (struct buffer *buf, int offset)
162 162
   return true;
163 163
 }
164 164
 
165
-static inline bool
166
-buf_defined (struct buffer *buf)
167
-{
168
-  return buf->data != NULL;
169
-}
170
-
171 165
 static inline void
172 166
 buf_set_write (struct buffer *buf, uint8_t *data, int size)
173 167
 {
168
+  if (!buf_size_valid (size))
169
+    buf_size_error (size);
174 170
   buf->len = 0;
175 171
   buf->offset = 0;
176 172
   buf->capacity = size;
... ...
@@ -182,6 +245,8 @@ buf_set_write (struct buffer *buf, uint8_t *data, int size)
182 182
 static inline void
183 183
 buf_set_read (struct buffer *buf, const uint8_t *data, int size)
184 184
 {
185
+  if (!buf_size_valid (size))
186
+    buf_size_error (size);
185 187
   buf->len = buf->capacity = size;
186 188
   buf->offset = 0;
187 189
   buf->data = (uint8_t *)data;
... ...
@@ -322,38 +387,57 @@ struct buffer buf_sub (struct buffer *buf, int size, bool prepend);
322 322
 static inline bool
323 323
 buf_safe (const struct buffer *buf, int len)
324 324
 {
325
-  return len >= 0 && buf->offset + buf->len + len <= buf->capacity;
325
+  return buf_valid (buf) && buf_size_valid (len)
326
+    && buf->offset + buf->len + len <= buf->capacity;
326 327
 }
327 328
 
328 329
 static inline bool
329 330
 buf_safe_bidir (const struct buffer *buf, int len)
330 331
 {
331
-  const int newlen = buf->len + len;
332
-  return newlen >= 0 && buf->offset + newlen <= buf->capacity;
332
+  if (buf_valid (buf) && buf_size_valid_signed (len))
333
+    {
334
+      const int newlen = buf->len + len;
335
+      return newlen >= 0 && buf->offset + newlen <= buf->capacity;
336
+    }
337
+  else
338
+    return false;
333 339
 }
334 340
 
335 341
 static inline int
336 342
 buf_forward_capacity (const struct buffer *buf)
337 343
 {
338
-  int ret = buf->capacity - (buf->offset + buf->len);
339
-  if (ret < 0)
340
-    ret = 0;
341
-  return ret;
344
+  if (buf_valid (buf))
345
+    {
346
+      int ret = buf->capacity - (buf->offset + buf->len);
347
+      if (ret < 0)
348
+	ret = 0;
349
+      return ret;
350
+    }
351
+  else
352
+    return 0;
342 353
 }
343 354
 
344 355
 static inline int
345 356
 buf_forward_capacity_total (const struct buffer *buf)
346 357
 {
347
-  int ret = buf->capacity - buf->offset;
348
-  if (ret < 0)
349
-    ret = 0;
350
-  return ret;
358
+  if (buf_valid (buf))
359
+    {
360
+      int ret = buf->capacity - buf->offset;
361
+      if (ret < 0)
362
+	ret = 0;
363
+      return ret;
364
+    }
365
+  else
366
+    return 0;
351 367
 }
352 368
 
353 369
 static inline int
354 370
 buf_reverse_capacity (const struct buffer *buf)
355 371
 {
356
-  return buf->offset;
372
+  if (buf_valid (buf))
373
+    return buf->offset;
374
+  else
375
+    return 0;
357 376
 }
358 377
 
359 378
 static inline bool
... ...
@@ -373,7 +457,7 @@ buf_inc_len (struct buffer *buf, int inc)
373 373
 static inline uint8_t *
374 374
 buf_prepend (struct buffer *buf, int size)
375 375
 {
376
-  if (size < 0 || size > buf->offset)
376
+  if (!buf_valid (buf) || size < 0 || size > buf->offset)
377 377
     return NULL;
378 378
   buf->offset -= size;
379 379
   buf->len += size;
... ...
@@ -383,7 +467,7 @@ buf_prepend (struct buffer *buf, int size)
383 383
 static inline bool
384 384
 buf_advance (struct buffer *buf, int size)
385 385
 {
386
-  if (size < 0 || buf->len < size)
386
+  if (!buf_valid (buf) || size < 0 || buf->len < size)
387 387
     return false;
388 388
   buf->offset += size;
389 389
   buf->len -= size;