/** * Try to realloc <b>ptr</b> so that it takes up sz1 * sz2 bytes. Check for * overflow. Unlike other allocation functions, return NULL on overflow. */ void * tor_reallocarray_(void *ptr, size_t sz1, size_t sz2) { /* XXXX we can make this return 0, but we would need to check all the * reallocarray users. */ raw_assert(size_mul_check(sz1, sz2)); return tor_realloc(ptr, (sz1 * sz2)); }
/** Return the lowest x such that x is at least <b>number</b>, and x modulo * <b>divisor</b> == 0. If no such x can be expressed as a uint64_t, return * UINT64_MAX. Asserts if divisor is zero. */ uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor) { raw_assert(divisor > 0); if (UINT64_MAX - divisor + 1 < number) return UINT64_MAX; number += divisor - 1; number -= number % divisor; return number; }
/** Return the lowest x such that x is at least <b>number</b>, and x modulo * <b>divisor</b> == 0. If no such x can be expressed as an unsigned, return * UINT_MAX. Asserts if divisor is zero. */ unsigned round_to_next_multiple_of(unsigned number, unsigned divisor) { raw_assert(divisor > 0); if (UINT_MAX - divisor + 1 < number) return UINT_MAX; number += divisor - 1; number -= number % divisor; return number; }
/** Helper: map a log severity to descriptive string. */ static inline const char * sev_to_string(int severity) { switch (severity) { case LOG_DEBUG: return "debug"; case LOG_INFO: return "info"; case LOG_NOTICE: return "notice"; case LOG_WARN: return "warn"; case LOG_ERR: return "err"; default: /* Call assert, not tor_assert, since tor_assert * calls log on failure. */ raw_assert(0); return "UNKNOWN"; // LCOV_EXCL_LINE } }
/** * Given an array of list of <b>n_entries</b> uint64_t values, whose sum is * <b>total</b>, find the first i such that the total of all elements 0...i is * greater than rand_val. * * Try to perform this operation in a constant-time way. */ int select_array_member_cumulative_timei(const uint64_t *entries, int n_entries, uint64_t total, uint64_t rand_val) { int i, i_chosen=-1, n_chosen=0; uint64_t total_so_far = 0; for (i = 0; i < n_entries; ++i) { total_so_far += entries[i]; if (gt_i64_timei(total_so_far, rand_val)) { i_chosen = i; n_chosen++; /* Set rand_val to INT64_MAX rather than stopping the loop. This way, * the time we spend in the loop does not leak which element we chose. */ rand_val = INT64_MAX; } } raw_assert(total_so_far == total); raw_assert(n_chosen == 1); raw_assert(i_chosen >= 0); raw_assert(i_chosen < n_entries); return i_chosen; }
/** Return a newly allocated copy of the NUL-terminated string s. On * error, log and terminate. (Like strdup(s), but never returns * NULL.) */ char * tor_strdup_(const char *s) { char *duplicate; raw_assert(s); duplicate = raw_strdup(s); if (PREDICT_UNLIKELY(duplicate == NULL)) { /* LCOV_EXCL_START */ raw_assert_unreached_msg("Out of memory on strdup(). Dying."); /* LCOV_EXCL_STOP */ } return duplicate; }
/** * Return a new anonymous memory mapping that holds <b>sz</b> bytes. * * Memory mappings are unlike the results from malloc() in that they are * handled separately by the operating system, and as such can have different * kernel-level flags set on them. * * The "flags" argument may be zero or more of ANONMAP_PRIVATE and * ANONMAP_NOINHERIT. * * Memory returned from this function must be released with * tor_munmap_anonymous(). * * If <b>inherit_result_out</b> is non-NULL, set it to one of * INHERIT_RES_KEEP, INHERIT_RES_DROP, or INHERIT_RES_ZERO, depending on the * properties of the returned memory. * * [Note: OS people use the word "anonymous" here to mean that the memory * isn't associated with any file. This has *nothing* to do with the kind of * anonymity that Tor is trying to provide.] */ void * tor_mmap_anonymous(size_t sz, unsigned flags, inherit_res_t *inherit_result_out) { void *ptr; inherit_res_t itmp=0; if (inherit_result_out == NULL) { inherit_result_out = &itmp; } *inherit_result_out = INHERIT_RES_KEEP; #if defined(_WIN32) HANDLE mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, /*attributes*/ PAGE_READWRITE, HIGH_SIZE_T_BYTES(sz), sz & 0xffffffff, NULL /* name */); raw_assert(mapping != NULL); ptr = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, /* Offset */ 0 /* Extend to end of mapping */); raw_assert(ptr); CloseHandle(mapping); /* mapped view holds a reference */ #elif defined(HAVE_SYS_MMAN_H) ptr = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); raw_assert(ptr != MAP_FAILED); raw_assert(ptr != NULL); #else ptr = tor_malloc_zero(sz); #endif if (flags & ANONMAP_PRIVATE) { int lock_result = lock_mem(ptr, sz); raw_assert(lock_result == 0); int nodump_result = nodump_mem(ptr, sz); raw_assert(nodump_result == 0); } if (flags & ANONMAP_NOINHERIT) { int noinherit_result = noinherit_mem(ptr, sz, inherit_result_out); raw_assert(noinherit_result == 0); } return ptr; }
/** Helper: decide whether to include the function name in the log message. */ static inline int should_log_function_name(log_domain_mask_t domain, int severity) { switch (severity) { case LOG_DEBUG: case LOG_INFO: /* All debugging messages occur in interesting places. */ return (domain & LD_NOFUNCNAME) == 0; case LOG_NOTICE: case LOG_WARN: case LOG_ERR: /* We care about places where bugs occur. */ return (domain & (LD_BUG|LD_NOFUNCNAME)) == LD_BUG; default: /* Call assert, not tor_assert, since tor_assert calls log on failure. */ raw_assert(0); return 0; // LCOV_EXCL_LINE } }
/** Change the size of the memory block pointed to by <b>ptr</b> to <b>size</b> * bytes long; return the new memory block. On error, log and * terminate. (Like realloc(ptr,size), but never returns NULL.) */ void * tor_realloc_(void *ptr, size_t size) { void *result; raw_assert(size < SIZE_T_CEILING); #ifndef MALLOC_ZERO_WORKS /* Some libc mallocs don't work when size==0. Override them. */ if (size==0) { size=1; } #endif /* !defined(MALLOC_ZERO_WORKS) */ result = raw_realloc(ptr, size); if (PREDICT_UNLIKELY(result == NULL)) { /* LCOV_EXCL_START */ raw_assert_unreached_msg("Out of memory on realloc(). Dying."); /* LCOV_EXCL_STOP */ } return result; }
/** Allocate a chunk of <b>nmemb</b>*<b>size</b> bytes of memory, fill * the memory with zero bytes, and return a pointer to the result. * Log and terminate the process on error. (Same as * calloc(<b>nmemb</b>,<b>size</b>), but never returns NULL.) * The second argument (<b>size</b>) should preferably be non-zero * and a compile-time constant. */ void * tor_calloc_(size_t nmemb, size_t size) { raw_assert(size_mul_check(nmemb, size)); return tor_malloc_zero_((nmemb * size)); }