mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 13:43:47 +01:00
Add utility functions needed for SOCKS argument parsing.
This commit is contained in:
parent
d86a45f991
commit
b8532bcb1e
@ -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
|
||||
* ===== */
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user