mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Move the escape-for-log code into src/lib/log
It doesn't need anything higher-level, and everything that needs the logs potentially needs this.
This commit is contained in:
parent
5f41bc91c6
commit
7159edf909
@ -559,128 +559,6 @@ tor_parse_uint64(const char *s, int base, uint64_t min,
|
|||||||
CHECK_STRTOX_RESULT();
|
CHECK_STRTOX_RESULT();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allocate and return a new string representing the contents of <b>s</b>,
|
|
||||||
* surrounded by quotes and using standard C escapes.
|
|
||||||
*
|
|
||||||
* Generally, we use this for logging values that come in over the network to
|
|
||||||
* keep them from tricking users, and for sending certain values to the
|
|
||||||
* controller.
|
|
||||||
*
|
|
||||||
* We trust values from the resolver, OS, configuration file, and command line
|
|
||||||
* to not be maliciously ill-formed. We validate incoming routerdescs and
|
|
||||||
* SOCKS requests and addresses from BEGIN cells as they're parsed;
|
|
||||||
* afterwards, we trust them as non-malicious.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
esc_for_log(const char *s)
|
|
||||||
{
|
|
||||||
const char *cp;
|
|
||||||
char *result, *outp;
|
|
||||||
size_t len = 3;
|
|
||||||
if (!s) {
|
|
||||||
return tor_strdup("(null)");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (cp = s; *cp; ++cp) {
|
|
||||||
switch (*cp) {
|
|
||||||
case '\\':
|
|
||||||
case '\"':
|
|
||||||
case '\'':
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
case '\t':
|
|
||||||
len += 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127)
|
|
||||||
++len;
|
|
||||||
else
|
|
||||||
len += 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tor_assert(len <= SSIZE_MAX);
|
|
||||||
|
|
||||||
result = outp = tor_malloc(len);
|
|
||||||
*outp++ = '\"';
|
|
||||||
for (cp = s; *cp; ++cp) {
|
|
||||||
/* This assertion should always succeed, since we will write at least
|
|
||||||
* one char here, and two chars for closing quote and nul later */
|
|
||||||
tor_assert((outp-result) < (ssize_t)len-2);
|
|
||||||
switch (*cp) {
|
|
||||||
case '\\':
|
|
||||||
case '\"':
|
|
||||||
case '\'':
|
|
||||||
*outp++ = '\\';
|
|
||||||
*outp++ = *cp;
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
*outp++ = '\\';
|
|
||||||
*outp++ = 'n';
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
*outp++ = '\\';
|
|
||||||
*outp++ = 't';
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
*outp++ = '\\';
|
|
||||||
*outp++ = 'r';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) {
|
|
||||||
*outp++ = *cp;
|
|
||||||
} else {
|
|
||||||
tor_assert((outp-result) < (ssize_t)len-4);
|
|
||||||
tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp);
|
|
||||||
outp += 4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tor_assert((outp-result) <= (ssize_t)len-2);
|
|
||||||
*outp++ = '\"';
|
|
||||||
*outp++ = 0;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Similar to esc_for_log. Allocate and return a new string representing
|
|
||||||
* the first n characters in <b>chars</b>, surround by quotes and using
|
|
||||||
* standard C escapes. If a NUL character is encountered in <b>chars</b>,
|
|
||||||
* the resulting string will be terminated there.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
esc_for_log_len(const char *chars, size_t n)
|
|
||||||
{
|
|
||||||
char *string = tor_strndup(chars, n);
|
|
||||||
char *string_escaped = esc_for_log(string);
|
|
||||||
tor_free(string);
|
|
||||||
return string_escaped;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Allocate and return a new string representing the contents of <b>s</b>,
|
|
||||||
* surrounded by quotes and using standard C escapes.
|
|
||||||
*
|
|
||||||
* THIS FUNCTION IS NOT REENTRANT. Don't call it from outside the main
|
|
||||||
* thread. Also, each call invalidates the last-returned value, so don't
|
|
||||||
* try log_warn(LD_GENERAL, "%s %s", escaped(a), escaped(b));
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
escaped(const char *s)
|
|
||||||
{
|
|
||||||
static char *escaped_val_ = NULL;
|
|
||||||
tor_free(escaped_val_);
|
|
||||||
|
|
||||||
if (s)
|
|
||||||
escaped_val_ = esc_for_log(s);
|
|
||||||
else
|
|
||||||
escaped_val_ = NULL;
|
|
||||||
|
|
||||||
return escaped_val_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return a newly allocated string equal to <b>string</b>, except that every
|
/** Return a newly allocated string equal to <b>string</b>, except that every
|
||||||
* character in <b>chars_to_escape</b> is preceded by a backslash. */
|
* character in <b>chars_to_escape</b> is preceded by a backslash. */
|
||||||
char *
|
char *
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "lib/intmath/cmp.h"
|
#include "lib/intmath/cmp.h"
|
||||||
#include "lib/log/ratelim.h"
|
#include "lib/log/ratelim.h"
|
||||||
#include "lib/log/util_bug.h"
|
#include "lib/log/util_bug.h"
|
||||||
|
#include "lib/log/escape.h"
|
||||||
|
|
||||||
#ifndef O_BINARY
|
#ifndef O_BINARY
|
||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
@ -99,10 +100,6 @@ int tor_mem_is_zero(const char *mem, size_t len);
|
|||||||
int tor_digest_is_zero(const char *digest);
|
int tor_digest_is_zero(const char *digest);
|
||||||
int tor_digest256_is_zero(const char *digest);
|
int tor_digest256_is_zero(const char *digest);
|
||||||
|
|
||||||
char *esc_for_log(const char *string) ATTR_MALLOC;
|
|
||||||
char *esc_for_log_len(const char *chars, size_t n) ATTR_MALLOC;
|
|
||||||
const char *escaped(const char *string);
|
|
||||||
|
|
||||||
char *tor_escape_str_for_pt_args(const char *string,
|
char *tor_escape_str_for_pt_args(const char *string,
|
||||||
const char *chars_to_escape);
|
const char *chars_to_escape);
|
||||||
|
|
||||||
|
132
src/lib/log/escape.c
Normal file
132
src/lib/log/escape.c
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/* Copyright (c) 2003, Roger Dingledine
|
||||||
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||||
|
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#include "lib/log/escape.h"
|
||||||
|
#include "lib/log/util_bug.h"
|
||||||
|
#include "lib/string/compat_ctype.h"
|
||||||
|
#include "lib/string/printf.h"
|
||||||
|
#include "lib/malloc/util_malloc.h"
|
||||||
|
|
||||||
|
/** Allocate and return a new string representing the contents of <b>s</b>,
|
||||||
|
* surrounded by quotes and using standard C escapes.
|
||||||
|
*
|
||||||
|
* Generally, we use this for logging values that come in over the network to
|
||||||
|
* keep them from tricking users, and for sending certain values to the
|
||||||
|
* controller.
|
||||||
|
*
|
||||||
|
* We trust values from the resolver, OS, configuration file, and command line
|
||||||
|
* to not be maliciously ill-formed. We validate incoming routerdescs and
|
||||||
|
* SOCKS requests and addresses from BEGIN cells as they're parsed;
|
||||||
|
* afterwards, we trust them as non-malicious.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
esc_for_log(const char *s)
|
||||||
|
{
|
||||||
|
const char *cp;
|
||||||
|
char *result, *outp;
|
||||||
|
size_t len = 3;
|
||||||
|
if (!s) {
|
||||||
|
return tor_strdup("(null)");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cp = s; *cp; ++cp) {
|
||||||
|
switch (*cp) {
|
||||||
|
case '\\':
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
case '\t':
|
||||||
|
len += 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127)
|
||||||
|
++len;
|
||||||
|
else
|
||||||
|
len += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tor_assert(len <= SSIZE_MAX);
|
||||||
|
|
||||||
|
result = outp = tor_malloc(len);
|
||||||
|
*outp++ = '\"';
|
||||||
|
for (cp = s; *cp; ++cp) {
|
||||||
|
/* This assertion should always succeed, since we will write at least
|
||||||
|
* one char here, and two chars for closing quote and nul later */
|
||||||
|
tor_assert((outp-result) < (ssize_t)len-2);
|
||||||
|
switch (*cp) {
|
||||||
|
case '\\':
|
||||||
|
case '\"':
|
||||||
|
case '\'':
|
||||||
|
*outp++ = '\\';
|
||||||
|
*outp++ = *cp;
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
*outp++ = '\\';
|
||||||
|
*outp++ = 'n';
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
*outp++ = '\\';
|
||||||
|
*outp++ = 't';
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
*outp++ = '\\';
|
||||||
|
*outp++ = 'r';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) {
|
||||||
|
*outp++ = *cp;
|
||||||
|
} else {
|
||||||
|
tor_assert((outp-result) < (ssize_t)len-4);
|
||||||
|
tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp);
|
||||||
|
outp += 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tor_assert((outp-result) <= (ssize_t)len-2);
|
||||||
|
*outp++ = '\"';
|
||||||
|
*outp++ = 0;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Similar to esc_for_log. Allocate and return a new string representing
|
||||||
|
* the first n characters in <b>chars</b>, surround by quotes and using
|
||||||
|
* standard C escapes. If a NUL character is encountered in <b>chars</b>,
|
||||||
|
* the resulting string will be terminated there.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
esc_for_log_len(const char *chars, size_t n)
|
||||||
|
{
|
||||||
|
char *string = tor_strndup(chars, n);
|
||||||
|
char *string_escaped = esc_for_log(string);
|
||||||
|
tor_free(string);
|
||||||
|
return string_escaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Allocate and return a new string representing the contents of <b>s</b>,
|
||||||
|
* surrounded by quotes and using standard C escapes.
|
||||||
|
*
|
||||||
|
* THIS FUNCTION IS NOT REENTRANT. Don't call it from outside the main
|
||||||
|
* thread. Also, each call invalidates the last-returned value, so don't
|
||||||
|
* try log_warn(LD_GENERAL, "%s %s", escaped(a), escaped(b));
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
escaped(const char *s)
|
||||||
|
{
|
||||||
|
static char *escaped_val_ = NULL;
|
||||||
|
tor_free(escaped_val_);
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
escaped_val_ = esc_for_log(s);
|
||||||
|
else
|
||||||
|
escaped_val_ = NULL;
|
||||||
|
|
||||||
|
return escaped_val_;
|
||||||
|
}
|
18
src/lib/log/escape.h
Normal file
18
src/lib/log/escape.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* Copyright (c) 2001, Matej Pfajfar.
|
||||||
|
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||||
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||||
|
* Copyright (c) 2007-2018, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#ifndef TOR_ESCAPE_H
|
||||||
|
#define TOR_ESCAPE_H
|
||||||
|
|
||||||
|
#include "orconfig.h"
|
||||||
|
#include "lib/cc/compat_compiler.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
char *esc_for_log(const char *string) ATTR_MALLOC;
|
||||||
|
char *esc_for_log_len(const char *chars, size_t n) ATTR_MALLOC;
|
||||||
|
const char *escaped(const char *string);
|
||||||
|
|
||||||
|
#endif /* !defined(TOR_TORLOG_H) */
|
@ -6,6 +6,7 @@ noinst_LIBRARIES += src/lib/libtor-log-testing.a
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
src_lib_libtor_log_a_SOURCES = \
|
src_lib_libtor_log_a_SOURCES = \
|
||||||
|
src/lib/log/escape.c \
|
||||||
src/lib/log/ratelim.c \
|
src/lib/log/ratelim.c \
|
||||||
src/lib/log/torlog.c \
|
src/lib/log/torlog.c \
|
||||||
src/lib/log/util_bug.c
|
src/lib/log/util_bug.c
|
||||||
@ -19,6 +20,7 @@ src/lib/log/torlog.$(OBJEXT) \
|
|||||||
src/lib/log/src_lib_libtor_log_testing_a-torlog.$(OBJEXT): micro-revision.i
|
src/lib/log/src_lib_libtor_log_testing_a-torlog.$(OBJEXT): micro-revision.i
|
||||||
|
|
||||||
noinst_HEADERS += \
|
noinst_HEADERS += \
|
||||||
|
src/lib/log/escape.h \
|
||||||
src/lib/log/ratelim.h \
|
src/lib/log/ratelim.h \
|
||||||
src/lib/log/torlog.h \
|
src/lib/log/torlog.h \
|
||||||
src/lib/log/util_bug.h
|
src/lib/log/util_bug.h
|
||||||
|
Loading…
Reference in New Issue
Block a user