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.c184
1 files changed, 64 insertions, 120 deletions
diff --git a/src/common/util.c b/src/common/util.c
index 71b77e20fa..db160fdf0a 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -20,7 +20,6 @@
#define UTIL_PRIVATE
#include "util.h"
#include "torlog.h"
-#undef log
#include "crypto.h"
#include "torint.h"
#include "container.h"
@@ -337,8 +336,8 @@ tor_log_mallinfo(int severity)
* ===== */
/**
- * Returns the natural logarithm of d base 2. We define this wrapper here so
- * as to make it easier not to conflict with Tor's log() macro.
+ * Returns the natural logarithm of d base e. We defined this wrapper here so
+ * to avoid conflicts with old versions of tor_log(), which were named log().
*/
double
tor_mathlog(double d)
@@ -1191,119 +1190,10 @@ escaped(const char *s)
return escaped_val_;
}
-/** Rudimentary string wrapping code: given a un-wrapped <b>string</b> (no
- * newlines!), break the string into newline-terminated lines of no more than
- * <b>width</b> characters long (not counting newline) and insert them into
- * <b>out</b> in order. Precede the first line with prefix0, and subsequent
- * lines with prefixRest.
- */
-/* This uses a stupid greedy wrapping algorithm right now:
- * - For each line:
- * - Try to fit as much stuff as possible, but break on a space.
- * - If the first "word" of the line will extend beyond the allowable
- * width, break the word at the end of the width.
- */
-void
-wrap_string(smartlist_t *out, const char *string, size_t width,
- const char *prefix0, const char *prefixRest)
-{
- size_t p0Len, pRestLen, pCurLen;
- const char *eos, *prefixCur;
- tor_assert(out);
- tor_assert(string);
- tor_assert(width);
- if (!prefix0)
- prefix0 = "";
- if (!prefixRest)
- prefixRest = "";
-
- p0Len = strlen(prefix0);
- pRestLen = strlen(prefixRest);
- tor_assert(width > p0Len && width > pRestLen);
- eos = strchr(string, '\0');
- tor_assert(eos);
- pCurLen = p0Len;
- prefixCur = prefix0;
-
- while ((eos-string)+pCurLen > width) {
- const char *eol = string + width - pCurLen;
- while (eol > string && *eol != ' ')
- --eol;
- /* eol is now the last space that can fit, or the start of the string. */
- if (eol > string) {
- size_t line_len = (eol-string) + pCurLen + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, eol-string);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- string = eol + 1;
- } else {
- size_t line_len = width + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, width - pCurLen);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- string += width-pCurLen;
- }
- prefixCur = prefixRest;
- pCurLen = pRestLen;
- }
-
- if (string < eos) {
- size_t line_len = (eos-string) + pCurLen + 2;
- char *line = tor_malloc(line_len);
- memcpy(line, prefixCur, pCurLen);
- memcpy(line+pCurLen, string, eos-string);
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- smartlist_add(out, line);
- }
-}
-
/* =====
* Time
* ===== */
-/**
- * Converts struct timeval to a double value.
- * Preserves microsecond precision, but just barely.
- * Error is approx +/- 0.1 usec when dealing with epoch values.
- */
-double
-tv_to_double(const struct timeval *tv)
-{
- double conv = tv->tv_sec;
- conv += tv->tv_usec/1000000.0;
- return conv;
-}
-
-/**
- * Converts timeval to milliseconds.
- */
-int64_t
-tv_to_msec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000L;
- /* Round ghetto-style */
- conv += ((int64_t)tv->tv_usec+500)/1000L;
- return conv;
-}
-
-/**
- * Converts timeval to microseconds.
- */
-int64_t
-tv_to_usec(const struct timeval *tv)
-{
- int64_t conv = ((int64_t)tv->tv_sec)*1000000L;
- conv += tv->tv_usec;
- return conv;
-}
-
/** Return the number of microseconds elapsed between *start and *end.
*/
long
@@ -2389,8 +2279,10 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
}
#endif
- if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING)
+ if ((uint64_t)(statbuf.st_size)+1 >= SIZE_T_CEILING) {
+ close(fd);
return NULL;
+ }
string = tor_malloc((size_t)(statbuf.st_size+1));
@@ -2550,10 +2442,13 @@ unescape_string(const char *s, char **result, size_t *size_out)
* key portion and *<b>value_out</b> to a new string holding the value portion
* of the line, and return a pointer to the start of the next line. If we run
* out of data, return a pointer to the end of the string. If we encounter an
- * error, return NULL.
+ * error, return NULL and set *<b>err_out</b> (if provided) to an error
+ * message.
*/
const char *
-parse_config_line_from_str(const char *line, char **key_out, char **value_out)
+parse_config_line_from_str_verbose(const char *line, char **key_out,
+ char **value_out,
+ const char **err_out)
{
/* I believe the file format here is supposed to be:
FILE = (EMPTYLINE | LINE)* (EMPTYLASTLINE | LASTLINE)?
@@ -2627,12 +2522,18 @@ parse_config_line_from_str(const char *line, char **key_out, char **value_out)
/* Find the end of the line. */
if (*line == '\"') { // XXX No continuation handling is done here
- if (!(line = unescape_string(line, value_out, NULL)))
- return NULL;
+ if (!(line = unescape_string(line, value_out, NULL))) {
+ if (err_out)
+ *err_out = "Invalid escape sequence in quoted string";
+ return NULL;
+ }
while (*line == ' ' || *line == '\t')
++line;
- if (*line && *line != '#' && *line != '\n')
+ if (*line && *line != '#' && *line != '\n') {
+ if (err_out)
+ *err_out = "Excess data after quoted string";
return NULL;
+ }
} else {
/* Look for the end of the line. */
while (*line && *line != '\n' && (*line != '#' || continuation)) {
@@ -3847,12 +3748,13 @@ tor_spawn_background(const char *const filename, const char **argv,
child_state = CHILD_STATE_MAXFD;
#ifdef _SC_OPEN_MAX
- if (-1 != max_fd) {
+ if (-1 == max_fd) {
max_fd = (int) sysconf(_SC_OPEN_MAX);
- if (max_fd == -1)
+ if (max_fd == -1) {
max_fd = DEFAULT_MAX_FD;
log_warn(LD_GENERAL,
"Cannot find maximum file descriptor, assuming %d", max_fd);
+ }
}
#else
max_fd = DEFAULT_MAX_FD;
@@ -5009,3 +4911,45 @@ tor_check_port_forwarding(const char *filename,
}
}
+/** Initialize the insecure RNG <b>rng</b> from a seed value <b>seed</b>. */
+void
+tor_init_weak_random(tor_weak_rng_t *rng, unsigned seed)
+{
+ rng->state = (uint32_t)(seed & 0x7fffffff);
+}
+
+/** Return a randomly chosen value in the range 0..TOR_WEAK_RANDOM_MAX based
+ * on the RNG state of <b>rng</b>. This entropy will not be cryptographically
+ * strong; do not rely on it for anything an adversary should not be able to
+ * predict. */
+int32_t
+tor_weak_random(tor_weak_rng_t *rng)
+{
+ /* Here's a linear congruential generator. OpenBSD and glibc use these
+ * parameters; they aren't too bad, and should have maximal period over the
+ * range 0..INT32_MAX. We don't want to use the platform rand() or random(),
+ * since some platforms have bad weak RNGs that only return values in the
+ * range 0..INT16_MAX, which just isn't enough. */
+ rng->state = (rng->state * 1103515245 + 12345) & 0x7fffffff;
+ return (int32_t) rng->state;
+}
+
+/** Return a random number in the range [0 , <b>top</b>). {That is, the range
+ * of integers i such that 0 <= i < top.} Chooses uniformly. Requires that
+ * top is greater than 0. This randomness is not cryptographically strong; do
+ * not rely on it for anything an adversary should not be able to predict. */
+int32_t
+tor_weak_random_range(tor_weak_rng_t *rng, int32_t top)
+{
+ /* We don't want to just do tor_weak_random() % top, since random() is often
+ * implemented with an LCG whose modulus is a power of 2, and those are
+ * cyclic in their low-order bits. */
+ int divisor, result;
+ tor_assert(top > 0);
+ divisor = TOR_WEAK_RANDOM_MAX / top;
+ do {
+ result = (int32_t)(tor_weak_random(rng) / divisor);
+ } while (result >= top);
+ return result;
+}
+