1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
10 * \brief Decode data that has been written as a C literal.
13 #include "lib/encoding/cstring.h"
14 #include "lib/log/log.h"
15 #include "lib/log/util_bug.h"
16 #include "lib/malloc/malloc.h"
17 #include "lib/string/compat_ctype.h"
21 #define TOR_ISODIGIT(c) ('0' <= (c) && (c) <= '7')
23 /** Given a c-style double-quoted escaped string in <b>s</b>, extract and
24 * decode its contents into a newly allocated string. On success, assign this
25 * string to *<b>result</b>, assign its length to <b>size_out</b> (if
26 * provided), and return a pointer to the position in <b>s</b> immediately
27 * after the string. On failure, return NULL.
30 unescape_string(const char *s
, char **result
, size_t *size_out
)
45 if (cp
[1] == 'x' || cp
[1] == 'X') {
46 if (!(TOR_ISXDIGIT(cp
[2]) && TOR_ISXDIGIT(cp
[3])))
49 } else if (TOR_ISODIGIT(cp
[1])) {
51 if (TOR_ISODIGIT(*cp
)) ++cp
;
52 if (TOR_ISODIGIT(*cp
)) ++cp
;
53 } else if (cp
[1] == 'n' || cp
[1] == 'r' || cp
[1] == 't' || cp
[1] == '"'
54 || cp
[1] == '\\' || cp
[1] == '\'') {
66 out
= *result
= tor_malloc(cp
-s
+ 1);
73 if (size_out
) *size_out
= out
- *result
;
76 /* LCOV_EXCL_START -- we caught this in parse_config_from_line. */
85 case 'n': *out
++ = '\n'; cp
+= 2; break;
86 case 'r': *out
++ = '\r'; cp
+= 2; break;
87 case 't': *out
++ = '\t'; cp
+= 2; break;
92 x1
= hex_decode_digit(cp
[2]);
93 x2
= hex_decode_digit(cp
[3]);
94 if (x1
== -1 || x2
== -1) {
96 /* we caught this above in the initial loop. */
97 tor_assert_nonfatal_unreached();
103 *out
++ = ((x1
<<4) + x2
);
107 case '0': case '1': case '2': case '3': case '4': case '5':
112 if (TOR_ISODIGIT(*cp
)) { n
= n
*8 + *cp
-'0'; cp
++; }
113 if (TOR_ISODIGIT(*cp
)) { n
= n
*8 + *cp
-'0'; cp
++; }
114 if (n
> 255) { tor_free(*result
); return NULL
; }
126 /* LCOV_EXCL_START */
128 /* we caught this above in the initial loop. */
129 tor_assert_nonfatal_unreached();
130 tor_free(*result
); return NULL
;