]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Add comments to fuzzing.c, fuzzing.h, remove unused function (fuzzer_read)
authorGuido Vranken <guidovranken@gmail.com>
Thu, 10 Aug 2017 21:29:50 +0000 (23:29 +0200)
committerGuido Vranken <guidovranken@gmail.com>
Thu, 10 Aug 2017 21:29:50 +0000 (23:29 +0200)
src/openvpn/fuzzing.c
src/openvpn/fuzzing.h

index 2bf31750cb1fa3efc415d06450f04ea9d1669f4c..3e826238c0b795d70fbdf1c1e2949d08b8a6d19d 100644 (file)
@@ -8,20 +8,29 @@
 #include "buffer.h"
 #include "fuzzing.h"
 
+/* Pointer to current position in the input buffer.
+ * Incremented by 1 for every byte read. */
 static unsigned char* fuzzer_data = NULL;
+
+/* Remaining buffer size.
+ * Decremented by 1 for every byte read */
 static size_t fuzzer_data_size = 0;
 
+/* Sets internal buffer state. Must be called before any other functions
+ * in this file */
 void fuzzer_set_input(unsigned char* data, size_t size)
 {
     fuzzer_data = data;
     fuzzer_data_size = size;
 }
 
+/* Getter for pointer to current buffer position */
 unsigned char* fuzzer_get_current_data(void)
 {
     return fuzzer_data;
 }
 
+/* Getter for pointer to current remaining buffer size */
 size_t fuzzer_get_current_size(void)
 {
     return fuzzer_data_size;
@@ -33,6 +42,7 @@ void fuzzer_set_recv_no_rnd(int yesno)
     recv_no_rnd = yesno;
 }
 
+/* Extract data of size 'size' and store it in 'dest' */
 ssize_t fuzzer_get_data(void* dest, size_t size)
 {
     if ( size > fuzzer_data_size )
@@ -47,7 +57,10 @@ ssize_t fuzzer_get_data(void* dest, size_t size)
 
     return size;
 }
-
+/* Does two things:
+ *    - Extract an integer of max size 'size' from the input stream
+ *    - If that much data is left in the input stream, copy it to 'dest'
+ */
 ssize_t fuzzer_get_data_rnd(void* dest, size_t size)
 {
     size_t realsize;
@@ -55,18 +68,24 @@ ssize_t fuzzer_get_data_rnd(void* dest, size_t size)
     unsigned short realsize_us;
     unsigned char realsize_uc;
 
+    /* No operation */
     if ( size == 0 )
     {
         return 0;
     }
 
+    /* Refuse to serve requests for more than 2 gigabytes */
     if ( size > 0x7FFFFFFF )
     {
         return 0;
     }
 
+    /* Get an integer from the input stream.
+     * Use different data types for different size requests, so as not
+     * to waste input buffer space */
     if ( size > 65535 )
     {
+        /* An unsigned int is needed */
         if ( fuzzer_get_data(&realsize_ui, sizeof(realsize_ui)) < 0 )
         {
             return -1;
@@ -75,6 +94,7 @@ ssize_t fuzzer_get_data_rnd(void* dest, size_t size)
     }
     else if ( size > 255 )
     {
+        /* An unsigned short is needed */
         if ( fuzzer_get_data(&realsize_us, sizeof(realsize_us)) < 0 )
         {
             return -1;
@@ -83,6 +103,7 @@ ssize_t fuzzer_get_data_rnd(void* dest, size_t size)
     }
     else
     {
+        /* An unsigned char will suffice */
         if ( fuzzer_get_data(&realsize_uc, sizeof(realsize_uc)) < 0 )
         {
             return -1;
@@ -90,8 +111,10 @@ ssize_t fuzzer_get_data_rnd(void* dest, size_t size)
         realsize = realsize_uc;
     }
 
+    /* Map the retrieved integer to the space [0..size+1] using modulo */
     realsize %= (size+1);
 
+    /* Attempt to get this much data */
     return fuzzer_get_data(dest, realsize);
 }
 
@@ -99,6 +122,7 @@ ssize_t fuzzer_get_integer(size_t max)
 {
     size_t s;
 
+    /* No operation */
     if ( max == 0 )
     {
         return 0;
@@ -111,11 +135,13 @@ ssize_t fuzzer_get_integer(size_t max)
     }
     */
 
+    /* Get a size_t from the input buffer */
     if ( fuzzer_get_data(&s, sizeof(s)) < 0 )
     {
         return -1;
     }
 
+    /* Map the retrieved integer to the space [0..max+1] using modulo */
     return s % (max+1);
 }
 
@@ -124,6 +150,7 @@ static char* fuzzer_get_string_inner(size_t maxsize, struct gc_arena* gc)
     ssize_t strsize;
     char* ret;
 
+    /* Get integer in range [0..maxsize] */
     if ( (strsize = fuzzer_get_integer(maxsize)) < 0 )
     {
         return NULL;
@@ -131,13 +158,16 @@ static char* fuzzer_get_string_inner(size_t maxsize, struct gc_arena* gc)
 
     if ( gc == NULL )
     {
+        /* Use default allocator */
         ret = malloc(strsize+1);
     }
     else
     {
+        /* Use the garbage collector allocator */
         ALLOC_ARRAY_GC(ret, char, strsize+1, gc);
     }
 
+    /* Allocation failure */
     if ( ret == NULL )
     {
         return NULL;
@@ -152,45 +182,49 @@ static char* fuzzer_get_string_inner(size_t maxsize, struct gc_arena* gc)
         return NULL;
     }
 
+    /* Null-terminate */
     ret[strsize] = 0;
 
     return ret;
 }
 
+/* Create null-terminated string of length 'maxsize' from
+ * fuzzer input data */
 char* fuzzer_get_string(size_t maxsize)
 {
     return fuzzer_get_string_inner(maxsize, NULL);
 }
 
+/* Create null-terminated string of length 'maxsize' from
+ * fuzzer input data, allocate memory using 'gc' */
 char* fuzzer_get_string_gc(size_t maxsize, struct gc_arena* gc)
 {
     return fuzzer_get_string_inner(maxsize, gc);
 }
 
-ssize_t fuzzer_read(void* dest, size_t size)
-{
-    if ( recv_no_rnd )
-    {
-        return fuzzer_get_data(dest, size);
-    }
-    else
-    {
-        return fuzzer_get_data_rnd(dest, size);
-    }
-}
-
+/* Abstraction function for POSIX read/recv/..
+ * Rather than giving socket or file data to the caller,
+ * return data from the fuzzer input stream
+ */
 ssize_t fuzzer_recv(void* dest, size_t size)
 {
     if ( recv_no_rnd )
     {
+        /* Store 'size' bytes in 'dest', or fail if insufficient data
+         * is available */
         return fuzzer_get_data(dest, size);
     }
     else
     {
+        /* Store up to 'size' bytes in 'dest', or fail if insufficient data
+         * is available */
         return fuzzer_get_data_rnd(dest, size);
     }
 }
 
+/* Abstraction function for POSIX send/write/..
+ * Currently always succeeds
+ */
 ssize_t fuzzer_send(size_t size)
 {
     /*
@@ -205,29 +239,52 @@ ssize_t fuzzer_send(size_t size)
     //return r;
 }
 
+/* Pseudo-randomly alter the struct buffer members
+ * 'offset' and 'len' such that:
+ *
+ * offset >= 0 and offset <= capacity
+ * len >= 0 and len <= (capacity - offset)
+ */
 void fuzzer_alter_buffer(struct buffer* buffer)
 {
     ssize_t newoffset, newlen;
+
     if ( buffer->capacity == 0 )
     {
         return;
     }
+
+    /* newoffset = integer in range [0..buffer->capacity] */
     FUZZER_GET_INTEGER(newoffset, buffer->capacity);
+
     newlen = buffer->capacity - newoffset;
     if ( newlen != 0 )
     {
+        /* newlen = integer in range [0..newlen] */
         FUZZER_GET_INTEGER(newlen, newlen);
     }
+
     buffer->offset = newoffset;
     buffer->len = newlen;
 
     return;
+
 cleanup:
     return;
 }
 
 void test_undefined_memory(void* vp, size_t s)
 {
+    /* MemorySanitizer (MSAN) will not trigger an exception for
+     * uninitialized data unless:
+     *    - The data is used for branching
+     *    - The data is serialized
+     *
+     * So here we "serialize" data 'vp' of size 's' to /dev/null.
+     * This is a trick to force MSAN to evaluate whether any bit in this
+     * buffer constitutes uninitialized data.
+     */
+
     FILE* fp = fopen("/dev/null", "wb");
     unsigned char* p = (unsigned char*)vp;
     fwrite(p, s, 1, fp);
index 0dec200ac78646824f1811c48930ba1012643398..a976d77b4cad5715bb60557462af0711421e394e 100644 (file)
@@ -15,22 +15,29 @@ ssize_t fuzzer_get_data_rnd(void* dest, size_t size);
 ssize_t fuzzer_get_integer(size_t max);
 char* fuzzer_get_string(size_t maxsize);
 char* fuzzer_get_string_gc(size_t maxsize, struct gc_arena* gc);
-ssize_t fuzzer_read(void* dest, size_t size);
 ssize_t fuzzer_recv(void* dest, size_t size);
 ssize_t fuzzer_send(size_t size);
 void fuzzer_alter_buffer(struct buffer* buffer);
 void test_undefined_memory(void* vp, size_t s);
+
+/* Get data of size 'size', store result in 'dest',
+ * go to 'cleanup' upon failure */
 #define FUZZER_GET_DATA(dest, size) { \
     if ( fuzzer_get_data((dest), (size)) < 0 ) { \
         goto cleanup; \
     } \
 }
+/* Get integer in range [0..max], store result in 'dest',
+ * go to 'cleanup' upon failure */
 #define FUZZER_GET_INTEGER(dest, max) { \
     (dest) = fuzzer_get_integer(max); \
     if ( (dest) < 0 ) { \
         goto cleanup; \
     } \
 }
+
+/* Get null-terminated string of size up to 'size', store
+ * result in 'dest', go to 'cleanup' upon failure */
 #define FUZZER_GET_STRING(dest, max) { \
     (dest) = NULL; \
     if ( ((dest) = fuzzer_get_string(max)) == NULL ) { \
@@ -38,6 +45,9 @@ void test_undefined_memory(void* vp, size_t s);
     } \
 }
 
+/* Get null-terminated string of size up to 'size' using
+ * garbage collector 'gc', store result in 'dest',
+ * go to 'cleanup' upon failure */
 #define FUZZER_GET_STRING_GC(dest, max, gc) { \
     (dest) = NULL; \
     if ( ((dest) = fuzzer_get_string_gc((max), (gc))) == NULL ) { \