LCOV - code coverage report
Current view: top level - aws-c-common/source - string.c (source / functions) Hit Total Coverage
Test: all_fuzz.info Lines: 174 224 77.7 %
Date: 2021-04-23 16:28:21 Functions: 16 21 76.2 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       3             :  * SPDX-License-Identifier: Apache-2.0.
       4             :  */
       5             : #include <aws/common/string.h>
       6             : 
       7      138168 : struct aws_string *aws_string_new_from_c_str(struct aws_allocator *allocator, const char *c_str) {
       8      138168 :     AWS_PRECONDITION(allocator && c_str);
       9      138168 :     return aws_string_new_from_array(allocator, (const uint8_t *)c_str, strlen(c_str));
      10      138168 : }
      11             : 
      12      284938 : struct aws_string *aws_string_new_from_array(struct aws_allocator *allocator, const uint8_t *bytes, size_t len) {
      13      284938 :     AWS_PRECONDITION(allocator);
      14      284938 :     AWS_PRECONDITION(AWS_MEM_IS_READABLE(bytes, len));
      15      284938 :     size_t malloc_size;
      16      284938 :     if (aws_add_size_checked(sizeof(struct aws_string) + 1, len, &malloc_size)) {
      17           0 :         return NULL;
      18           0 :     }
      19      284938 :     struct aws_string *str = aws_mem_acquire(allocator, malloc_size);
      20      284938 :     if (!str) {
      21           0 :         return NULL;
      22           0 :     }
      23      284938 : 
      24      284938 :     /* Fields are declared const, so we need to copy them in like this */
      25      284938 :     *(struct aws_allocator **)(&str->allocator) = allocator;
      26      284938 :     *(size_t *)(&str->len) = len;
      27      284938 :     if (len > 0) {
      28      261214 :         memcpy((void *)str->bytes, bytes, len);
      29      261214 :     }
      30      284938 :     *(uint8_t *)&str->bytes[len] = '\0';
      31      284938 :     AWS_RETURN_WITH_POSTCONDITION(str, aws_string_is_valid(str));
      32      284938 : }
      33             : 
      34      124988 : struct aws_string *aws_string_new_from_string(struct aws_allocator *allocator, const struct aws_string *str) {
      35      124988 :     AWS_PRECONDITION(allocator && aws_string_is_valid(str));
      36      124988 :     return aws_string_new_from_array(allocator, str->bytes, str->len);
      37      124988 : }
      38             : 
      39           0 : struct aws_string *aws_string_new_from_cursor(struct aws_allocator *allocator, const struct aws_byte_cursor *cursor) {
      40           0 :     AWS_PRECONDITION(allocator && aws_byte_cursor_is_valid(cursor));
      41           0 :     return aws_string_new_from_array(allocator, cursor->ptr, cursor->len);
      42           0 : }
      43             : 
      44           0 : struct aws_string *aws_string_new_from_buf(struct aws_allocator *allocator, const struct aws_byte_buf *buf) {
      45           0 :     AWS_PRECONDITION(allocator && aws_byte_buf_is_valid(buf));
      46           0 :     return aws_string_new_from_array(allocator, buf->buffer, buf->len);
      47           0 : }
      48             : 
      49      245782 : void aws_string_destroy(struct aws_string *str) {
      50      245782 :     AWS_PRECONDITION(!str || aws_string_is_valid(str));
      51      245782 :     if (str && str->allocator) {
      52       87385 :         aws_mem_release(str->allocator, str);
      53       87385 :     }
      54      245782 : }
      55             : 
      56           0 : void aws_string_destroy_secure(struct aws_string *str) {
      57           0 :     AWS_PRECONDITION(!str || aws_string_is_valid(str));
      58           0 :     if (str) {
      59           0 :         aws_secure_zero((void *)aws_string_bytes(str), str->len);
      60           0 :         if (str->allocator) {
      61           0 :             aws_mem_release(str->allocator, str);
      62           0 :         }
      63           0 :     }
      64           0 : }
      65             : 
      66      199616 : int aws_string_compare(const struct aws_string *a, const struct aws_string *b) {
      67      199616 :     AWS_PRECONDITION(!a || aws_string_is_valid(a));
      68      199616 :     AWS_PRECONDITION(!b || aws_string_is_valid(b));
      69      199616 :     if (a == b) {
      70      124118 :         return 0; /* strings identical */
      71      124118 :     }
      72       75498 :     if (a == NULL) {
      73        3833 :         return -1;
      74        3833 :     }
      75       71665 :     if (b == NULL) {
      76        3430 :         return 1;
      77        3430 :     }
      78       68235 : 
      79       68235 :     size_t len_a = a->len;
      80       68235 :     size_t len_b = b->len;
      81       68235 :     size_t min_len = len_a < len_b ? len_a : len_b;
      82       68235 : 
      83       68235 :     int ret = memcmp(aws_string_bytes(a), aws_string_bytes(b), min_len);
      84       68235 :     AWS_POSTCONDITION(aws_string_is_valid(a));
      85       68235 :     AWS_POSTCONDITION(aws_string_is_valid(b));
      86       68235 :     if (ret) {
      87       52719 :         return ret; /* overlapping characters differ */
      88       52719 :     }
      89       15516 :     if (len_a == len_b) {
      90        1471 :         return 0; /* strings identical */
      91        1471 :     }
      92       14045 :     if (len_a > len_b) {
      93       10831 :         return 1; /* string b is first n characters of string a */
      94       10831 :     }
      95        3214 :     return -1; /* string a is first n characters of string b */
      96        3214 : }
      97             : 
      98      127450 : int aws_array_list_comparator_string(const void *a, const void *b) {
      99      127450 :     if (a == b) {
     100       36016 :         return 0; /* strings identical */
     101       36016 :     }
     102       91434 :     if (a == NULL) {
     103        9245 :         return -1;
     104        9245 :     }
     105       82189 :     if (b == NULL) {
     106       10769 :         return 1;
     107       10769 :     }
     108       71420 :     const struct aws_string *str_a = *(const struct aws_string **)a;
     109       71420 :     const struct aws_string *str_b = *(const struct aws_string **)b;
     110       71420 :     return aws_string_compare(str_a, str_b);
     111       71420 : }
     112             : 
     113             : /**
     114             :  * Returns true if bytes of string are the same, false otherwise.
     115             :  */
     116      253393 : bool aws_string_eq(const struct aws_string *a, const struct aws_string *b) {
     117      253393 :     AWS_PRECONDITION(!a || aws_string_is_valid(a));
     118      253393 :     AWS_PRECONDITION(!b || aws_string_is_valid(b));
     119      253393 :     if (a == b) {
     120      101240 :         return true;
     121      101240 :     }
     122      152153 :     if (a == NULL || b == NULL) {
     123       11412 :         return false;
     124       11412 :     }
     125      140741 :     return aws_array_eq(a->bytes, a->len, b->bytes, b->len);
     126      140741 : }
     127             : 
     128             : /**
     129             :  * Returns true if bytes of string are equivalent, using a case-insensitive comparison.
     130             :  */
     131      123907 : bool aws_string_eq_ignore_case(const struct aws_string *a, const struct aws_string *b) {
     132      123907 :     AWS_PRECONDITION(!a || aws_string_is_valid(a));
     133      123907 :     AWS_PRECONDITION(!b || aws_string_is_valid(b));
     134      123907 :     if (a == b) {
     135       21467 :         return true;
     136       21467 :     }
     137      102440 :     if (a == NULL || b == NULL) {
     138       26596 :         return false;
     139       26596 :     }
     140       75844 :     return aws_array_eq_ignore_case(a->bytes, a->len, b->bytes, b->len);
     141       75844 : }
     142             : 
     143             : /**
     144             :  * Returns true if bytes of string and cursor are the same, false otherwise.
     145             :  */
     146      133543 : bool aws_string_eq_byte_cursor(const struct aws_string *str, const struct aws_byte_cursor *cur) {
     147      133543 :     AWS_PRECONDITION(!str || aws_string_is_valid(str));
     148      133543 :     AWS_PRECONDITION(!cur || aws_byte_cursor_is_valid(cur));
     149      133543 :     if (str == NULL && cur == NULL) {
     150        5897 :         return true;
     151        5897 :     }
     152      127646 :     if (str == NULL || cur == NULL) {
     153       52563 :         return false;
     154       52563 :     }
     155       75083 :     return aws_array_eq(str->bytes, str->len, cur->ptr, cur->len);
     156       75083 : }
     157             : 
     158             : /**
     159             :  * Returns true if bytes of string and cursor are equivalent, using a case-insensitive comparison.
     160             :  */
     161             : 
     162      124509 : bool aws_string_eq_byte_cursor_ignore_case(const struct aws_string *str, const struct aws_byte_cursor *cur) {
     163      124509 :     AWS_PRECONDITION(!str || aws_string_is_valid(str));
     164      124509 :     AWS_PRECONDITION(!cur || aws_byte_cursor_is_valid(cur));
     165      124509 :     if (str == NULL && cur == NULL) {
     166        8810 :         return true;
     167        8810 :     }
     168      115699 :     if (str == NULL || cur == NULL) {
     169       53195 :         return false;
     170       53195 :     }
     171       62504 :     return aws_array_eq_ignore_case(str->bytes, str->len, cur->ptr, cur->len);
     172       62504 : }
     173             : 
     174             : /**
     175             :  * Returns true if bytes of string and buffer are the same, false otherwise.
     176             :  */
     177      125957 : bool aws_string_eq_byte_buf(const struct aws_string *str, const struct aws_byte_buf *buf) {
     178      125957 :     AWS_PRECONDITION(!str || aws_string_is_valid(str));
     179      125957 :     AWS_PRECONDITION(!buf || aws_byte_buf_is_valid(buf));
     180      125957 :     if (str == NULL && buf == NULL) {
     181        8008 :         return true;
     182        8008 :     }
     183      117949 :     if (str == NULL || buf == NULL) {
     184       54995 :         return false;
     185       54995 :     }
     186       62954 :     return aws_array_eq(str->bytes, str->len, buf->buffer, buf->len);
     187       62954 : }
     188             : 
     189             : /**
     190             :  * Returns true if bytes of string and buffer are equivalent, using a case-insensitive comparison.
     191             :  */
     192             : 
     193      117686 : bool aws_string_eq_byte_buf_ignore_case(const struct aws_string *str, const struct aws_byte_buf *buf) {
     194      117686 :     AWS_PRECONDITION(!str || aws_string_is_valid(str));
     195      117686 :     AWS_PRECONDITION(!buf || aws_byte_buf_is_valid(buf));
     196      117686 :     if (str == NULL && buf == NULL) {
     197        5793 :         return true;
     198        5793 :     }
     199      111893 :     if (str == NULL || buf == NULL) {
     200       41620 :         return false;
     201       41620 :     }
     202       70273 :     return aws_array_eq_ignore_case(str->bytes, str->len, buf->buffer, buf->len);
     203       70273 : }
     204             : 
     205      132217 : bool aws_string_eq_c_str(const struct aws_string *str, const char *c_str) {
     206      132217 :     AWS_PRECONDITION(!str || aws_string_is_valid(str));
     207      132217 :     if (str == NULL && c_str == NULL) {
     208        3814 :         return true;
     209        3814 :     }
     210      128403 :     if (str == NULL || c_str == NULL) {
     211       37234 :         return false;
     212       37234 :     }
     213       91169 :     return aws_array_eq_c_str(str->bytes, str->len, c_str);
     214       91169 : }
     215             : 
     216             : /**
     217             :  * Returns true if bytes of strings are equivalent, using a case-insensitive comparison.
     218             :  */
     219      128784 : bool aws_string_eq_c_str_ignore_case(const struct aws_string *str, const char *c_str) {
     220      128784 :     AWS_PRECONDITION(!str || aws_string_is_valid(str));
     221      128784 :     if (str == NULL && c_str == NULL) {
     222        4596 :         return true;
     223        4596 :     }
     224      124188 :     if (str == NULL || c_str == NULL) {
     225       50235 :         return false;
     226       50235 :     }
     227       73953 :     return aws_array_eq_c_str_ignore_case(str->bytes, str->len, c_str);
     228       73953 : }
     229             : 
     230             : bool aws_byte_buf_write_from_whole_string(
     231             :     struct aws_byte_buf *AWS_RESTRICT buf,
     232       75578 :     const struct aws_string *AWS_RESTRICT src) {
     233       75578 :     AWS_PRECONDITION(!buf || aws_byte_buf_is_valid(buf));
     234       75578 :     AWS_PRECONDITION(!src || aws_string_is_valid(src));
     235       75578 :     if (buf == NULL || src == NULL) {
     236       36176 :         return false;
     237       36176 :     }
     238       39402 :     return aws_byte_buf_write(buf, aws_string_bytes(src), src->len);
     239       39402 : }
     240             : 
     241             : /**
     242             :  * Creates an aws_byte_cursor from an existing string.
     243             :  */
     244      136305 : struct aws_byte_cursor aws_byte_cursor_from_string(const struct aws_string *src) {
     245      136305 :     AWS_PRECONDITION(aws_string_is_valid(src));
     246      136305 :     return aws_byte_cursor_from_array(aws_string_bytes(src), src->len);
     247      136305 : }
     248             : 
     249           0 : struct aws_string *aws_string_clone_or_reuse(struct aws_allocator *allocator, const struct aws_string *str) {
     250           0 :     AWS_PRECONDITION(allocator);
     251           0 :     AWS_PRECONDITION(aws_string_is_valid(str));
     252           0 : 
     253           0 :     if (str->allocator == NULL) {
     254           0 :         /* Since the string cannot be deallocated, we assume that it will remain valid for the lifetime of the
     255           0 :          * application */
     256           0 :         AWS_POSTCONDITION(aws_string_is_valid(str));
     257           0 :         return (struct aws_string *)str;
     258           0 :     }
     259           0 : 
     260           0 :     AWS_POSTCONDITION(aws_string_is_valid(str));
     261           0 :     return aws_string_new_from_string(allocator, str);
     262           0 : }
     263             : 
     264           0 : int aws_secure_strlen(const char *str, size_t max_read_len, size_t *str_len) {
     265           0 :     AWS_ERROR_PRECONDITION(str && str_len, AWS_ERROR_INVALID_ARGUMENT);
     266           0 : 
     267           0 :     /* why not strnlen? It doesn't work everywhere as it wasn't standardized til C11, and is considered
     268           0 :      * a GNU extension. This should be faster anyways. This should work for ascii and utf8.
     269           0 :      * Any other character sets in use deserve what they get. */
     270           0 :     char *null_char_ptr = memchr(str, '\0', max_read_len);
     271           0 : 
     272           0 :     if (null_char_ptr) {
     273           0 :         *str_len = null_char_ptr - str;
     274           0 :         return AWS_OP_SUCCESS;
     275           0 :     }
     276           0 : 
     277           0 :     return aws_raise_error(AWS_ERROR_C_STRING_BUFFER_NOT_NULL_TERMINATED);
     278           0 : }

Generated by: LCOV version 1.13