summaryrefslogtreecommitdiff
path: root/src/common/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/util.c')
-rw-r--r--src/common/util.c439
1 files changed, 309 insertions, 130 deletions
diff --git a/src/common/util.c b/src/common/util.c
index f3effe0957..a7bce2ea6c 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -9,10 +9,6 @@
* process control.
**/
-/* This is required on rh7 to make strptime not complain.
- */
-#define _GNU_SOURCE
-
#include "orconfig.h"
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
@@ -105,23 +101,6 @@
#endif
/* =====
- * Assertion helper.
- * ===== */
-/** Helper for tor_assert: report the assertion failure. */
-void
-tor_assertion_failed_(const char *fname, unsigned int line,
- const char *func, const char *expr)
-{
- char buf[256];
- log_err(LD_BUG, "%s:%u: %s: Assertion %s failed; aborting.",
- fname, line, func, expr);
- tor_snprintf(buf, sizeof(buf),
- "Assertion %s failed in %s at %s:%u",
- expr, func, fname, line);
- log_backtrace(LOG_ERR, LD_BUG, buf);
-}
-
-/* =====
* Memory management
* ===== */
#ifdef USE_DMALLOC
@@ -168,15 +147,17 @@ tor_malloc_(size_t size DMALLOC_PARAMS)
#ifdef USE_DMALLOC
result = dmalloc_malloc(file, line, size, DMALLOC_FUNC_MALLOC, 0, 0);
#else
- result = malloc(size);
+ result = raw_malloc(size);
#endif
if (PREDICT_UNLIKELY(result == NULL)) {
+ /* LCOV_EXCL_START */
log_err(LD_MM,"Out of memory on malloc(). Dying.");
/* If these functions die within a worker process, they won't call
* spawn_exit, but that's ok, since the parent will run out of memory soon
* anyway. */
exit(1);
+ /* LCOV_EXCL_STOP */
}
return result;
}
@@ -221,6 +202,15 @@ size_mul_check(const size_t x, const size_t y)
x <= SIZE_MAX / y);
}
+#ifdef TOR_UNIT_TESTS
+/** Exposed for unit tests only */
+int
+size_mul_check__(const size_t x, const size_t y)
+{
+ return size_mul_check(x,y);
+}
+#endif
+
/** 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
@@ -256,12 +246,14 @@ tor_realloc_(void *ptr, size_t size DMALLOC_PARAMS)
#ifdef USE_DMALLOC
result = dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0);
#else
- result = realloc(ptr, size);
+ result = raw_realloc(ptr, size);
#endif
if (PREDICT_UNLIKELY(result == NULL)) {
+ /* LCOV_EXCL_START */
log_err(LD_MM,"Out of memory on realloc(). Dying.");
exit(1);
+ /* LCOV_EXCL_STOP */
}
return result;
}
@@ -287,19 +279,21 @@ tor_reallocarray_(void *ptr, size_t sz1, size_t sz2 DMALLOC_PARAMS)
char *
tor_strdup_(const char *s DMALLOC_PARAMS)
{
- char *dup;
+ char *duplicate;
tor_assert(s);
#ifdef USE_DMALLOC
- dup = dmalloc_strdup(file, line, s, 0);
+ duplicate = dmalloc_strdup(file, line, s, 0);
#else
- dup = strdup(s);
+ duplicate = raw_strdup(s);
#endif
- if (PREDICT_UNLIKELY(dup == NULL)) {
+ if (PREDICT_UNLIKELY(duplicate == NULL)) {
+ /* LCOV_EXCL_START */
log_err(LD_MM,"Out of memory on strdup(). Dying.");
exit(1);
+ /* LCOV_EXCL_STOP */
}
- return dup;
+ return duplicate;
}
/** Allocate and return a new string containing the first <b>n</b>
@@ -311,17 +305,17 @@ tor_strdup_(const char *s DMALLOC_PARAMS)
char *
tor_strndup_(const char *s, size_t n DMALLOC_PARAMS)
{
- char *dup;
+ char *duplicate;
tor_assert(s);
tor_assert(n < SIZE_T_CEILING);
- dup = tor_malloc_((n+1) DMALLOC_FN_ARGS);
+ duplicate = tor_malloc_((n+1) DMALLOC_FN_ARGS);
/* Performance note: Ordinarily we prefer strlcpy to strncpy. But
* this function gets called a whole lot, and platform strncpy is
* much faster than strlcpy when strlen(s) is much longer than n.
*/
- strncpy(dup, s, n);
- dup[n]='\0';
- return dup;
+ strncpy(duplicate, s, n);
+ duplicate[n]='\0';
+ return duplicate;
}
/** Allocate a chunk of <b>len</b> bytes, with the same contents as the
@@ -329,12 +323,12 @@ tor_strndup_(const char *s, size_t n DMALLOC_PARAMS)
void *
tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS)
{
- char *dup;
+ char *duplicate;
tor_assert(len < SIZE_T_CEILING);
tor_assert(mem);
- dup = tor_malloc_(len DMALLOC_FN_ARGS);
- memcpy(dup, mem, len);
- return dup;
+ duplicate = tor_malloc_(len DMALLOC_FN_ARGS);
+ memcpy(duplicate, mem, len);
+ return duplicate;
}
/** As tor_memdup(), but add an extra 0 byte at the end of the resulting
@@ -342,13 +336,13 @@ tor_memdup_(const void *mem, size_t len DMALLOC_PARAMS)
void *
tor_memdup_nulterm_(const void *mem, size_t len DMALLOC_PARAMS)
{
- char *dup;
+ char *duplicate;
tor_assert(len < SIZE_T_CEILING+1);
tor_assert(mem);
- dup = tor_malloc_(len+1 DMALLOC_FN_ARGS);
- memcpy(dup, mem, len);
- dup[len] = '\0';
- return dup;
+ duplicate = tor_malloc_(len+1 DMALLOC_FN_ARGS);
+ memcpy(duplicate, mem, len);
+ duplicate[len] = '\0';
+ return duplicate;
}
/** Helper for places that need to take a function pointer to the right
@@ -359,6 +353,7 @@ tor_free_(void *mem)
tor_free(mem);
}
+DISABLE_GCC_WARNING(aggregate-return)
/** Call the platform malloc info function, and dump the results to the log at
* level <b>severity</b>. If no such function exists, do nothing. */
void
@@ -386,6 +381,7 @@ tor_log_mallinfo(int severity)
);
#endif
}
+ENABLE_GCC_WARNING(aggregate-return)
/* =====
* Math
@@ -530,21 +526,6 @@ round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor)
return number;
}
-/** Return the lowest x in [INT64_MIN, INT64_MAX] 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 int64_t, return INT64_MAX */
-int64_t
-round_int64_to_next_multiple_of(int64_t number, int64_t divisor)
-{
- tor_assert(divisor > 0);
- if (INT64_MAX - divisor + 1 < number)
- return INT64_MAX;
- if (number >= 0)
- number += divisor - 1;
- number -= number % divisor;
- return number;
-}
-
/** Transform a random value <b>p</b> from the uniform distribution in
* [0.0, 1.0[ into a Laplace distributed value with location parameter
* <b>mu</b> and scale parameter <b>b</b>. Truncate the final result
@@ -575,7 +556,7 @@ sample_laplace_distribution(double mu, double b, double p)
* The epsilon value must be between ]0.0, 1.0]. delta_f must be greater
* than 0. */
int64_t
-add_laplace_noise(int64_t signal, double random, double delta_f,
+add_laplace_noise(int64_t signal_, double random_, double delta_f,
double epsilon)
{
int64_t noise;
@@ -588,15 +569,38 @@ add_laplace_noise(int64_t signal, double random, double delta_f,
/* Just add noise, no further signal */
noise = sample_laplace_distribution(0.0,
delta_f / epsilon,
- random);
+ random_);
/* Clip (signal + noise) to [INT64_MIN, INT64_MAX] */
- if (noise > 0 && INT64_MAX - noise < signal)
+ if (noise > 0 && INT64_MAX - noise < signal_)
return INT64_MAX;
- else if (noise < 0 && INT64_MIN - noise > signal)
+ else if (noise < 0 && INT64_MIN - noise > signal_)
return INT64_MIN;
else
- return signal + noise;
+ return signal_ + noise;
+}
+
+/* Helper: return greatest common divisor of a,b */
+static uint64_t
+gcd64(uint64_t a, uint64_t b)
+{
+ while (b) {
+ uint64_t t = b;
+ b = a % b;
+ a = t;
+ }
+ return a;
+}
+
+/* Given a fraction *<b>numer</b> / *<b>denom</b>, simplify it.
+ * Requires that the denominator is greater than 0. */
+void
+simplify_fraction64(uint64_t *numer, uint64_t *denom)
+{
+ tor_assert(denom);
+ uint64_t gcd = gcd64(*numer, *denom);
+ *numer /= gcd;
+ *denom /= gcd;
}
/** Return the number of bits set in <b>v</b>. */
@@ -634,12 +638,12 @@ n_bits_set_u8(uint8_t v)
void
tor_strstrip(char *s, const char *strip)
{
- char *read = s;
- while (*read) {
- if (strchr(strip, *read)) {
- ++read;
+ char *readp = s;
+ while (*readp) {
+ if (strchr(strip, *readp)) {
+ ++readp;
} else {
- *s++ = *read++;
+ *s++ = *readp++;
}
}
*s = '\0';
@@ -1130,6 +1134,9 @@ tor_digest256_is_zero(const char *digest)
/* Were there unexpected unconverted characters? */ \
if (!next && *endptr) \
goto err; \
+ /* Illogical (max, min) inputs? */ \
+ if (BUG(max < min)) \
+ goto err; \
/* Is r within limits? */ \
if (r < min || r > max) \
goto err; \
@@ -1402,42 +1409,138 @@ tor_escape_str_for_pt_args(const char *string, const char *chars_to_escape)
* Time
* ===== */
+#define TOR_USEC_PER_SEC 1000000
+
+/** Return the difference between start->tv_sec and end->tv_sec.
+ * Returns INT64_MAX on overflow and underflow.
+ */
+static int64_t
+tv_secdiff_impl(const struct timeval *start, const struct timeval *end)
+{
+ const int64_t s = (int64_t)start->tv_sec;
+ const int64_t e = (int64_t)end->tv_sec;
+
+ /* This may not be the most efficient way of implemeting this check,
+ * but it's easy to see that it's correct and doesn't overflow */
+
+ if (s > 0 && e < INT64_MIN + s) {
+ /* s is positive: equivalent to e - s < INT64_MIN, but without any
+ * overflow */
+ return INT64_MAX;
+ } else if (s < 0 && e > INT64_MAX + s) {
+ /* s is negative: equivalent to e - s > INT64_MAX, but without any
+ * overflow */
+ return INT64_MAX;
+ }
+
+ return e - s;
+}
+
/** Return the number of microseconds elapsed between *start and *end.
+ * Returns LONG_MAX on overflow and underflow.
*/
long
tv_udiff(const struct timeval *start, const struct timeval *end)
{
- long udiff;
- long secdiff = end->tv_sec - start->tv_sec;
+ /* Sanity check tv_usec */
+ if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
+ "start tv_usec: " I64_FORMAT " microseconds",
+ I64_PRINTF_ARG(start->tv_usec));
+ return LONG_MAX;
+ }
+
+ if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on microsecond detail with bad "
+ "end tv_usec: " I64_FORMAT " microseconds",
+ I64_PRINTF_ARG(end->tv_usec));
+ return LONG_MAX;
+ }
+
+ /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
+ */
+ int64_t udiff;
+ const int64_t secdiff = tv_secdiff_impl(start, end);
- if (labs(secdiff+1) > LONG_MAX/1000000) {
+ /* end->tv_usec - start->tv_usec can be up to 1 second either way */
+ if (secdiff > (int64_t)(LONG_MAX/1000000 - 1) ||
+ secdiff < (int64_t)(LONG_MIN/1000000 + 1)) {
log_warn(LD_GENERAL, "comparing times on microsecond detail too far "
- "apart: %ld seconds", secdiff);
+ "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
+ return LONG_MAX;
+ }
+
+ /* we'll never get an overflow here, because we check that both usecs are
+ * between 0 and TV_USEC_PER_SEC. */
+ udiff = secdiff*1000000 + ((int64_t)end->tv_usec - (int64_t)start->tv_usec);
+
+ /* Some compilers are smart enough to work out this is a no-op on L64 */
+#if SIZEOF_LONG < 8
+ if (udiff > (int64_t)LONG_MAX || udiff < (int64_t)LONG_MIN) {
return LONG_MAX;
}
+#endif
- udiff = secdiff*1000000L + (end->tv_usec - start->tv_usec);
- return udiff;
+ return (long)udiff;
}
/** Return the number of milliseconds elapsed between *start and *end.
+ * If the tv_usec difference is 500, rounds away from zero.
+ * Returns LONG_MAX on overflow and underflow.
*/
long
tv_mdiff(const struct timeval *start, const struct timeval *end)
{
- long mdiff;
- long secdiff = end->tv_sec - start->tv_sec;
+ /* Sanity check tv_usec */
+ if (start->tv_usec > TOR_USEC_PER_SEC || start->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
+ "start tv_usec: " I64_FORMAT " microseconds",
+ I64_PRINTF_ARG(start->tv_usec));
+ return LONG_MAX;
+ }
- if (labs(secdiff+1) > LONG_MAX/1000) {
+ if (end->tv_usec > TOR_USEC_PER_SEC || end->tv_usec < 0) {
+ log_warn(LD_GENERAL, "comparing times on millisecond detail with bad "
+ "end tv_usec: " I64_FORMAT " microseconds",
+ I64_PRINTF_ARG(end->tv_usec));
+ return LONG_MAX;
+ }
+
+ /* Some BSDs have struct timeval.tv_sec 64-bit, but time_t (and long) 32-bit
+ */
+ int64_t mdiff;
+ const int64_t secdiff = tv_secdiff_impl(start, end);
+
+ /* end->tv_usec - start->tv_usec can be up to 1 second either way, but the
+ * mdiff calculation may add another temporary second for rounding.
+ * Whether this actually causes overflow depends on the compiler's constant
+ * folding and order of operations. */
+ if (secdiff > (int64_t)(LONG_MAX/1000 - 2) ||
+ secdiff < (int64_t)(LONG_MIN/1000 + 1)) {
log_warn(LD_GENERAL, "comparing times on millisecond detail too far "
- "apart: %ld seconds", secdiff);
+ "apart: " I64_FORMAT " seconds", I64_PRINTF_ARG(secdiff));
return LONG_MAX;
}
/* Subtract and round */
- mdiff = secdiff*1000L +
- ((long)end->tv_usec - (long)start->tv_usec + 500L) / 1000L;
- return mdiff;
+ mdiff = secdiff*1000 +
+ /* We add a million usec here to ensure that the result is positive,
+ * so that the round-towards-zero behavior of the division will give
+ * the right result for rounding to the nearest msec. Later we subtract
+ * 1000 in order to get the correct result.
+ * We'll never get an overflow here, because we check that both usecs are
+ * between 0 and TV_USEC_PER_SEC. */
+ ((int64_t)end->tv_usec - (int64_t)start->tv_usec + 500 + 1000000) / 1000
+ - 1000;
+
+ /* Some compilers are smart enough to work out this is a no-op on L64 */
+#if SIZEOF_LONG < 8
+ if (mdiff > (int64_t)LONG_MAX || mdiff < (int64_t)LONG_MIN) {
+ return LONG_MAX;
+ }
+#endif
+
+ return (long)mdiff;
}
/**
@@ -1456,11 +1559,12 @@ tv_to_msec(const struct timeval *tv)
#define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
/** Helper: Return the number of leap-days between Jan 1, y1 and Jan 1, y2. */
static int
-n_leapdays(int y1, int y2)
+n_leapdays(int year1, int year2)
{
- --y1;
- --y2;
- return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
+ --year1;
+ --year2;
+ return (year2/4 - year1/4) - (year2/100 - year1/100)
+ + (year2/400 - year1/400);
}
/** Number of days per month in non-leap year; used by tor_timegm and
* parse_rfc1123_time. */
@@ -1638,11 +1742,16 @@ parse_rfc1123_time(const char *buf, time_t *t)
tm.tm_sec = (int)tm_sec;
if (tm.tm_year < 1970) {
+ /* LCOV_EXCL_START
+ * XXXX I think this is dead code; we already checked for
+ * invalid_year above. */
+ tor_assert_nonfatal_unreached();
char *esc = esc_for_log(buf);
log_warn(LD_GENERAL,
"Got invalid RFC1123 time %s. (Before 1970)", esc);
tor_free(esc);
return -1;
+ /* LCOV_EXCL_STOP */
}
tm.tm_year -= 1900;
@@ -1726,10 +1835,15 @@ parse_iso_time_(const char *cp, time_t *t, int strict)
st_tm.tm_wday = 0; /* Should be ignored. */
if (st_tm.tm_year < 70) {
+ /* LCOV_EXCL_START
+ * XXXX I think this is dead code; we already checked for
+ * year < 1970 above. */
+ tor_assert_nonfatal_unreached();
char *esc = esc_for_log(cp);
log_warn(LD_GENERAL, "Got invalid ISO time %s. (Before 1970)", esc);
tor_free(esc);
return -1;
+ /* LCOV_EXCL_STOP */
}
return tor_timegm(&st_tm, t);
}
@@ -1893,7 +2007,9 @@ update_approx_time(time_t now)
/** If the rate-limiter <b>lim</b> is ready at <b>now</b>, return the number
* of calls to rate_limit_is_ready (including this one!) since the last time
- * rate_limit_is_ready returned nonzero. Otherwise return 0. */
+ * rate_limit_is_ready returned nonzero. Otherwise return 0.
+ * If the call number hits <b>RATELIM_TOOMANY</b> limit, drop a warning
+ * about this event and stop counting. */
static int
rate_limit_is_ready(ratelim_t *lim, time_t now)
{
@@ -1903,7 +2019,10 @@ rate_limit_is_ready(ratelim_t *lim, time_t now)
lim->n_calls_since_last_time = 0;
return res;
} else {
- ++lim->n_calls_since_last_time;
+ if (lim->n_calls_since_last_time <= RATELIM_TOOMANY) {
+ ++lim->n_calls_since_last_time;
+ }
+
return 0;
}
}
@@ -1920,9 +2039,12 @@ rate_limit_log(ratelim_t *lim, time_t now)
return tor_strdup("");
} else {
char *cp=NULL;
+ const char *opt_over = (n >= RATELIM_TOOMANY) ? "over " : "";
+ /* XXXX this is not exactly correct: the messages could have occurred
+ * any time between the old value of lim->allowed and now. */
tor_asprintf(&cp,
- " [%d similar message(s) suppressed in last %d seconds]",
- n-1, lim->rate);
+ " [%s%d similar message(s) suppressed in last %d seconds]",
+ opt_over, n-1, lim->rate);
return cp;
}
} else {
@@ -2011,6 +2133,16 @@ clean_name_for_stat(char *name)
#endif
}
+/** Wrapper for unlink() to make it mockable for the test suite; returns 0
+ * if unlinking the file succeeded, -1 and sets errno if unlinking fails.
+ */
+
+MOCK_IMPL(int,
+tor_unlink,(const char *pathname))
+{
+ return unlink(pathname);
+}
+
/** Return:
* FN_ERROR if filename can't be read, is NULL, or is zero-length,
* FN_NOENT if it doesn't exist,
@@ -2059,11 +2191,13 @@ file_status(const char *fname)
}
}
-/** Check whether <b>dirname</b> exists and is private. If yes return 0. If
- * it does not exist, and <b>check</b>&CPD_CREATE is set, try to create it
- * and return 0 on success. If it does not exist, and
- * <b>check</b>&CPD_CHECK, and we think we can create it, return 0. Else
- * return -1. If CPD_GROUP_OK is set, then it's okay if the directory
+/** Check whether <b>dirname</b> exists and is private. If yes return 0.
+ * If <b>dirname</b> does not exist:
+ * - if <b>check</b>&CPD_CREATE, try to create it and return 0 on success.
+ * - if <b>check</b>&CPD_CHECK, and we think we can create it, return 0.
+ * - if <b>check</b>&CPD_CHECK is false, and the directory exists, return 0.
+ * - otherwise, return -1.
+ * If CPD_GROUP_OK is set, then it's okay if the directory
* is group-readable, but in all cases we create the directory mode 0700.
* If CPD_GROUP_READ is set, existing directory behaves as CPD_GROUP_OK and
* if the directory is created it will use mode 0750 with group read
@@ -2074,9 +2208,9 @@ file_status(const char *fname)
* When effective_user is not NULL, check permissions against the given user
* and its primary group.
*/
-int
-check_private_dir(const char *dirname, cpd_check_t check,
- const char *effective_user)
+MOCK_IMPL(int,
+check_private_dir,(const char *dirname, cpd_check_t check,
+ const char *effective_user))
{
int r;
struct stat st;
@@ -2189,13 +2323,14 @@ check_private_dir(const char *dirname, cpd_check_t check,
running_gid = getgid();
}
if (st.st_uid != running_uid) {
- const struct passwd *pw = NULL;
+ const struct passwd *pw_uid = NULL;
char *process_ownername = NULL;
- pw = tor_getpwuid(running_uid);
- process_ownername = pw ? tor_strdup(pw->pw_name) : tor_strdup("<unknown>");
+ pw_uid = tor_getpwuid(running_uid);
+ process_ownername = pw_uid ? tor_strdup(pw_uid->pw_name) :
+ tor_strdup("<unknown>");
- pw = tor_getpwuid(st.st_uid);
+ pw_uid = tor_getpwuid(st.st_uid);
log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by "
"%s (%d). Perhaps you are running Tor as the wrong user?",
@@ -2304,8 +2439,8 @@ check_private_dir(const char *dirname, cpd_check_t check,
* function, and all other functions in util.c that create files, create them
* with mode 0600.
*/
-int
-write_str_to_file(const char *fname, const char *str, int bin)
+MOCK_IMPL(int,
+write_str_to_file,(const char *fname, const char *str, int bin))
{
#ifdef _WIN32
if (!bin && strchr(str, '\r')) {
@@ -2664,8 +2799,8 @@ read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out)
* the call to stat and the call to read_all: the resulting string will
* be truncated.
*/
-char *
-read_file_to_str(const char *filename, int flags, struct stat *stat_out)
+MOCK_IMPL(char *,
+read_file_to_str, (const char *filename, int flags, struct stat *stat_out))
{
int fd; /* router file */
struct stat statbuf;
@@ -2773,7 +2908,7 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
* provided), and return a pointer to the position in <b>s</b> immediately
* after the string. On failure, return NULL.
*/
-static const char *
+const char *
unescape_string(const char *s, char **result, size_t *size_out)
{
const char *cp;
@@ -2820,9 +2955,11 @@ unescape_string(const char *s, char **result, size_t *size_out)
if (size_out) *size_out = out - *result;
return cp+1;
case '\0':
+ /* LCOV_EXCL_START -- we caught this in parse_config_from_line. */
tor_fragile_assert();
tor_free(*result);
return NULL;
+ /* LCOV_EXCL_STOP */
case '\\':
switch (cp[1])
{
@@ -2836,8 +2973,12 @@ unescape_string(const char *s, char **result, size_t *size_out)
x1 = hex_decode_digit(cp[2]);
x2 = hex_decode_digit(cp[3]);
if (x1 == -1 || x2 == -1) {
- tor_free(*result);
- return NULL;
+ /* LCOV_EXCL_START */
+ /* we caught this above in the initial loop. */
+ tor_assert_nonfatal_unreached();
+ tor_free(*result);
+ return NULL;
+ /* LCOV_EXCL_STOP */
}
*out++ = ((x1<<4) + x2);
@@ -2863,7 +3004,11 @@ unescape_string(const char *s, char **result, size_t *size_out)
cp += 2;
break;
default:
+ /* LCOV_EXCL_START */
+ /* we caught this above in the initial loop. */
+ tor_assert_nonfatal_unreached();
tor_free(*result); return NULL;
+ /* LCOV_EXCL_STOP */
}
break;
default:
@@ -2936,6 +3081,8 @@ parse_config_line_from_str_verbose(const char *line, char **key_out,
}
while (*line == ' ' || *line == '\t')
++line;
+ if (*line == '\r' && *(++line) == '\n')
+ ++line;
if (*line && *line != '#' && *line != '\n') {
if (err_out)
*err_out = "Excess data after quoted string";
@@ -3079,7 +3226,7 @@ digit_to_num(char d)
* success, store the result in <b>out</b>, advance bufp to the next
* character, and return 0. On failure, return -1. */
static int
-scan_unsigned(const char **bufp, unsigned long *out, int width, int base)
+scan_unsigned(const char **bufp, unsigned long *out, int width, unsigned base)
{
unsigned long result = 0;
int scanned_so_far = 0;
@@ -3092,7 +3239,7 @@ scan_unsigned(const char **bufp, unsigned long *out, int width, int base)
while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
&& scanned_so_far < width) {
- int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
+ unsigned digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
// Check for overflow beforehand, without actually causing any overflow
// This preserves functionality on compilers that don't wrap overflow
// (i.e. that trap or optimise away overflow)
@@ -3138,14 +3285,15 @@ scan_signed(const char **bufp, long *out, int width)
if (neg && result > 0) {
if (result > ((unsigned long)LONG_MAX) + 1)
return -1; /* Underflow */
- // Avoid overflow on the cast to signed long when result is LONG_MIN
- // by subtracting 1 from the unsigned long positive value,
- // then, after it has been cast to signed and negated,
- // subtracting the original 1 (the double-subtraction is intentional).
- // Otherwise, the cast to signed could cause a temporary long
- // to equal LONG_MAX + 1, which is undefined.
- // We avoid underflow on the subtraction by treating -0 as positive.
- *out = (-(long)(result - 1)) - 1;
+ else if (result == ((unsigned long)LONG_MAX) + 1)
+ *out = LONG_MIN;
+ else {
+ /* We once had a far more clever no-overflow conversion here, but
+ * some versions of GCC apparently ran it into the ground. Now
+ * we just check for LONG_MIN explicitly.
+ */
+ *out = -(long)result;
+ }
} else {
if (result > LONG_MAX)
return -1; /* Overflow */
@@ -3291,8 +3439,10 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
*out = lng;
} else {
int *out = va_arg(ap, int *);
+#if LONG_MAX > INT_MAX
if (lng < INT_MIN || lng > INT_MAX)
return n_matched;
+#endif
*out = (int)lng;
}
++pattern;
@@ -3387,8 +3537,8 @@ smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern,
/** Return a new list containing the filenames in the directory <b>dirname</b>.
* Return NULL on error or if <b>dirname</b> is not a directory.
*/
-smartlist_t *
-tor_listdir(const char *dirname)
+MOCK_IMPL(smartlist_t *,
+tor_listdir, (const char *dirname))
{
smartlist_t *result;
#ifdef _WIN32
@@ -3495,13 +3645,17 @@ start_daemon(void)
start_daemon_called = 1;
if (pipe(daemon_filedes)) {
+ /* LCOV_EXCL_START */
log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno));
exit(1);
+ /* LCOV_EXCL_STOP */
}
pid = fork();
if (pid < 0) {
+ /* LCOV_EXCL_START */
log_err(LD_GENERAL,"fork failed. Exiting.");
exit(1);
+ /* LCOV_EXCL_STOP */
}
if (pid) { /* Parent */
int ok;
@@ -3563,8 +3717,10 @@ finish_daemon(const char *desired_cwd)
nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
if (nullfd < 0) {
+ /* LCOV_EXCL_START */
log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
exit(1);
+ /* LCOV_EXCL_STOP */
}
/* close fds linking to invoking terminal, but
* close usual incoming fds, but redirect them somewhere
@@ -3573,8 +3729,10 @@ finish_daemon(const char *desired_cwd)
if (dup2(nullfd,0) < 0 ||
dup2(nullfd,1) < 0 ||
dup2(nullfd,2) < 0) {
+ /* LCOV_EXCL_START */
log_err(LD_GENERAL,"dup2 failed. Exiting.");
exit(1);
+ /* LCOV_EXCL_STOP */
}
if (nullfd > 2)
close(nullfd);
@@ -3688,9 +3846,9 @@ format_win_cmdline_argument(const char *arg)
formatted_arg[i++] = '"';
/* Add characters */
- SMARTLIST_FOREACH(arg_chars, char*, c,
+ SMARTLIST_FOREACH(arg_chars, char*, ch,
{
- formatted_arg[i++] = *c;
+ formatted_arg[i++] = *ch;
});
/* Add trailing quote */
@@ -3771,7 +3929,7 @@ format_number_sigsafe(unsigned long x, char *buf, int buf_len,
/* NOT tor_assert; see above. */
if (cp != buf) {
- abort();
+ abort(); // LCOV_EXCL_LINE
}
return len;
@@ -4349,7 +4507,7 @@ tor_spawn_background(const char *const filename, const char **argv,
_exit(255);
/* Never reached, but avoids compiler warning */
- return status;
+ return status; // LCOV_EXCL_LINE
}
/* In parent */
@@ -4548,13 +4706,13 @@ tor_get_exit_code(process_handle_t *process_handle,
return PROCESS_EXIT_RUNNING;
} else if (retval != process_handle->pid) {
log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s",
- process_handle->pid, strerror(errno));
+ (int)process_handle->pid, strerror(errno));
return PROCESS_EXIT_ERROR;
}
if (!WIFEXITED(stat_loc)) {
log_warn(LD_GENERAL, "Process %d did not exit normally",
- process_handle->pid);
+ (int)process_handle->pid);
return PROCESS_EXIT_ERROR;
}
@@ -5535,7 +5693,7 @@ tor_weak_random_range(tor_weak_rng_t *rng, int32_t top)
int64_t
clamp_double_to_int64(double number)
{
- int exp;
+ int exponent;
/* NaN is a special case that can't be used with the logic below. */
if (isnan(number)) {
@@ -5549,18 +5707,39 @@ clamp_double_to_int64(double number)
* magnitude of number is strictly less than 2^exp.
*
* If number is infinite, the call to frexp is legal but the contents of
- * exp are unspecified. */
- frexp(number, &exp);
+ * are exponent unspecified. */
+ frexp(number, &exponent);
/* If the magnitude of number is strictly less than 2^63, the truncated
* version of number is guaranteed to be representable. The only
* representable integer for which this is not the case is INT64_MIN, but
* it is covered by the logic below. */
- if (isfinite(number) && exp <= 63) {
- return number;
+ if (isfinite(number) && exponent <= 63) {
+ return (int64_t)number;
}
/* Handle infinities and finite numbers with magnitude >= 2^63. */
return signbit(number) ? INT64_MIN : INT64_MAX;
}
+/** Return a uint64_t value from <b>a</b> in network byte order. */
+uint64_t
+tor_htonll(uint64_t a)
+{
+#ifdef WORDS_BIGENDIAN
+ /* Big endian. */
+ return a;
+#else /* WORDS_BIGENDIAN */
+ /* Little endian. The worst... */
+ return htonl((uint32_t)(a>>32)) |
+ (((uint64_t)htonl((uint32_t)a))<<32);
+#endif /* WORDS_BIGENDIAN */
+}
+
+/** Return a uint64_t value from <b>a</b> in host byte order. */
+uint64_t
+tor_ntohll(uint64_t a)
+{
+ return tor_htonll(a);
+}
+