Commit b8532bcb authored by George Kadianakis's avatar George Kadianakis
Browse files

Add utility functions needed for SOCKS argument parsing.

parent d86a45f9
Loading
Loading
Loading
Loading
+67 −0
Changes for src/common/util.c: 67 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -865,6 +865,36 @@ tor_digest_is_zero(const char *digest)
  return tor_memeq(digest, ZERO_DIGEST, DIGEST_LEN);
}

/** Return true if <b>string</b> is a valid '<key>=<value>' string.
 *  <value> is optional, to indicate the empty string. */
int
string_is_key_value(const char *string)
{
  /* position of equal sign in string */
  char *equal_sign_pos = NULL;

  tor_assert(string);

  if (strlen(string) < 2) { /* "x=a" is shortest args string */
    log_warn(LD_GENERAL, "'%s' is too short to be a k=v value.", string);
    return 0;
  }

  equal_sign_pos = strchr(string, '=');
  if (!equal_sign_pos) {
    log_warn(LD_GENERAL, "'%s' is not a k=v value.", string);
    return 0;
  }

  /* validate that the '=' is not in the beginning of the string. */
  if (equal_sign_pos == string) {
    log_warn(LD_GENERAL, "'%s' is not a valid k=v value.", string);
    return 0;
  }

  return 1;
}

/** Return true iff the DIGEST256_LEN bytes in digest are all zero. */
int
tor_digest256_is_zero(const char *digest)
@@ -1249,6 +1279,43 @@ wrap_string(smartlist_t *out, const char *string, size_t width,
  }
}

/** Escape every character of <b>string</b> that belongs to the set of
 *  characters <b>set</b>. Use <b>escape_char</b> as the character to
 *  use for escaping. */
char *
tor_escape_str_for_socks_arg(const char *string)
{
  char *new_string = NULL;
  char *new_cp = NULL;
  size_t length, new_length;
  static const char *chars_to_escape = ";\\";

  tor_assert(string);

  length = strlen(string);

  if (!length)
    return NULL;
  /* (new_length > SIZE_MAX) => ((length * 2) + 1 > SIZE_MAX) =>
     (length*2 > SIZE_MAX - 1) => (length > (SIZE_MAX - 1)/2) */
  if (length > (SIZE_MAX - 1)/2) /* check for overflow */
    return NULL;

  /* this should be enough even if all characters must be escaped */
  new_length = (length * 2) + 1;

  new_string = new_cp = tor_malloc_zero(new_length);

  while (*string) {
    if (strchr(chars_to_escape, *string))
      *new_cp++ = '\\';

    *new_cp++ = *string++;
  }

  return new_string;
}

/* =====
 * Time
 * ===== */
+4 −0
Changes for src/common/util.h: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -209,12 +209,16 @@ const char *find_whitespace_eos(const char *s, const char *eos);
const char *find_str_at_start_of_line(const char *haystack,
                                      const char *needle);
int string_is_C_identifier(const char *string);
int string_is_key_value(const char *string);

int tor_mem_is_zero(const char *mem, size_t len);
int tor_digest_is_zero(const char *digest);
int tor_digest256_is_zero(const char *digest);
char *esc_for_log(const char *string) ATTR_MALLOC;
const char *escaped(const char *string);

char *tor_escape_str_for_socks_arg(const char *string);

struct smartlist_t;
void wrap_string(struct smartlist_t *out, const char *string, size_t width,
                 const char *prefix0, const char *prefixRest);
+50 −0
Changes for src/test/test_util.c: 50 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -795,6 +795,54 @@ test_util_expand_filename(void)
}
#endif

/** Test tor_escape_str_for_socks_arg(). */
static void
test_util_escape_string_socks(void)
{
  char *escaped_string = NULL;

  /** Simple backslash escape. */
  escaped_string = tor_escape_str_for_socks_arg("This is a backslash: \\");
  test_assert(escaped_string);
  test_streq(escaped_string, "This is a backslash: \\\\");
  tor_free(escaped_string);

  /** Simple semicolon escape. */
  escaped_string = tor_escape_str_for_socks_arg("First rule: Do not use ;");
  test_assert(escaped_string);
  test_streq(escaped_string, "First rule: Do not use \\;");
  tor_free(escaped_string);

  /** Ilegal: Empty string. */
  escaped_string = tor_escape_str_for_socks_arg("");
  test_assert(!escaped_string);

  /** Escape all characters. */
  escaped_string = tor_escape_str_for_socks_arg(";\\;\\");
  test_assert(escaped_string);
  test_streq(escaped_string, "\\;\\\\\\;\\\\");
  tor_free(escaped_string);

 done:
  tor_free(escaped_string);
}

static void
test_util_string_is_key_value(void *ptr)
{
  (void)ptr;
  test_assert(string_is_key_value("key=value"));
  test_assert(string_is_key_value("k=v"));
  test_assert(string_is_key_value("key="));
  test_assert(!string_is_key_value("=value"));
  test_assert(!string_is_key_value("="));

  /* ??? */
  /* test_assert(!string_is_key_value("===")); */
 done:
  ;
}

/** Test basic string functionality. */
static void
test_util_strmisc(void)
@@ -3271,6 +3319,8 @@ struct testcase_t util_tests[] = {
#ifndef _WIN32
  UTIL_LEGACY(expand_filename),
#endif
  UTIL_LEGACY(escape_string_socks),
  UTIL_LEGACY(string_is_key_value),
  UTIL_LEGACY(strmisc),
  UTIL_LEGACY(pow2),
  UTIL_LEGACY(gzip),