Tor 0.4.9.0-alpha-dev
cstring.c
Go to the documentation of this file.
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 */
6
7/**
8 * \file cstring.c
9 *
10 * \brief Decode data that has been written as a C literal.
11 **/
12
14#include "lib/log/log.h"
15#include "lib/log/util_bug.h"
16#include "lib/malloc/malloc.h"
18
19#include <string.h>
20
21#define TOR_ISODIGIT(c) ('0' <= (c) && (c) <= '7')
22
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.
28 */
29const char *
30unescape_string(const char *s, char **result, size_t *size_out)
31{
32 const char *cp;
33 char *out;
34 if (s[0] != '\"')
35 return NULL;
36 cp = s+1;
37 while (1) {
38 switch (*cp) {
39 case '\0':
40 case '\n':
41 return NULL;
42 case '\"':
43 goto end_of_loop;
44 case '\\':
45 if (cp[1] == 'x' || cp[1] == 'X') {
46 if (!(TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3])))
47 return NULL;
48 cp += 4;
49 } else if (TOR_ISODIGIT(cp[1])) {
50 cp += 2;
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] == '\'') {
55 cp += 2;
56 } else {
57 return NULL;
58 }
59 break;
60 default:
61 ++cp;
62 break;
63 }
64 }
65 end_of_loop:
66 out = *result = tor_malloc(cp-s + 1);
67 cp = s+1;
68 while (1) {
69 switch (*cp)
70 {
71 case '\"':
72 *out = '\0';
73 if (size_out) *size_out = out - *result;
74 return cp+1;
75
76 /* LCOV_EXCL_START -- we caught this in parse_config_from_line. */
77 case '\0':
79 tor_free(*result);
80 return NULL;
81 /* LCOV_EXCL_STOP */
82 case '\\':
83 switch (cp[1])
84 {
85 case 'n': *out++ = '\n'; cp += 2; break;
86 case 'r': *out++ = '\r'; cp += 2; break;
87 case 't': *out++ = '\t'; cp += 2; break;
88 case 'x': case 'X':
89 {
90 int x1, x2;
91
92 x1 = hex_decode_digit(cp[2]);
93 x2 = hex_decode_digit(cp[3]);
94 if (x1 == -1 || x2 == -1) {
95 /* LCOV_EXCL_START */
96 /* we caught this above in the initial loop. */
98 tor_free(*result);
99 return NULL;
100 /* LCOV_EXCL_STOP */
101 }
102
103 *out++ = ((x1<<4) + x2);
104 cp += 4;
105 }
106 break;
107 case '0': case '1': case '2': case '3': case '4': case '5':
108 case '6': case '7':
109 {
110 int n = cp[1]-'0';
111 cp += 2;
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; }
115 *out++ = (char)n;
116 }
117 break;
118 case '\'':
119 case '\"':
120 case '\\':
121 case '\?':
122 *out++ = cp[1];
123 cp += 2;
124 break;
125
126 /* LCOV_EXCL_START */
127 default:
128 /* we caught this above in the initial loop. */
130 tor_free(*result); return NULL;
131 /* LCOV_EXCL_STOP */
132 }
133 break;
134 default:
135 *out++ = *cp++;
136 }
137 }
138}
Locale-independent character-type inspection (header)
static int hex_decode_digit(char c)
Definition: compat_ctype.h:43
const char * unescape_string(const char *s, char **result, size_t *size_out)
Definition: cstring.c:30
Header for cstring.c.
Headers for log.c.
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
Macros to manage assertions, fatal and non-fatal.
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:177
#define tor_fragile_assert()
Definition: util_bug.h:278