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

          Line data    Source code
       1             : /* Copyright (c) 2003, Roger Dingledine
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : /**
       7             :  * \file escape.c
       8             :  * \brief Escape untrusted strings before sending them to the log.
       9             :  **/
      10             : 
      11             : #include "lib/log/escape.h"
      12             : #include "lib/log/util_bug.h"
      13             : #include "lib/string/compat_ctype.h"
      14             : #include "lib/string/printf.h"
      15             : #include "lib/malloc/malloc.h"
      16             : 
      17             : /** Allocate and return a new string representing the contents of <b>s</b>,
      18             :  * surrounded by quotes and using standard C escapes.
      19             :  *
      20             :  * Generally, we use this for logging values that come in over the network to
      21             :  * keep them from tricking users, and for sending certain values to the
      22             :  * controller.
      23             :  *
      24             :  * We trust values from the resolver, OS, configuration file, and command line
      25             :  * to not be maliciously ill-formed.  We validate incoming routerdescs and
      26             :  * SOCKS requests and addresses from BEGIN cells as they're parsed;
      27             :  * afterwards, we trust them as non-malicious.
      28             :  */
      29             : char *
      30        3657 : esc_for_log(const char *s)
      31             : {
      32        3657 :   const char *cp;
      33        3657 :   char *result, *outp;
      34        3657 :   size_t len = 3;
      35        3657 :   if (!s) {
      36           1 :     return tor_strdup("(null)");
      37             :   }
      38             : 
      39      107843 :   for (cp = s; *cp; ++cp) {
      40      104187 :     switch (*cp) {
      41        1408 :       case '\\':
      42             :       case '\"':
      43             :       case '\'':
      44             :       case '\r':
      45             :       case '\n':
      46             :       case '\t':
      47        1408 :         len += 2;
      48        1408 :         break;
      49      102779 :       default:
      50      102779 :         if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127)
      51       97158 :           ++len;
      52             :         else
      53        5621 :           len += 4;
      54             :         break;
      55             :     }
      56             :   }
      57             : 
      58        3656 :   tor_assert(len <= SSIZE_MAX);
      59             : 
      60        3656 :   result = outp = tor_malloc(len);
      61        3656 :   *outp++ = '\"';
      62      107843 :   for (cp = s; *cp; ++cp) {
      63             :     /* This assertion should always succeed, since we will write at least
      64             :      * one char here, and two chars for closing quote and nul later */
      65      104187 :     tor_assert((outp-result) < (ssize_t)len-2);
      66      104187 :     switch (*cp) {
      67         714 :       case '\\':
      68             :       case '\"':
      69             :       case '\'':
      70         714 :         *outp++ = '\\';
      71         714 :         *outp++ = *cp;
      72         714 :         break;
      73         266 :       case '\n':
      74         266 :         *outp++ = '\\';
      75         266 :         *outp++ = 'n';
      76         266 :         break;
      77         194 :       case '\t':
      78         194 :         *outp++ = '\\';
      79         194 :         *outp++ = 't';
      80         194 :         break;
      81         234 :       case '\r':
      82         234 :         *outp++ = '\\';
      83         234 :         *outp++ = 'r';
      84         234 :         break;
      85      102779 :       default:
      86      102779 :         if (TOR_ISPRINT(*cp) && ((uint8_t)*cp)<127) {
      87       97158 :           *outp++ = *cp;
      88             :         } else {
      89        5621 :           tor_assert((outp-result) < (ssize_t)len-4);
      90        5621 :           tor_snprintf(outp, 5, "\\%03o", (int)(uint8_t) *cp);
      91        5621 :           outp += 4;
      92             :         }
      93             :         break;
      94             :     }
      95             :   }
      96             : 
      97        3656 :   tor_assert((outp-result) <= (ssize_t)len-2);
      98        3656 :   *outp++ = '\"';
      99        3656 :   *outp++ = 0;
     100             : 
     101        3656 :   return result;
     102             : }
     103             : 
     104             : /** Similar to esc_for_log. Allocate and return a new string representing
     105             :  * the first n characters in <b>chars</b>, surround by quotes and using
     106             :  * standard C escapes. If a NUL character is encountered in <b>chars</b>,
     107             :  * the resulting string will be terminated there.
     108             :  */
     109             : char *
     110          40 : esc_for_log_len(const char *chars, size_t n)
     111             : {
     112          40 :   char *string = tor_strndup(chars, n);
     113          40 :   char *string_escaped = esc_for_log(string);
     114          40 :   tor_free(string);
     115          40 :   return string_escaped;
     116             : }
     117             : 
     118             : /** Allocate and return a new string representing the contents of <b>s</b>,
     119             :  * surrounded by quotes and using standard C escapes.
     120             :  *
     121             :  * THIS FUNCTION IS NOT REENTRANT.  Don't call it from outside the main
     122             :  * thread.  Also, each call invalidates the last-returned value, so don't
     123             :  * try log_warn(LD_GENERAL, "%s %s", escaped(a), escaped(b));
     124             :  */
     125             : const char *
     126        7842 : escaped(const char *s)
     127             : {
     128        7842 :   static char *escaped_val_ = NULL;
     129        7842 :   tor_free(escaped_val_);
     130             : 
     131        7842 :   if (s)
     132        3369 :     escaped_val_ = esc_for_log(s);
     133             :   else
     134             :     escaped_val_ = NULL;
     135             : 
     136        7842 :   return escaped_val_;
     137             : }

Generated by: LCOV version 1.14