LCOV - code coverage report
Current view: top level - lib/encoding - cstring.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 57 57 100.0 %
Date: 2021-11-24 03:28:48 Functions: 1 1 100.0 %

          Line data    Source code
       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"
      17             : #include "lib/string/compat_ctype.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          77 : unescape_string(const char *s, char **result, size_t *size_out)
      31             : {
      32          77 :   const char *cp;
      33          77 :   char *out;
      34          77 :   if (s[0] != '\"')
      35             :     return NULL;
      36          77 :   cp = s+1;
      37         806 :   while (1) {
      38         806 :     switch (*cp) {
      39             :       case '\0':
      40             :       case '\n':
      41             :         return NULL;
      42          61 :       case '\"':
      43          61 :         goto end_of_loop;
      44          39 :       case '\\':
      45          39 :         if (cp[1] == 'x' || cp[1] == 'X') {
      46           9 :           if (!(TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3])))
      47             :             return NULL;
      48           5 :           cp += 4;
      49          30 :         } else if (TOR_ISODIGIT(cp[1])) {
      50           5 :           cp += 2;
      51           5 :           if (TOR_ISODIGIT(*cp)) ++cp;
      52           5 :           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          19 :           cp += 2;
      56             :         } else {
      57             :           return NULL;
      58             :         }
      59             :         break;
      60         700 :       default:
      61         700 :         ++cp;
      62         700 :         break;
      63             :     }
      64             :   }
      65          61 :  end_of_loop:
      66          61 :   out = *result = tor_malloc(cp-s + 1);
      67          61 :   cp = s+1;
      68         674 :   while (1) {
      69         674 :     switch (*cp)
      70             :       {
      71          61 :       case '\"':
      72          61 :         *out = '\0';
      73          61 :         if (size_out) *size_out = out - *result;
      74          61 :         return cp+1;
      75             : 
      76             :         /* LCOV_EXCL_START -- we caught this in parse_config_from_line. */
      77             :       case '\0':
      78             :         tor_fragile_assert();
      79             :         tor_free(*result);
      80             :         return NULL;
      81             :         /* LCOV_EXCL_STOP */
      82          28 :       case '\\':
      83          28 :         switch (cp[1])
      84             :           {
      85           3 :           case 'n': *out++ = '\n'; cp += 2; break;
      86           1 :           case 'r': *out++ = '\r'; cp += 2; break;
      87           3 :           case 't': *out++ = '\t'; cp += 2; break;
      88           5 :           case 'x': case 'X':
      89             :             {
      90           5 :               int x1, x2;
      91             : 
      92           5 :               x1 = hex_decode_digit(cp[2]);
      93           5 :               x2 = hex_decode_digit(cp[3]);
      94           5 :               if (x1 == -1 || x2 == -1) {
      95             :                 /* LCOV_EXCL_START */
      96             :                 /* we caught this above in the initial loop. */
      97             :                 tor_assert_nonfatal_unreached();
      98             :                 tor_free(*result);
      99             :                 return NULL;
     100             :                 /* LCOV_EXCL_STOP */
     101             :               }
     102             : 
     103           5 :               *out++ = ((x1<<4) + x2);
     104           5 :               cp += 4;
     105             :             }
     106           5 :             break;
     107           5 :           case '0': case '1': case '2': case '3': case '4': case '5':
     108             :           case '6': case '7':
     109             :             {
     110           5 :               int n = cp[1]-'0';
     111           5 :               cp += 2;
     112           5 :               if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
     113           5 :               if (TOR_ISODIGIT(*cp)) { n = n*8 + *cp-'0'; cp++; }
     114           5 :               if (n > 255) { tor_free(*result); return NULL; }
     115           5 :               *out++ = (char)n;
     116             :             }
     117           5 :             break;
     118          11 :           case '\'':
     119             :           case '\"':
     120             :           case '\\':
     121             :           case '\?':
     122          11 :             *out++ = cp[1];
     123          11 :             cp += 2;
     124          11 :             break;
     125             : 
     126             :             /* LCOV_EXCL_START */
     127             :           default:
     128             :             /* we caught this above in the initial loop. */
     129             :             tor_assert_nonfatal_unreached();
     130             :             tor_free(*result); return NULL;
     131             :             /* LCOV_EXCL_STOP */
     132             :           }
     133             :         break;
     134         585 :       default:
     135         585 :         *out++ = *cp++;
     136             :       }
     137             :   }
     138             : }

Generated by: LCOV version 1.14