Home | History | Annotate | Download | only in libavb
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Permission is hereby granted, free of charge, to any person
      5  * obtaining a copy of this software and associated documentation
      6  * files (the "Software"), to deal in the Software without
      7  * restriction, including without limitation the rights to use, copy,
      8  * modify, merge, publish, distribute, sublicense, and/or sell copies
      9  * of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be
     13  * included in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  */
     24 
     25 #include "avb_util.h"
     26 
     27 #include <stdarg.h>
     28 
     29 uint32_t avb_be32toh(uint32_t in) {
     30   uint8_t* d = (uint8_t*)&in;
     31   uint32_t ret;
     32   ret = ((uint32_t)d[0]) << 24;
     33   ret |= ((uint32_t)d[1]) << 16;
     34   ret |= ((uint32_t)d[2]) << 8;
     35   ret |= ((uint32_t)d[3]);
     36   return ret;
     37 }
     38 
     39 uint64_t avb_be64toh(uint64_t in) {
     40   uint8_t* d = (uint8_t*)&in;
     41   uint64_t ret;
     42   ret = ((uint64_t)d[0]) << 56;
     43   ret |= ((uint64_t)d[1]) << 48;
     44   ret |= ((uint64_t)d[2]) << 40;
     45   ret |= ((uint64_t)d[3]) << 32;
     46   ret |= ((uint64_t)d[4]) << 24;
     47   ret |= ((uint64_t)d[5]) << 16;
     48   ret |= ((uint64_t)d[6]) << 8;
     49   ret |= ((uint64_t)d[7]);
     50   return ret;
     51 }
     52 
     53 /* Converts a 32-bit unsigned integer from host to big-endian byte order. */
     54 uint32_t avb_htobe32(uint32_t in) {
     55   union {
     56     uint32_t word;
     57     uint8_t bytes[4];
     58   } ret;
     59   ret.bytes[0] = (in >> 24) & 0xff;
     60   ret.bytes[1] = (in >> 16) & 0xff;
     61   ret.bytes[2] = (in >> 8) & 0xff;
     62   ret.bytes[3] = in & 0xff;
     63   return ret.word;
     64 }
     65 
     66 /* Converts a 64-bit unsigned integer from host to big-endian byte order. */
     67 uint64_t avb_htobe64(uint64_t in) {
     68   union {
     69     uint64_t word;
     70     uint8_t bytes[8];
     71   } ret;
     72   ret.bytes[0] = (in >> 56) & 0xff;
     73   ret.bytes[1] = (in >> 48) & 0xff;
     74   ret.bytes[2] = (in >> 40) & 0xff;
     75   ret.bytes[3] = (in >> 32) & 0xff;
     76   ret.bytes[4] = (in >> 24) & 0xff;
     77   ret.bytes[5] = (in >> 16) & 0xff;
     78   ret.bytes[6] = (in >> 8) & 0xff;
     79   ret.bytes[7] = in & 0xff;
     80   return ret.word;
     81 }
     82 
     83 int avb_safe_memcmp(const void* s1, const void* s2, size_t n) {
     84   const unsigned char* us1 = s1;
     85   const unsigned char* us2 = s2;
     86   int result = 0;
     87 
     88   if (0 == n) {
     89     return 0;
     90   }
     91 
     92   /*
     93    * Code snippet without data-dependent branch due to Nate Lawson
     94    * (nate (at) root.org) of Root Labs.
     95    */
     96   while (n--) {
     97     result |= *us1++ ^ *us2++;
     98   }
     99 
    100   return result != 0;
    101 }
    102 
    103 bool avb_safe_add_to(uint64_t* value, uint64_t value_to_add) {
    104   uint64_t original_value;
    105 
    106   avb_assert(value != NULL);
    107 
    108   original_value = *value;
    109 
    110   *value += value_to_add;
    111   if (*value < original_value) {
    112     avb_error("Overflow when adding values.\n");
    113     return false;
    114   }
    115 
    116   return true;
    117 }
    118 
    119 bool avb_safe_add(uint64_t* out_result, uint64_t a, uint64_t b) {
    120   uint64_t dummy;
    121   if (out_result == NULL) {
    122     out_result = &dummy;
    123   }
    124   *out_result = a;
    125   return avb_safe_add_to(out_result, b);
    126 }
    127 
    128 bool avb_validate_utf8(const uint8_t* data, size_t num_bytes) {
    129   size_t n;
    130   unsigned int num_cc;
    131 
    132   for (n = 0, num_cc = 0; n < num_bytes; n++) {
    133     uint8_t c = data[n];
    134 
    135     if (num_cc > 0) {
    136       if ((c & (0x80 | 0x40)) == 0x80) {
    137         /* 10xx xxxx */
    138       } else {
    139         goto fail;
    140       }
    141       num_cc--;
    142     } else {
    143       if (c < 0x80) {
    144         num_cc = 0;
    145       } else if ((c & (0x80 | 0x40 | 0x20)) == (0x80 | 0x40)) {
    146         /* 110x xxxx */
    147         num_cc = 1;
    148       } else if ((c & (0x80 | 0x40 | 0x20 | 0x10)) == (0x80 | 0x40 | 0x20)) {
    149         /* 1110 xxxx */
    150         num_cc = 2;
    151       } else if ((c & (0x80 | 0x40 | 0x20 | 0x10 | 0x08)) ==
    152                  (0x80 | 0x40 | 0x20 | 0x10)) {
    153         /* 1111 0xxx */
    154         num_cc = 3;
    155       } else {
    156         goto fail;
    157       }
    158     }
    159   }
    160 
    161   if (num_cc != 0) {
    162     goto fail;
    163   }
    164 
    165   return true;
    166 
    167 fail:
    168   return false;
    169 }
    170 
    171 bool avb_str_concat(char* buf,
    172                     size_t buf_size,
    173                     const char* str1,
    174                     size_t str1_len,
    175                     const char* str2,
    176                     size_t str2_len) {
    177   uint64_t combined_len;
    178 
    179   if (!avb_safe_add(&combined_len, str1_len, str2_len)) {
    180     avb_error("Overflow when adding string sizes.\n");
    181     return false;
    182   }
    183 
    184   if (combined_len > buf_size - 1) {
    185     avb_error("Insufficient buffer space.\n");
    186     return false;
    187   }
    188 
    189   avb_memcpy(buf, str1, str1_len);
    190   avb_memcpy(buf + str1_len, str2, str2_len);
    191   buf[combined_len] = '\0';
    192 
    193   return true;
    194 }
    195 
    196 void* avb_malloc(size_t size) {
    197   void* ret = avb_malloc_(size);
    198   if (ret == NULL) {
    199     avb_error("Failed to allocate memory.\n");
    200     return NULL;
    201   }
    202   return ret;
    203 }
    204 
    205 void* avb_calloc(size_t size) {
    206   void* ret = avb_malloc(size);
    207   if (ret == NULL) {
    208     return NULL;
    209   }
    210 
    211   avb_memset(ret, '\0', size);
    212   return ret;
    213 }
    214 
    215 char* avb_strdup(const char* str) {
    216   size_t len = avb_strlen(str);
    217   char* ret = avb_malloc(len + 1);
    218   if (ret == NULL) {
    219     return NULL;
    220   }
    221 
    222   avb_memcpy(ret, str, len);
    223   ret[len] = '\0';
    224 
    225   return ret;
    226 }
    227 
    228 const char* avb_strstr(const char* haystack, const char* needle) {
    229   size_t n, m;
    230 
    231   /* Look through |haystack| and check if the first character of
    232    * |needle| matches. If so, check the rest of |needle|.
    233    */
    234   for (n = 0; haystack[n] != '\0'; n++) {
    235     if (haystack[n] != needle[0]) {
    236       continue;
    237     }
    238 
    239     for (m = 1;; m++) {
    240       if (needle[m] == '\0') {
    241         return haystack + n;
    242       }
    243 
    244       if (haystack[n + m] != needle[m]) {
    245         break;
    246       }
    247     }
    248   }
    249 
    250   return NULL;
    251 }
    252 
    253 const char* avb_strv_find_str(const char* const* strings,
    254                               const char* str,
    255                               size_t str_size) {
    256   size_t n;
    257   for (n = 0; strings[n] != NULL; n++) {
    258     if (avb_strlen(strings[n]) == str_size &&
    259         avb_memcmp(strings[n], str, str_size) == 0) {
    260       return strings[n];
    261     }
    262   }
    263   return NULL;
    264 }
    265 
    266 char* avb_replace(const char* str, const char* search, const char* replace) {
    267   char* ret = NULL;
    268   size_t ret_len = 0;
    269   size_t search_len, replace_len;
    270   const char* str_after_last_replace;
    271 
    272   search_len = avb_strlen(search);
    273   replace_len = avb_strlen(replace);
    274 
    275   str_after_last_replace = str;
    276   while (*str != '\0') {
    277     const char* s;
    278     size_t num_before;
    279     size_t num_new;
    280 
    281     s = avb_strstr(str, search);
    282     if (s == NULL) {
    283       break;
    284     }
    285 
    286     num_before = s - str;
    287 
    288     if (ret == NULL) {
    289       num_new = num_before + replace_len + 1;
    290       ret = avb_malloc(num_new);
    291       if (ret == NULL) {
    292         goto out;
    293       }
    294       avb_memcpy(ret, str, num_before);
    295       avb_memcpy(ret + num_before, replace, replace_len);
    296       ret[num_new - 1] = '\0';
    297       ret_len = num_new - 1;
    298     } else {
    299       char* new_str;
    300       num_new = ret_len + num_before + replace_len + 1;
    301       new_str = avb_malloc(num_new);
    302       if (ret == NULL) {
    303         goto out;
    304       }
    305       avb_memcpy(new_str, ret, ret_len);
    306       avb_memcpy(new_str + ret_len, str, num_before);
    307       avb_memcpy(new_str + ret_len + num_before, replace, replace_len);
    308       new_str[num_new - 1] = '\0';
    309       avb_free(ret);
    310       ret = new_str;
    311       ret_len = num_new - 1;
    312     }
    313 
    314     str = s + search_len;
    315     str_after_last_replace = str;
    316   }
    317 
    318   if (ret == NULL) {
    319     ret = avb_strdup(str_after_last_replace);
    320     if (ret == NULL) {
    321       goto out;
    322     }
    323   } else {
    324     size_t num_remaining = avb_strlen(str_after_last_replace);
    325     size_t num_new = ret_len + num_remaining + 1;
    326     char* new_str = avb_malloc(num_new);
    327     if (ret == NULL) {
    328       goto out;
    329     }
    330     avb_memcpy(new_str, ret, ret_len);
    331     avb_memcpy(new_str + ret_len, str_after_last_replace, num_remaining);
    332     new_str[num_new - 1] = '\0';
    333     avb_free(ret);
    334     ret = new_str;
    335     ret_len = num_new - 1;
    336   }
    337 
    338 out:
    339   return ret;
    340 }
    341 
    342 /* We only support a limited amount of strings in avb_strdupv(). */
    343 #define AVB_STRDUPV_MAX_NUM_STRINGS 32
    344 
    345 char* avb_strdupv(const char* str, ...) {
    346   va_list ap;
    347   const char* strings[AVB_STRDUPV_MAX_NUM_STRINGS];
    348   size_t lengths[AVB_STRDUPV_MAX_NUM_STRINGS];
    349   size_t num_strings, n;
    350   uint64_t total_length;
    351   char *ret = NULL, *dest;
    352 
    353   num_strings = 0;
    354   total_length = 0;
    355   va_start(ap, str);
    356   do {
    357     size_t str_len = avb_strlen(str);
    358     strings[num_strings] = str;
    359     lengths[num_strings] = str_len;
    360     if (!avb_safe_add_to(&total_length, str_len)) {
    361       avb_fatal("Overflow while determining total length.\n");
    362       break;
    363     }
    364     num_strings++;
    365     if (num_strings == AVB_STRDUPV_MAX_NUM_STRINGS) {
    366       avb_fatal("Too many strings passed.\n");
    367       break;
    368     }
    369     str = va_arg(ap, const char*);
    370   } while (str != NULL);
    371   va_end(ap);
    372 
    373   ret = avb_malloc(total_length + 1);
    374   if (ret == NULL) {
    375     goto out;
    376   }
    377 
    378   dest = ret;
    379   for (n = 0; n < num_strings; n++) {
    380     avb_memcpy(dest, strings[n], lengths[n]);
    381     dest += lengths[n];
    382   }
    383   *dest = '\0';
    384   avb_assert(dest == ret + total_length);
    385 
    386 out:
    387   return ret;
    388 }
    389 
    390 const char* avb_basename(const char* str) {
    391   int64_t n;
    392   size_t len;
    393 
    394   len = avb_strlen(str);
    395   if (len >= 2) {
    396     for (n = len - 2; n >= 0; n--) {
    397       if (str[n] == '/') {
    398         return str + n + 1;
    399       }
    400     }
    401   }
    402   return str;
    403 }
    404