Răsfoiți Sursa

bstruct, OTPChecker: fix overflows in size computation

ambrop7 14 ani în urmă
părinte
comite
8e3eda263f

+ 37 - 13
bstruct_generator/bstruct_functions.php

@@ -117,8 +117,10 @@ function generate_header ($name, $directives, $structures)
 */
 
 #include <stdint.h>
+#include <limits.h>
 
 #include <misc/balign.h>
+#include <misc/debug.h>
 
 
 EOD;
@@ -160,10 +162,10 @@ EOD;
             }
 
             echo <<<EOD
-    int {$entry["name"]}_off;
-    int {$entry["name"]}_size;
+    size_t {$entry["name"]}_off;
+    size_t {$entry["name"]}_size;
     #ifndef NDEBUG
-    int {$entry["name"]}_count;
+    size_t {$entry["name"]}_count;
     #endif
 
 
@@ -171,15 +173,17 @@ EOD;
         }
 
         echo <<<EOD
-    int len;
-    int align;
+    size_t len;
+    size_t align;
 } {$struct["name"]}Params;
 
-static void {$struct["name"]}Params_Init ({$struct["name"]}Params *o{$add_parameters})
+static int {$struct["name"]}Params_Init ({$struct["name"]}Params *o{$add_parameters}) WARN_UNUSED;
+
+static int {$struct["name"]}Params_Init ({$struct["name"]}Params *o{$add_parameters})
 {
-    int cur_size;
-    int cur_align;
-    int cur_count;
+    size_t cur_size;
+    size_t cur_align;
+    size_t cur_count;
 
     o->len = 0;
     o->align = 1;
@@ -200,7 +204,9 @@ EOD;
                     $init_add_parameters = ", {$entry["type"]["parameters"]}";
                 }
                 echo <<<EOD
-    {$entry["type"]["name"]}Params_Init(&o->{$entry["name"]}_params{$init_add_parameters});
+    if (!{$entry["type"]["name"]}Params_Init(&o->{$entry["name"]}_params{$init_add_parameters})) {
+        return 0;
+    }
 
 EOD;
             }
@@ -211,22 +217,39 @@ EOD;
 
 
             echo <<<EOD
+    if ({$size} > SIZE_MAX) {
+        return 0;
+    }
     cur_size = {$size};
+    if ({$align} > SIZE_MAX) {
+        return 0;
+    }
     cur_align = {$align};
+    if ({$entry["num"]} > SIZE_MAX) {
+        return 0;
+    }
     cur_count = ({$entry["num"]});
 
 EOD;
 
             $off = "balign_up(o->len, cur_align)";
-            $len = "(cur_count * cur_size)";
 
             echo <<<EOD
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->{$entry["name"]}_off = {$off};
     o->{$entry["name"]}_size = cur_size;
     #ifndef NDEBUG
     o->{$entry["name"]}_count = cur_count;
     #endif
-    o->len = o->{$entry["name"]}_off + {$len};
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->{$entry["name"]}_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->{$entry["name"]}_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
 
@@ -234,6 +257,7 @@ EOD;
         }
 
         echo <<<EOD
+    return 1;
 }
 
 
@@ -247,7 +271,7 @@ static {$entry["type"]["ctype"]} * {$struct["name"]}_{$entry["name"]} ({$struct[
     return ({$entry["type"]["ctype"]} *)((uint8_t *)s + o->{$entry["name"]}_off);
 }
 
-static {$entry["type"]["ctype"]} * {$struct["name"]}_{$entry["name"]}_at ({$struct["name"]}Params *o, {$struct["name"]} *s, int i)
+static {$entry["type"]["ctype"]} * {$struct["name"]}_{$entry["name"]}_at ({$struct["name"]}Params *o, {$struct["name"]} *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->{$entry["name"]}_count)

+ 92 - 28
generated/bstruct_OTPChecker.h

@@ -4,60 +4,101 @@
 */
 
 #include <stdint.h>
+#include <limits.h>
 
 #include <misc/balign.h>
+#include <misc/debug.h>
 
 
 typedef struct oc_table_struct oc_table;
 
 typedef struct {
-    int id_off;
-    int id_size;
+    size_t id_off;
+    size_t id_size;
     #ifndef NDEBUG
-    int id_count;
+    size_t id_count;
     #endif
 
-    int entries_off;
-    int entries_size;
+    size_t entries_off;
+    size_t entries_size;
     #ifndef NDEBUG
-    int entries_count;
+    size_t entries_count;
     #endif
 
-    int len;
-    int align;
+    size_t len;
+    size_t align;
 } oc_tableParams;
 
-static void oc_tableParams_Init (oc_tableParams *o, int num_entries)
+static int oc_tableParams_Init (oc_tableParams *o, int num_entries) WARN_UNUSED;
+
+static int oc_tableParams_Init (oc_tableParams *o, int num_entries)
 {
-    int cur_size;
-    int cur_align;
-    int cur_count;
+    size_t cur_size;
+    size_t cur_align;
+    size_t cur_count;
 
     o->len = 0;
     o->align = 1;
 
+    if ((sizeof(uint16_t)) > SIZE_MAX) {
+        return 0;
+    }
     cur_size = (sizeof(uint16_t));
+    if ((__alignof__(uint16_t)) > SIZE_MAX) {
+        return 0;
+    }
     cur_align = (__alignof__(uint16_t));
+    if (1 > SIZE_MAX) {
+        return 0;
+    }
     cur_count = (1);
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->id_off = balign_up(o->len, cur_align);
     o->id_size = cur_size;
     #ifndef NDEBUG
     o->id_count = cur_count;
     #endif
-    o->len = o->id_off + (cur_count * cur_size);
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->id_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->id_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
+    if ((sizeof(struct OTPChecker_entry)) > SIZE_MAX) {
+        return 0;
+    }
     cur_size = (sizeof(struct OTPChecker_entry));
+    if ((__alignof__(struct OTPChecker_entry)) > SIZE_MAX) {
+        return 0;
+    }
     cur_align = (__alignof__(struct OTPChecker_entry));
+    if (num_entries > SIZE_MAX) {
+        return 0;
+    }
     cur_count = (num_entries);
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->entries_off = balign_up(o->len, cur_align);
     o->entries_size = cur_size;
     #ifndef NDEBUG
     o->entries_count = cur_count;
     #endif
-    o->len = o->entries_off + (cur_count * cur_size);
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->entries_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->entries_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
+    return 1;
 }
 
 static uint16_t * oc_table_id (oc_tableParams *o, oc_table *s)
@@ -65,7 +106,7 @@ static uint16_t * oc_table_id (oc_tableParams *o, oc_table *s)
     return (uint16_t *)((uint8_t *)s + o->id_off);
 }
 
-static uint16_t * oc_table_id_at (oc_tableParams *o, oc_table *s, int i)
+static uint16_t * oc_table_id_at (oc_tableParams *o, oc_table *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->id_count)
@@ -78,7 +119,7 @@ static struct OTPChecker_entry * oc_table_entries (oc_tableParams *o, oc_table *
     return (struct OTPChecker_entry *)((uint8_t *)s + o->entries_off);
 }
 
-static struct OTPChecker_entry * oc_table_entries_at (oc_tableParams *o, oc_table *s, int i)
+static struct OTPChecker_entry * oc_table_entries_at (oc_tableParams *o, oc_table *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->entries_count)
@@ -90,37 +131,60 @@ typedef struct oc_tables_struct oc_tables;
 
 typedef struct {
     oc_tableParams tables_params;
-    int tables_off;
-    int tables_size;
+    size_t tables_off;
+    size_t tables_size;
     #ifndef NDEBUG
-    int tables_count;
+    size_t tables_count;
     #endif
 
-    int len;
-    int align;
+    size_t len;
+    size_t align;
 } oc_tablesParams;
 
-static void oc_tablesParams_Init (oc_tablesParams *o, int num_tables, int num_entries)
+static int oc_tablesParams_Init (oc_tablesParams *o, int num_tables, int num_entries) WARN_UNUSED;
+
+static int oc_tablesParams_Init (oc_tablesParams *o, int num_tables, int num_entries)
 {
-    int cur_size;
-    int cur_align;
-    int cur_count;
+    size_t cur_size;
+    size_t cur_align;
+    size_t cur_count;
 
     o->len = 0;
     o->align = 1;
 
-    oc_tableParams_Init(&o->tables_params, num_entries);
+    if (!oc_tableParams_Init(&o->tables_params, num_entries)) {
+        return 0;
+    }
+    if (o->tables_params.len > SIZE_MAX) {
+        return 0;
+    }
     cur_size = o->tables_params.len;
+    if (o->tables_params.align > SIZE_MAX) {
+        return 0;
+    }
     cur_align = o->tables_params.align;
+    if (num_tables > SIZE_MAX) {
+        return 0;
+    }
     cur_count = (num_tables);
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->tables_off = balign_up(o->len, cur_align);
     o->tables_size = cur_size;
     #ifndef NDEBUG
     o->tables_count = cur_count;
     #endif
-    o->len = o->tables_off + (cur_count * cur_size);
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->tables_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->tables_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
+    return 1;
 }
 
 static oc_table * oc_tables_tables (oc_tablesParams *o, oc_tables *s)
@@ -128,7 +192,7 @@ static oc_table * oc_tables_tables (oc_tablesParams *o, oc_tables *s)
     return (oc_table *)((uint8_t *)s + o->tables_off);
 }
 
-static oc_table * oc_tables_tables_at (oc_tablesParams *o, oc_tables *s, int i)
+static oc_table * oc_tables_tables_at (oc_tablesParams *o, oc_tables *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->tables_count)

+ 138 - 38
generated/bstruct_bstruct_test.h

@@ -4,43 +4,66 @@
 */
 
 #include <stdint.h>
+#include <limits.h>
 
 #include <misc/balign.h>
+#include <misc/debug.h>
 
 
 typedef struct str0_struct str0;
 
 typedef struct {
-    int x_off;
-    int x_size;
+    size_t x_off;
+    size_t x_size;
     #ifndef NDEBUG
-    int x_count;
+    size_t x_count;
     #endif
 
-    int len;
-    int align;
+    size_t len;
+    size_t align;
 } str0Params;
 
-static void str0Params_Init (str0Params *o, int n)
+static int str0Params_Init (str0Params *o, int n) WARN_UNUSED;
+
+static int str0Params_Init (str0Params *o, int n)
 {
-    int cur_size;
-    int cur_align;
-    int cur_count;
+    size_t cur_size;
+    size_t cur_align;
+    size_t cur_count;
 
     o->len = 0;
     o->align = 1;
 
+    if ((sizeof(int)) > SIZE_MAX) {
+        return 0;
+    }
     cur_size = (sizeof(int));
+    if ((__alignof__(int)) > SIZE_MAX) {
+        return 0;
+    }
     cur_align = (__alignof__(int));
+    if (n > SIZE_MAX) {
+        return 0;
+    }
     cur_count = (n);
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->x_off = balign_up(o->len, cur_align);
     o->x_size = cur_size;
     #ifndef NDEBUG
     o->x_count = cur_count;
     #endif
-    o->len = o->x_off + (cur_count * cur_size);
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->x_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->x_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
+    return 1;
 }
 
 static int * str0_x (str0Params *o, str0 *s)
@@ -48,7 +71,7 @@ static int * str0_x (str0Params *o, str0 *s)
     return (int *)((uint8_t *)s + o->x_off);
 }
 
-static int * str0_x_at (str0Params *o, str0 *s, int i)
+static int * str0_x_at (str0Params *o, str0 *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->x_count)
@@ -59,89 +82,166 @@ static int * str0_x_at (str0Params *o, str0 *s, int i)
 typedef struct str1_struct str1;
 
 typedef struct {
-    int a_off;
-    int a_size;
+    size_t a_off;
+    size_t a_size;
     #ifndef NDEBUG
-    int a_count;
+    size_t a_count;
     #endif
 
-    int b_off;
-    int b_size;
+    size_t b_off;
+    size_t b_size;
     #ifndef NDEBUG
-    int b_count;
+    size_t b_count;
     #endif
 
-    int c_off;
-    int c_size;
+    size_t c_off;
+    size_t c_size;
     #ifndef NDEBUG
-    int c_count;
+    size_t c_count;
     #endif
 
     str0Params d_params;
-    int d_off;
-    int d_size;
+    size_t d_off;
+    size_t d_size;
     #ifndef NDEBUG
-    int d_count;
+    size_t d_count;
     #endif
 
-    int len;
-    int align;
+    size_t len;
+    size_t align;
 } str1Params;
 
-static void str1Params_Init (str1Params *o, int nb, int nc, int m)
+static int str1Params_Init (str1Params *o, int nb, int nc, int m) WARN_UNUSED;
+
+static int str1Params_Init (str1Params *o, int nb, int nc, int m)
 {
-    int cur_size;
-    int cur_align;
-    int cur_count;
+    size_t cur_size;
+    size_t cur_align;
+    size_t cur_count;
 
     o->len = 0;
     o->align = 1;
 
+    if ((sizeof(int)) > SIZE_MAX) {
+        return 0;
+    }
     cur_size = (sizeof(int));
+    if ((__alignof__(int)) > SIZE_MAX) {
+        return 0;
+    }
     cur_align = (__alignof__(int));
+    if (1 > SIZE_MAX) {
+        return 0;
+    }
     cur_count = (1);
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->a_off = balign_up(o->len, cur_align);
     o->a_size = cur_size;
     #ifndef NDEBUG
     o->a_count = cur_count;
     #endif
-    o->len = o->a_off + (cur_count * cur_size);
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->a_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->a_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
+    if ((sizeof(char)) > SIZE_MAX) {
+        return 0;
+    }
     cur_size = (sizeof(char));
+    if ((__alignof__(char)) > SIZE_MAX) {
+        return 0;
+    }
     cur_align = (__alignof__(char));
+    if (nb > SIZE_MAX) {
+        return 0;
+    }
     cur_count = (nb);
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->b_off = balign_up(o->len, cur_align);
     o->b_size = cur_size;
     #ifndef NDEBUG
     o->b_count = cur_count;
     #endif
-    o->len = o->b_off + (cur_count * cur_size);
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->b_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->b_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
+    if ((sizeof(double)) > SIZE_MAX) {
+        return 0;
+    }
     cur_size = (sizeof(double));
+    if ((__alignof__(double)) > SIZE_MAX) {
+        return 0;
+    }
     cur_align = (__alignof__(double));
+    if (nc > SIZE_MAX) {
+        return 0;
+    }
     cur_count = (nc);
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->c_off = balign_up(o->len, cur_align);
     o->c_size = cur_size;
     #ifndef NDEBUG
     o->c_count = cur_count;
     #endif
-    o->len = o->c_off + (cur_count * cur_size);
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->c_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->c_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
-    str0Params_Init(&o->d_params, m);
+    if (!str0Params_Init(&o->d_params, m)) {
+        return 0;
+    }
+    if (o->d_params.len > SIZE_MAX) {
+        return 0;
+    }
     cur_size = o->d_params.len;
+    if (o->d_params.align > SIZE_MAX) {
+        return 0;
+    }
     cur_align = o->d_params.align;
+    if (1 > SIZE_MAX) {
+        return 0;
+    }
     cur_count = (1);
+    if (balign_up_overflows(o->len, cur_align)) {
+        return 0;
+    }
     o->d_off = balign_up(o->len, cur_align);
     o->d_size = cur_size;
     #ifndef NDEBUG
     o->d_count = cur_count;
     #endif
-    o->len = o->d_off + (cur_count * cur_size);
+    if (cur_count > SIZE_MAX / cur_size) {
+        return 0;
+    }
+    if (o->d_off > SIZE_MAX - cur_count * cur_size) {
+        return 0;
+    }
+    o->len = o->d_off + cur_count * cur_size;
     o->align = (cur_align > o->align ? cur_align : o->align);
 
+    return 1;
 }
 
 static int * str1_a (str1Params *o, str1 *s)
@@ -149,7 +249,7 @@ static int * str1_a (str1Params *o, str1 *s)
     return (int *)((uint8_t *)s + o->a_off);
 }
 
-static int * str1_a_at (str1Params *o, str1 *s, int i)
+static int * str1_a_at (str1Params *o, str1 *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->a_count)
@@ -162,7 +262,7 @@ static char * str1_b (str1Params *o, str1 *s)
     return (char *)((uint8_t *)s + o->b_off);
 }
 
-static char * str1_b_at (str1Params *o, str1 *s, int i)
+static char * str1_b_at (str1Params *o, str1 *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->b_count)
@@ -175,7 +275,7 @@ static double * str1_c (str1Params *o, str1 *s)
     return (double *)((uint8_t *)s + o->c_off);
 }
 
-static double * str1_c_at (str1Params *o, str1 *s, int i)
+static double * str1_c_at (str1Params *o, str1 *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->c_count)
@@ -188,7 +288,7 @@ static str0 * str1_d (str1Params *o, str1 *s)
     return (str0 *)((uint8_t *)s + o->d_off);
 }
 
-static str0 * str1_d_at (str1Params *o, str1 *s, int i)
+static str0 * str1_d_at (str1Params *o, str1 *s, size_t i)
 {
     ASSERT(i >= 0)
     ASSERT(i < o->d_count)

+ 6 - 1
security/OTPChecker.c

@@ -155,6 +155,9 @@ int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables, B
     mc->handler = NULL;
     
     // set number of entries
+    if (mc->num_otps > INT_MAX / 2) {
+        goto fail0;
+    }
     mc->num_entries = 2 * mc->num_otps;
     
     // set no tables used
@@ -167,7 +170,9 @@ int OTPChecker_Init (OTPChecker *mc, int num_otps, int cipher, int num_tables, B
     }
     
     // allocate tables
-    oc_tablesParams_Init(&mc->tables_params, mc->num_tables, mc->num_entries);
+    if (!(oc_tablesParams_Init(&mc->tables_params, mc->num_tables, mc->num_entries))) {
+        goto fail1;
+    }
     if (!(mc->tables = malloc(mc->tables_params.len))) {
         goto fail1;
     }

+ 2 - 2
tests/bstruct_test.c

@@ -12,9 +12,9 @@ int main ()
     int m = 6;
     
     str1Params p;
-    str1Params_Init(&p, nb, nc, m);
+    ASSERT_FORCE(str1Params_Init(&p, nb, nc, m))
     
-    printf("len=%d align=%d\n", p.len, p.align);
+    printf("len=%zu align=%zu\n", p.len, p.align);
     
     void *s = malloc(p.len);
     ASSERT_FORCE(s)