LCOV - code coverage report
Current view: top level - test - test-escape.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 118 118 100.0 %
Date: 2019-08-23 13:36:53 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 74 118 62.7 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include "alloc-util.h"
       4                 :            : #include "escape.h"
       5                 :            : #include "macro.h"
       6                 :            : #include "tests.h"
       7                 :            : 
       8                 :          4 : static void test_cescape(void) {
       9                 :          4 :         _cleanup_free_ char *t;
      10                 :            : 
      11         [ -  + ]:          4 :         assert_se(t = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
      12         [ -  + ]:          4 :         assert_se(streq(t, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
      13                 :          4 : }
      14                 :            : 
      15                 :          4 : static void test_xescape(void) {
      16                 :          4 :         _cleanup_free_ char *t;
      17                 :            : 
      18         [ -  + ]:          4 :         assert_se(t = xescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", ""));
      19         [ -  + ]:          4 :         assert_se(streq(t, "abc\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb"));
      20                 :          4 : }
      21                 :            : 
      22                 :          8 : static void test_xescape_full(bool eight_bits) {
      23                 :         16 :         const char* escaped = !eight_bits ?
      24         [ +  + ]:          8 :                 "a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb" :
      25                 :            :                 "a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\177\234\313";
      26         [ +  + ]:          8 :         const unsigned full_fit = !eight_bits ? 55 : 46;
      27                 :            : 
      28         [ +  + ]:        488 :         for (unsigned i = 0; i < 60; i++) {
      29                 :        480 :                 _cleanup_free_ char *t;
      30                 :            : 
      31         [ -  + ]:        480 :                 assert_se(t = xescape_full("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", "b", i, eight_bits));
      32                 :            : 
      33         [ +  - ]:        480 :                 log_info("%02d: %s", i, t);
      34                 :            : 
      35         [ +  + ]:        480 :                 if (i >= full_fit)
      36         [ -  + ]:         76 :                         assert_se(streq(t, escaped));
      37         [ +  + ]:        404 :                 else if (i >= 3) {
      38                 :            :                         /* We need up to four columns, so up to three three columns may be wasted */
      39   [ +  +  +  +  :        380 :                         assert_se(strlen(t) == i || strlen(t) == i - 1 || strlen(t) == i - 2 || strlen(t) == i - 3);
          +  +  +  +  +  
                +  -  + ]
      40   [ +  +  +  +  :        380 :                         assert_se(strneq(t, escaped, i - 3) || strneq(t, escaped, i - 4) ||
          +  +  +  +  +  
                +  -  + ]
      41                 :            :                                   strneq(t, escaped, i - 5) || strneq(t, escaped, i - 6));
      42         [ -  + ]:        380 :                         assert_se(endswith(t, "..."));
      43                 :            :                 } else {
      44         [ -  + ]:         24 :                         assert_se(strlen(t) == i);
      45         [ -  + ]:         24 :                         assert_se(strneq(t, "...", i));
      46                 :            :                 }
      47                 :            :         }
      48                 :          8 : }
      49                 :            : 
      50                 :          4 : static void test_cunescape(void) {
      51                 :          4 :         _cleanup_free_ char *unescaped;
      52                 :            : 
      53         [ -  + ]:          4 :         assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
      54         [ -  + ]:          4 :         assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
      55         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
      56                 :          4 :         unescaped = mfree(unescaped);
      57                 :            : 
      58                 :            :         /* incomplete sequences */
      59         [ -  + ]:          4 :         assert_se(cunescape("\\x0", 0, &unescaped) < 0);
      60         [ -  + ]:          4 :         assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0);
      61         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "\\x0"));
      62                 :          4 :         unescaped = mfree(unescaped);
      63                 :            : 
      64         [ -  + ]:          4 :         assert_se(cunescape("\\x", 0, &unescaped) < 0);
      65         [ -  + ]:          4 :         assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0);
      66         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "\\x"));
      67                 :          4 :         unescaped = mfree(unescaped);
      68                 :            : 
      69         [ -  + ]:          4 :         assert_se(cunescape("\\", 0, &unescaped) < 0);
      70         [ -  + ]:          4 :         assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0);
      71         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "\\"));
      72                 :          4 :         unescaped = mfree(unescaped);
      73                 :            : 
      74         [ -  + ]:          4 :         assert_se(cunescape("\\11", 0, &unescaped) < 0);
      75         [ -  + ]:          4 :         assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0);
      76         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "\\11"));
      77                 :          4 :         unescaped = mfree(unescaped);
      78                 :            : 
      79         [ -  + ]:          4 :         assert_se(cunescape("\\1", 0, &unescaped) < 0);
      80         [ -  + ]:          4 :         assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0);
      81         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "\\1"));
      82                 :          4 :         unescaped = mfree(unescaped);
      83                 :            : 
      84         [ -  + ]:          4 :         assert_se(cunescape("\\u0000", 0, &unescaped) < 0);
      85         [ -  + ]:          4 :         assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0);
      86         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "ßßΠA"));
      87                 :          4 :         unescaped = mfree(unescaped);
      88                 :            : 
      89         [ -  + ]:          4 :         assert_se(cunescape("\\073", 0, &unescaped) >= 0);
      90         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, ";"));
      91                 :          4 :         unescaped = mfree(unescaped);
      92                 :            : 
      93         [ -  + ]:          4 :         assert_se(cunescape("A=A\\\\x0aB", 0, &unescaped) >= 0);
      94         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "A=A\\x0aB"));
      95                 :          4 :         unescaped = mfree(unescaped);
      96                 :            : 
      97         [ -  + ]:          4 :         assert_se(cunescape("A=A\\\\x0aB", UNESCAPE_RELAX, &unescaped) >= 0);
      98         [ -  + ]:          4 :         assert_se(streq_ptr(unescaped, "A=A\\x0aB"));
      99                 :          4 : }
     100                 :            : 
     101                 :         20 : static void test_shell_escape_one(const char *s, const char *bad, const char *expected) {
     102                 :         20 :         _cleanup_free_ char *r;
     103                 :            : 
     104         [ -  + ]:         20 :         assert_se(r = shell_escape(s, bad));
     105         [ -  + ]:         20 :         assert_se(streq_ptr(r, expected));
     106                 :         20 : }
     107                 :            : 
     108                 :          4 : static void test_shell_escape(void) {
     109                 :          4 :         test_shell_escape_one("", "", "");
     110                 :          4 :         test_shell_escape_one("\\", "", "\\\\");
     111                 :          4 :         test_shell_escape_one("foobar", "", "foobar");
     112                 :          4 :         test_shell_escape_one("foobar", "o", "f\\o\\obar");
     113                 :          4 :         test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz");
     114                 :          4 : }
     115                 :            : 
     116                 :         88 : static void test_shell_maybe_quote_one(const char *s,
     117                 :            :                                        EscapeStyle style,
     118                 :            :                                        const char *expected) {
     119                 :         88 :         _cleanup_free_ char *ret = NULL;
     120                 :            : 
     121         [ -  + ]:         88 :         assert_se(ret = shell_maybe_quote(s, style));
     122         [ +  - ]:         88 :         log_debug("[%s] → [%s] (%s)", s, ret, expected);
     123         [ -  + ]:         88 :         assert_se(streq(ret, expected));
     124                 :         88 : }
     125                 :            : 
     126                 :          4 : static void test_shell_maybe_quote(void) {
     127                 :            : 
     128                 :          4 :         test_shell_maybe_quote_one("", ESCAPE_BACKSLASH, "");
     129                 :          4 :         test_shell_maybe_quote_one("", ESCAPE_POSIX, "");
     130                 :          4 :         test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH, "\"\\\\\"");
     131                 :          4 :         test_shell_maybe_quote_one("\\", ESCAPE_POSIX, "$'\\\\'");
     132                 :          4 :         test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH, "\"\\\"\"");
     133                 :          4 :         test_shell_maybe_quote_one("\"", ESCAPE_POSIX, "$'\"'");
     134                 :          4 :         test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH, "foobar");
     135                 :          4 :         test_shell_maybe_quote_one("foobar", ESCAPE_POSIX, "foobar");
     136                 :          4 :         test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH, "\"foo bar\"");
     137                 :          4 :         test_shell_maybe_quote_one("foo bar", ESCAPE_POSIX, "$'foo bar'");
     138                 :          4 :         test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH, "\"foo\tbar\"");
     139                 :          4 :         test_shell_maybe_quote_one("foo\tbar", ESCAPE_POSIX, "$'foo\\tbar'");
     140                 :          4 :         test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH, "\"foo\nbar\"");
     141                 :          4 :         test_shell_maybe_quote_one("foo\nbar", ESCAPE_POSIX, "$'foo\\nbar'");
     142                 :          4 :         test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH, "\"foo \\\"bar\\\" waldo\"");
     143                 :          4 :         test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_POSIX, "$'foo \"bar\" waldo'");
     144                 :          4 :         test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH, "\"foo\\$bar\"");
     145                 :          4 :         test_shell_maybe_quote_one("foo$bar", ESCAPE_POSIX, "$'foo$bar'");
     146                 :            : 
     147                 :            :         /* Note that current users disallow control characters, so this "test"
     148                 :            :          * is here merely to establish current behaviour. If control characters
     149                 :            :          * were allowed, they should be quoted, i.e. \001 should become \\001. */
     150                 :          4 :         test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH, "\"a\nb\001\"");
     151                 :          4 :         test_shell_maybe_quote_one("a\nb\001", ESCAPE_POSIX, "$'a\\nb\001'");
     152                 :            : 
     153                 :          4 :         test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH, "\"foo!bar\"");
     154                 :          4 :         test_shell_maybe_quote_one("foo!bar", ESCAPE_POSIX, "$'foo!bar'");
     155                 :          4 : }
     156                 :            : 
     157                 :          4 : int main(int argc, char *argv[]) {
     158                 :          4 :         test_setup_logging(LOG_DEBUG);
     159                 :            : 
     160                 :          4 :         test_cescape();
     161                 :          4 :         test_xescape();
     162                 :          4 :         test_xescape_full(false);
     163                 :          4 :         test_xescape_full(true);
     164                 :          4 :         test_cunescape();
     165                 :          4 :         test_shell_escape();
     166                 :          4 :         test_shell_maybe_quote();
     167                 :            : 
     168                 :          4 :         return 0;
     169                 :            : }

Generated by: LCOV version 1.14