qstring.c (2416B)
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 2 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 3 /* See LICENSE for licensing information */ 4 5 /** 6 * \file qstring.c 7 * \brief Implement QuotedString parsing. 8 * 9 * Note that this is only used for controller authentication; do not 10 * create new users for this. Instead, prefer the cstring.c functions. 11 **/ 12 13 #include "orconfig.h" 14 #include "lib/encoding/qstring.h" 15 #include "lib/malloc/malloc.h" 16 #include "lib/log/util_bug.h" 17 18 /** If the first <b>in_len_max</b> characters in <b>start</b> contain a 19 * QuotedString, return the length of that 20 * string (as encoded, including quotes). Otherwise return -1. */ 21 static inline int 22 get_qstring_length(const char *start, size_t in_len_max, 23 int *chars_out) 24 { 25 const char *cp, *end; 26 int chars = 0; 27 28 if (*start != '\"') 29 return -1; 30 31 cp = start+1; 32 end = start+in_len_max; 33 34 /* Calculate length. */ 35 while (1) { 36 if (cp >= end) { 37 return -1; /* Too long. */ 38 } else if (*cp == '\\') { 39 if (++cp == end) 40 return -1; /* Can't escape EOS. */ 41 ++cp; 42 ++chars; 43 } else if (*cp == '\"') { 44 break; 45 } else { 46 ++cp; 47 ++chars; 48 } 49 } 50 if (chars_out) 51 *chars_out = chars; 52 return (int)(cp - start+1); 53 } 54 55 /** Given a pointer to a string starting at <b>start</b> containing 56 * <b>in_len_max</b> characters, decode a string beginning with one double 57 * quote, containing any number of non-quote characters or characters escaped 58 * with a backslash, and ending with a final double quote. Place the resulting 59 * string (unquoted, unescaped) into a newly allocated string in *<b>out</b>; 60 * store its length in <b>out_len</b>. On success, return a pointer to the 61 * character immediately following the escaped string. On failure, return 62 * NULL. */ 63 const char * 64 decode_qstring(const char *start, size_t in_len_max, 65 char **out, size_t *out_len) 66 { 67 const char *cp, *end; 68 char *outp; 69 int len, n_chars = 0; 70 71 len = get_qstring_length(start, in_len_max, &n_chars); 72 if (len<0) 73 return NULL; 74 75 end = start+len-1; /* Index of last quote. */ 76 tor_assert(*end == '\"'); 77 outp = *out = tor_malloc(len+1); 78 *out_len = n_chars; 79 80 cp = start+1; 81 while (cp < end) { 82 if (*cp == '\\') 83 ++cp; 84 *outp++ = *cp++; 85 } 86 *outp = '\0'; 87 tor_assert((outp - *out) == (int)*out_len); 88 89 return end+1; 90 }