winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

pure_routines.h (5946B)


      1 int pure_eq(
      2   const uint8_t* buffer,
      3   const uint64_t buffer_size,   // The absolute length of the entire buffer.
      4   const uint64_t buffer_offset, // The offset from which to start comparing.
      5   const uint8_t* string,
      6   const uint64_t string_size
      7 ) {
      8   assert(buffer_offset <= buffer_size);
      9   assert(string_size > 0);
     10   if (buffer_offset + string_size > buffer_size) return 0;
     11   return memcmp(buffer + buffer_offset, string, (size_t) string_size) == 0;
     12 }
     13 
     14 int pure_free(uint8_t** data, uint64_t* data_size) {
     15   if (*data_size == 0) {
     16     assert(*data == NULL);
     17     // We never call malloc for 0.
     18     // We always assert that `required` is greater than 0.
     19     // We may therefore use `data_size == 0` to indicate the lack of allocation.
     20   } else {
     21     assert(*data != NULL);
     22     free(*data);
     23     *data = NULL;
     24     *data_size = 0;
     25   }
     26   return 0;
     27 }
     28 
     29 int pure_overflow(
     30   const uint64_t offset,
     31   const uint64_t length,
     32   const uint64_t available
     33 ) {
     34   if (available < length) return 1;
     35   if (offset > available - length) return 1;
     36   return 0;
     37 }
     38 
     39 int pure_realloc(
     40   uint8_t** data,
     41   uint64_t* data_size,
     42   const uint64_t required
     43 ) {
     44   assert(required > 0); // N.B. See comment in pure_free().
     45   assert(required <= SIZE_MAX);
     46   if (*data_size > 0 && *data_size < required) {
     47     pure_free(data, data_size);
     48     assert(*data == NULL);
     49     assert(*data_size == 0);
     50   }
     51   if (*data_size == 0) {
     52     assert(*data == NULL);
     53     uint64_t size = required;
     54     if (size < PURE_MALLOC_MIN) size = PURE_MALLOC_MIN;
     55     *data = (uint8_t*) malloc(size);
     56     if (*data == NULL) return PURE_E_MALLOC;
     57     *data_size = size;
     58   }
     59   assert(*data != NULL);
     60   assert(*data_size >= required);
     61   return 0;
     62 }
     63 
     64 int pure_search(
     65   const uint8_t* buffer,
     66   const uint64_t buffer_size,
     67   const uint64_t search_offset,
     68         uint64_t search_size,
     69   const uint8_t* string,
     70   const uint64_t string_size,
     71   uint64_t* offset
     72 ) {
     73   assert(*offset == 0);
     74   assert(string_size > 0);
     75   if (search_offset >= buffer_size) return PURE_E_STRING_NOT_FOUND;
     76   if (search_offset + search_size > buffer_size) {
     77     search_size = buffer_size - search_offset;
     78   }
     79   assert(search_offset + search_size <= buffer_size);
     80   if (search_size < string_size) return PURE_E_STRING_NOT_FOUND;
     81   uint64_t index = search_offset;
     82   uint64_t length = search_offset + search_size - string_size;
     83   assert(length + string_size <= buffer_size);
     84   while (index < length) {
     85     if (
     86       // Avoid a function call most of the time:
     87       buffer[index] == string[0] &&
     88       // Check the string in full:
     89       pure_eq(
     90         buffer,
     91         buffer_size,
     92         index,
     93         string,
     94         string_size
     95       )
     96     ) {
     97       *offset = index;
     98       return 0;
     99     }
    100     index++;
    101   }
    102   return PURE_E_STRING_NOT_FOUND;
    103 }
    104 
    105 uint16_t pure_u16(const uint8_t* buffer) {
    106   const uint8_t a = buffer[0];
    107   const uint8_t b = buffer[1];
    108   return (a << 0) | (b << 8);
    109 }
    110 
    111 uint32_t pure_u32(const uint8_t* buffer) {
    112   const uint8_t a = buffer[0];
    113   const uint8_t b = buffer[1];
    114   const uint8_t c = buffer[2];
    115   const uint8_t d = buffer[3];
    116   return (a << 0) | (b << 8) | (c << 16) | (d << 24);
    117 }
    118 
    119 uint64_t pure_u64(const uint8_t* buffer) {
    120   const uint32_t a = pure_u32(buffer + 0);
    121   const uint32_t b = pure_u32(buffer + 4);
    122   return ((uint64_t) b << 32) + a;
    123 }
    124 
    125 int pure_zeroes(
    126   const uint8_t* buffer, 
    127         uint64_t offset,
    128   const uint64_t length
    129 ) {
    130   assert(offset <= length);
    131   // TO DO: Optimize: Perform 64-bit comparisons:
    132   while (offset < length) {
    133     if (buffer[offset++] != 0) return 0;
    134   }
    135   return 1;
    136 }
    137 
    138 // Find end of component delimited by slash or EOF.
    139 uint64_t pure_path_component_index(
    140   const uint8_t* path,
    141   uint64_t index,
    142   const uint64_t length
    143 ) {
    144   assert(index <= length);
    145   while (index < length) {
    146     if (path[index] == PURE_BACKSLASH || path[index] == PURE_FORWARD_SLASH) {
    147       return index;
    148     } else {
    149       index++;
    150     }
    151   }
    152   return index;
    153 }
    154 
    155 int pure_path_component_overflow(const uint8_t* path, const uint64_t length) {
    156   if (length < PURE_PATH_COMPONENT_MAX) return 0;
    157   uint64_t start = 0;
    158   while (start < length) {
    159     uint64_t end = pure_path_component_index(path, start, length);
    160     if (end - start > PURE_PATH_COMPONENT_MAX) return 1;
    161     start = end + 1;
    162   }
    163   return 0;
    164 }
    165 
    166 int pure_path_control_characters_iconr(
    167   const uint8_t* path,
    168   const uint64_t length
    169 ) {
    170   if (length < PURE_L_ICONR) return 0;
    171   uint64_t offset = length - PURE_L_ICONR;
    172   if (!pure_eq(path, length, offset, PURE_S_ICONR, PURE_L_ICONR)) return 0;
    173   return (
    174     offset == 0 ||
    175     // Do not fall for partial path component matches:
    176     path[offset - 1] == PURE_BACKSLASH ||
    177     path[offset - 1] == PURE_FORWARD_SLASH
    178   );
    179 }
    180 
    181 int pure_path_control_characters(const uint8_t* path, const uint64_t length) {
    182   // We want to check for control characters, except the "\r" in "Icon\r" files:
    183   uint64_t excluding_iconr_length = (uint64_t) length;
    184   if (pure_path_control_characters_iconr(path, length)) {
    185     assert(excluding_iconr_length >= PURE_L_ICONR);
    186     excluding_iconr_length -= PURE_L_ICONR;
    187   }
    188   for (uint64_t index = 0; index < excluding_iconr_length; index++) {
    189     if (PURE_CONTROL_CHARACTER[path[index]]) return 1;
    190   }
    191   return 0;
    192 }
    193 
    194 int pure_path_double_dots(const uint8_t* path, const uint64_t length) {
    195   uint64_t start = 0;
    196   while (start < length) {
    197     uint64_t end = pure_path_component_index(path, start, length);
    198     // Check two-character components for double dots (".."):
    199     if (end - start == 2 && path[start + 0] == 46 && path[start + 1] == 46) {
    200       return 1;
    201     }
    202     start = end + 1;
    203   }
    204   return 0;
    205 }
    206 
    207 int pure_path_drive(const uint8_t* path, const uint64_t length) {
    208   return (
    209     length >= 2 &&
    210     path[1] == 58 && // ":"
    211     path[0] >= 65 && // "A"
    212     path[0] <= 122   // "z"
    213   );
    214 }
    215 
    216 int pure_path_relative(const uint8_t* path, const uint64_t length) {
    217   if (length == 0) return 0;
    218   return path[0] == PURE_BACKSLASH || path[0] == PURE_FORWARD_SLASH;
    219 }