Tor  0.4.7.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 
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"
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  */
29 const char *
30 unescape_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:52
Macros to manage assertions, fatal and non-fatal.
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:176
#define tor_fragile_assert()
Definition: util_bug.h:270