LCOV - code coverage report
Current view: top level - test - test-escape.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 118 118 100.0 %
Date: 2019-08-22 15:41:25 Functions: 9 9 100.0 %

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

Generated by: LCOV version 1.14