[tor-commits] [tor/master] Add utility functions needed for SOCKS argument parsing.

nickm at torproject.org nickm at torproject.org
Tue Mar 19 17:25:51 UTC 2013


commit b8532bcb1ec51fcfae4ceff869be116fec4ccbb9
Author: George Kadianakis <desnacked at riseup.net>
Date:   Mon Dec 17 14:14:09 2012 +0200

    Add utility functions needed for SOCKS argument parsing.
---
 src/common/util.c    |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/common/util.h    |    4 +++
 src/test/test_util.c |   50 +++++++++++++++++++++++++++++++++++++
 3 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/src/common/util.c b/src/common/util.c
index 93e2ba8..b2f12bf 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -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
  * ===== */
diff --git a/src/common/util.h b/src/common/util.h
index 911b1b5..e3cd721 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -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);
diff --git a/src/test/test_util.c b/src/test/test_util.c
index bed33fa..b41f235 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -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),





More information about the tor-commits mailing list