LCOV - code coverage report
Current view: top level - lib/malloc - malloc.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 58 58 100.0 %
Date: 2021-11-24 03:28:48 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2003, Roger Dingledine
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : /**
       7             :  * \file malloc.c
       8             :  * \brief Wrappers for C malloc code, and replacements for items that
       9             :  *   may be missing.
      10             :  **/
      11             : 
      12             : #include "orconfig.h"
      13             : 
      14             : #include <stdlib.h>
      15             : #include <string.h>
      16             : 
      17             : #include "lib/testsupport/testsupport.h"
      18             : #define UTIL_MALLOC_PRIVATE
      19             : #include "lib/malloc/malloc.h"
      20             : #include "lib/cc/torint.h"
      21             : #include "lib/err/torerr.h"
      22             : 
      23             : #ifdef __clang_analyzer__
      24             : #undef MALLOC_ZERO_WORKS
      25             : #endif
      26             : 
      27             : /** Allocate a chunk of <b>size</b> bytes of memory, and return a pointer to
      28             :  * result.  On error, log and terminate the process.  (Same as malloc(size),
      29             :  * but never returns NULL.)
      30             :  */
      31             : void *
      32     6753492 : tor_malloc_(size_t size)
      33             : {
      34     6753492 :   void *result;
      35             : 
      36     6753492 :   raw_assert(size < SIZE_T_CEILING);
      37             : 
      38             : #ifndef MALLOC_ZERO_WORKS
      39             :   /* Some libc mallocs don't work when size==0. Override them. */
      40             :   if (size==0) {
      41             :     size=1;
      42             :   }
      43             : #endif /* !defined(MALLOC_ZERO_WORKS) */
      44             : 
      45     6753492 :   result = raw_malloc(size);
      46             : 
      47     6753492 :   if (PREDICT_UNLIKELY(result == NULL)) {
      48             :     /* LCOV_EXCL_START */
      49             :     /* If these functions die within a worker process, they won't call
      50             :      * spawn_exit, but that's ok, since the parent will run out of memory soon
      51             :      * anyway. */
      52             :     raw_assert_unreached_msg("Out of memory on malloc(). Dying.");
      53             :     /* LCOV_EXCL_STOP */
      54             :   }
      55     6753492 :   return result;
      56             : }
      57             : 
      58             : /** Allocate a chunk of <b>size</b> bytes of memory, fill the memory with
      59             :  * zero bytes, and return a pointer to the result.  Log and terminate
      60             :  * the process on error.  (Same as calloc(size,1), but never returns NULL.)
      61             :  */
      62             : void *
      63     4109063 : tor_malloc_zero_(size_t size)
      64             : {
      65             :   /* You may ask yourself, "wouldn't it be smart to use calloc instead of
      66             :    * malloc+memset?  Perhaps libc's calloc knows some nifty optimization trick
      67             :    * we don't!"  Indeed it does, but its optimizations are only a big win when
      68             :    * we're allocating something very big (it knows if it just got the memory
      69             :    * from the OS in a pre-zeroed state).  We don't want to use tor_malloc_zero
      70             :    * for big stuff, so we don't bother with calloc. */
      71     4109063 :   void *result = tor_malloc_(size);
      72     4109063 :   memset(result, 0, size);
      73     4109063 :   return result;
      74             : }
      75             : 
      76             : /* The square root of SIZE_MAX + 1.  If a is less than this, and b is less
      77             :  * than this, then a*b is less than SIZE_MAX.  (For example, if size_t is
      78             :  * 32 bits, then SIZE_MAX is 0xffffffff and this value is 0x10000.  If a and
      79             :  * b are less than this, then their product is at most (65535*65535) ==
      80             :  * 0xfffe0001. */
      81             : #define SQRT_SIZE_MAX_P1 (((size_t)1) << (sizeof(size_t)*4))
      82             : 
      83             : /** Return non-zero if and only if the product of the arguments is exact,
      84             :  * and cannot overflow. */
      85             : STATIC int
      86      758373 : size_mul_check(const size_t x, const size_t y)
      87             : {
      88             :   /* This first check is equivalent to
      89             :      (x < SQRT_SIZE_MAX_P1 && y < SQRT_SIZE_MAX_P1)
      90             : 
      91             :      Rationale: if either one of x or y is >= SQRT_SIZE_MAX_P1, then it
      92             :      will have some bit set in its most significant half.
      93             :    */
      94          11 :   return ((x|y) < SQRT_SIZE_MAX_P1 ||
      95      758373 :           y == 0 ||
      96          11 :           x <= SIZE_MAX / y);
      97             : }
      98             : 
      99             : /** Allocate a chunk of <b>nmemb</b>*<b>size</b> bytes of memory, fill
     100             :  * the memory with zero bytes, and return a pointer to the result.
     101             :  * Log and terminate the process on error.  (Same as
     102             :  * calloc(<b>nmemb</b>,<b>size</b>), but never returns NULL.)
     103             :  * The second argument (<b>size</b>) should preferably be non-zero
     104             :  * and a compile-time constant.
     105             :  */
     106             : void *
     107      661062 : tor_calloc_(size_t nmemb, size_t size)
     108             : {
     109      661062 :   raw_assert(size_mul_check(nmemb, size));
     110      661062 :   return tor_malloc_zero_((nmemb * size));
     111             : }
     112             : 
     113             : /** Change the size of the memory block pointed to by <b>ptr</b> to <b>size</b>
     114             :  * bytes long; return the new memory block.  On error, log and
     115             :  * terminate. (Like realloc(ptr,size), but never returns NULL.)
     116             :  */
     117             : void *
     118      129044 : tor_realloc_(void *ptr, size_t size)
     119             : {
     120      129044 :   void *result;
     121             : 
     122      129044 :   raw_assert(size < SIZE_T_CEILING);
     123             : 
     124             : #ifndef MALLOC_ZERO_WORKS
     125             :   /* Some libc mallocs don't work when size==0. Override them. */
     126             :   if (size==0) {
     127             :     size=1;
     128             :   }
     129             : #endif /* !defined(MALLOC_ZERO_WORKS) */
     130             : 
     131      129044 :   result = raw_realloc(ptr, size);
     132             : 
     133      129044 :   if (PREDICT_UNLIKELY(result == NULL)) {
     134             :     /* LCOV_EXCL_START */
     135             :     raw_assert_unreached_msg("Out of memory on realloc(). Dying.");
     136             :     /* LCOV_EXCL_STOP */
     137             :   }
     138      129044 :   return result;
     139             : }
     140             : 
     141             : /**
     142             :  * Try to realloc <b>ptr</b> so that it takes up sz1 * sz2 bytes.  Check for
     143             :  * overflow. Unlike other allocation functions, return NULL on overflow.
     144             :  */
     145             : void *
     146       97296 : tor_reallocarray_(void *ptr, size_t sz1, size_t sz2)
     147             : {
     148             :   /* XXXX we can make this return 0, but we would need to check all the
     149             :    * reallocarray users. */
     150       97296 :   raw_assert(size_mul_check(sz1, sz2));
     151             : 
     152       97296 :   return tor_realloc(ptr, (sz1 * sz2));
     153             : }
     154             : 
     155             : /** Return a newly allocated copy of the NUL-terminated string s. On
     156             :  * error, log and terminate.  (Like strdup(s), but never returns
     157             :  * NULL.)
     158             :  */
     159             : char *
     160     1160901 : tor_strdup_(const char *s)
     161             : {
     162     1160901 :   char *duplicate;
     163     1160901 :   raw_assert(s);
     164             : 
     165     1160901 :   duplicate = raw_strdup(s);
     166             : 
     167     1160901 :   if (PREDICT_UNLIKELY(duplicate == NULL)) {
     168             :     /* LCOV_EXCL_START */
     169             :     raw_assert_unreached_msg("Out of memory on strdup(). Dying.");
     170             :     /* LCOV_EXCL_STOP */
     171             :   }
     172     1160901 :   return duplicate;
     173             : }
     174             : 
     175             : /** Allocate and return a new string containing the first <b>n</b>
     176             :  * characters of <b>s</b>.  If <b>s</b> is longer than <b>n</b>
     177             :  * characters, only the first <b>n</b> are copied.  The result is
     178             :  * always NUL-terminated.  (Like strndup(s,n), but never returns
     179             :  * NULL.)
     180             :  */
     181             : char *
     182     1427174 : tor_strndup_(const char *s, size_t n)
     183             : {
     184     1427174 :   char *duplicate;
     185     1427174 :   raw_assert(s);
     186     1427174 :   raw_assert(n < SIZE_T_CEILING);
     187     1427174 :   duplicate = tor_malloc_((n+1));
     188             :   /* Performance note: Ordinarily we prefer strlcpy to strncpy.  But
     189             :    * this function gets called a whole lot, and platform strncpy is
     190             :    * much faster than strlcpy when strlen(s) is much longer than n.
     191             :    */
     192     1427174 :   strncpy(duplicate, s, n);
     193     1427174 :   duplicate[n]='\0';
     194     1427174 :   return duplicate;
     195             : }
     196             : 
     197             : /** Allocate a chunk of <b>len</b> bytes, with the same contents as the
     198             :  * <b>len</b> bytes starting at <b>mem</b>. */
     199             : void *
     200      168114 : tor_memdup_(const void *mem, size_t len)
     201             : {
     202      168114 :   char *duplicate;
     203      168114 :   raw_assert(len < SIZE_T_CEILING);
     204      168114 :   raw_assert(mem);
     205      168114 :   duplicate = tor_malloc_(len);
     206      168114 :   memcpy(duplicate, mem, len);
     207      168114 :   return duplicate;
     208             : }
     209             : 
     210             : /** As tor_memdup(), but add an extra 0 byte at the end of the resulting
     211             :  * memory. */
     212             : void *
     213         916 : tor_memdup_nulterm_(const void *mem, size_t len)
     214             : {
     215         916 :   char *duplicate;
     216         916 :   raw_assert(len < SIZE_T_CEILING+1);
     217         916 :   raw_assert(mem);
     218         916 :   duplicate = tor_malloc_(len+1);
     219         916 :   memcpy(duplicate, mem, len);
     220         916 :   duplicate[len] = '\0';
     221         916 :   return duplicate;
     222             : }
     223             : 
     224             : /** Helper for places that need to take a function pointer to the right
     225             :  * spelling of "free()". */
     226             : void
     227       77331 : tor_free_(void *mem)
     228             : {
     229       77331 :   tor_free(mem);
     230       77331 : }

Generated by: LCOV version 1.14