github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/cmd/libsnap-confine-private/string-utils-test.c (about)

     1  /*
     2   * Copyright (C) 2016-2017 Canonical Ltd
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License version 3 as
     6   * published by the Free Software Foundation.
     7   *
     8   * This program is distributed in the hope that it will be useful,
     9   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11   * GNU General Public License for more details.
    12   *
    13   * You should have received a copy of the GNU General Public License
    14   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15   *
    16   */
    17  
    18  #include "string-utils.h"
    19  #include "string-utils.c"
    20  
    21  #include <glib.h>
    22  
    23  static void test_sc_streq(void)
    24  {
    25  	g_assert_false(sc_streq(NULL, NULL));
    26  	g_assert_false(sc_streq(NULL, "text"));
    27  	g_assert_false(sc_streq("text", NULL));
    28  	g_assert_false(sc_streq("foo", "bar"));
    29  	g_assert_false(sc_streq("foo", "barbar"));
    30  	g_assert_false(sc_streq("foofoo", "bar"));
    31  	g_assert_true(sc_streq("text", "text"));
    32  	g_assert_true(sc_streq("", ""));
    33  }
    34  
    35  static void test_sc_endswith(void)
    36  {
    37  	// NULL doesn't end with anything, nothing ends with NULL
    38  	g_assert_false(sc_endswith("", NULL));
    39  	g_assert_false(sc_endswith(NULL, ""));
    40  	g_assert_false(sc_endswith(NULL, NULL));
    41  	// Empty string ends with an empty string
    42  	g_assert_true(sc_endswith("", ""));
    43  	// Ends-with (matches)
    44  	g_assert_true(sc_endswith("foobar", "bar"));
    45  	g_assert_true(sc_endswith("foobar", "ar"));
    46  	g_assert_true(sc_endswith("foobar", "r"));
    47  	g_assert_true(sc_endswith("foobar", ""));
    48  	g_assert_true(sc_endswith("bar", "bar"));
    49  	// Ends-with (non-matches)
    50  	g_assert_false(sc_endswith("foobar", "quux"));
    51  	g_assert_false(sc_endswith("", "bar"));
    52  	g_assert_false(sc_endswith("b", "bar"));
    53  	g_assert_false(sc_endswith("ba", "bar"));
    54  }
    55  
    56  static void test_sc_startswith(void)
    57  {
    58  	// NULL doesn't start with anything, nothing starts with NULL
    59  	g_assert_false(sc_startswith("", NULL));
    60  	g_assert_false(sc_startswith(NULL, ""));
    61  	g_assert_false(sc_startswith(NULL, NULL));
    62  	// Empty string starts with an empty string
    63  	g_assert_true(sc_startswith("", ""));
    64  	// Starts-with (matches)
    65  	g_assert_true(sc_startswith("foobar", "foo"));
    66  	g_assert_true(sc_startswith("foobar", "fo"));
    67  	g_assert_true(sc_startswith("foobar", "f"));
    68  	g_assert_true(sc_startswith("foobar", ""));
    69  	g_assert_true(sc_startswith("bar", "bar"));
    70  	// Starts-with (non-matches)
    71  	g_assert_false(sc_startswith("foobar", "quux"));
    72  	g_assert_false(sc_startswith("", "bar"));
    73  	g_assert_false(sc_startswith("b", "bar"));
    74  	g_assert_false(sc_startswith("ba", "bar"));
    75  }
    76  
    77  static void test_sc_must_snprintf(void)
    78  {
    79  	char buf[5] = { 0 };
    80  	sc_must_snprintf(buf, sizeof buf, "1234");
    81  	g_assert_cmpstr(buf, ==, "1234");
    82  }
    83  
    84  static void test_sc_must_snprintf__fail(void)
    85  {
    86  	if (g_test_subprocess()) {
    87  		char buf[5];
    88  		sc_must_snprintf(buf, sizeof buf, "12345");
    89  		g_test_message("expected sc_must_snprintf not to return");
    90  		g_test_fail();
    91  		return;
    92  	}
    93  	g_test_trap_subprocess(NULL, 0, 0);
    94  	g_test_trap_assert_failed();
    95  	g_test_trap_assert_stderr("cannot format string: 1234\n");
    96  }
    97  
    98  // Check that appending to a buffer works OK.
    99  static void test_sc_string_append(void)
   100  {
   101  	union {
   102  		char bigbuf[6];
   103  		struct {
   104  			signed char canary1;
   105  			char buf[4];
   106  			signed char canary2;
   107  		};
   108  	} data = {
   109  		.buf = {
   110  			'f', '\0', 0xFF, 0xFF},.canary1 = ~0,.canary2 = ~0,
   111  	};
   112  
   113  	// Sanity check, ensure that the layout of structures is as spelled above.
   114  	// (first canary1, then buf and finally canary2.
   115  	g_assert_cmpint(((char *)&data.buf[0]) - ((char *)&data.canary1), ==,
   116  			1);
   117  	g_assert_cmpint(((char *)&data.buf[4]) - ((char *)&data.canary2), ==,
   118  			0);
   119  
   120  	sc_string_append(data.buf, sizeof data.buf, "oo");
   121  
   122  	// Check that we didn't corrupt either canary.
   123  	g_assert_cmpint(data.canary1, ==, ~0);
   124  	g_assert_cmpint(data.canary2, ==, ~0);
   125  
   126  	// Check that we got the result that was expected.
   127  	g_assert_cmpstr(data.buf, ==, "foo");
   128  }
   129  
   130  // Check that appending an empty string to a full buffer is valid.
   131  static void test_sc_string_append__empty_to_full(void)
   132  {
   133  	union {
   134  		char bigbuf[6];
   135  		struct {
   136  			signed char canary1;
   137  			char buf[4];
   138  			signed char canary2;
   139  		};
   140  	} data = {
   141  		.buf = {
   142  			'f', 'o', 'o', '\0'},.canary1 = ~0,.canary2 = ~0,
   143  	};
   144  
   145  	// Sanity check, ensure that the layout of structures is as spelled above.
   146  	// (first canary1, then buf and finally canary2.
   147  	g_assert_cmpint(((char *)&data.buf[0]) - ((char *)&data.canary1), ==,
   148  			1);
   149  	g_assert_cmpint(((char *)&data.buf[4]) - ((char *)&data.canary2), ==,
   150  			0);
   151  
   152  	sc_string_append(data.buf, sizeof data.buf, "");
   153  
   154  	// Check that we didn't corrupt either canary.
   155  	g_assert_cmpint(data.canary1, ==, ~0);
   156  	g_assert_cmpint(data.canary2, ==, ~0);
   157  
   158  	// Check that we got the result that was expected.
   159  	g_assert_cmpstr(data.buf, ==, "foo");
   160  }
   161  
   162  // Check that the overflow detection works.
   163  static void test_sc_string_append__overflow(void)
   164  {
   165  	if (g_test_subprocess()) {
   166  		char buf[4] = { 0 };
   167  
   168  		// Try to append a string that's one character too long.
   169  		sc_string_append(buf, sizeof buf, "1234");
   170  
   171  		g_test_message("expected sc_string_append not to return");
   172  		g_test_fail();
   173  		return;
   174  	}
   175  	g_test_trap_subprocess(NULL, 0, 0);
   176  	g_test_trap_assert_failed();
   177  	g_test_trap_assert_stderr
   178  	    ("cannot append string: str is too long or unterminated\n");
   179  }
   180  
   181  // Check that the uninitialized buffer detection works.
   182  static void test_sc_string_append__uninitialized_buf(void)
   183  {
   184  	if (g_test_subprocess()) {
   185  		char buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
   186  
   187  		// Try to append a string to a buffer which is not a valic C-string.
   188  		sc_string_append(buf, sizeof buf, "");
   189  
   190  		g_test_message("expected sc_string_append not to return");
   191  		g_test_fail();
   192  		return;
   193  	}
   194  	g_test_trap_subprocess(NULL, 0, 0);
   195  	g_test_trap_assert_failed();
   196  	g_test_trap_assert_stderr
   197  	    ("cannot append string: dst is unterminated\n");
   198  }
   199  
   200  // Check that `buf' cannot be NULL.
   201  static void test_sc_string_append__NULL_buf(void)
   202  {
   203  	if (g_test_subprocess()) {
   204  		char buf[4];
   205  
   206  		sc_string_append(NULL, sizeof buf, "foo");
   207  
   208  		g_test_message("expected sc_string_append not to return");
   209  		g_test_fail();
   210  		return;
   211  	}
   212  	g_test_trap_subprocess(NULL, 0, 0);
   213  	g_test_trap_assert_failed();
   214  	g_test_trap_assert_stderr("cannot append string: buffer is NULL\n");
   215  }
   216  
   217  // Check that `src' cannot be NULL.
   218  static void test_sc_string_append__NULL_str(void)
   219  {
   220  	if (g_test_subprocess()) {
   221  		char buf[4];
   222  
   223  		sc_string_append(buf, sizeof buf, NULL);
   224  
   225  		g_test_message("expected sc_string_append not to return");
   226  		g_test_fail();
   227  		return;
   228  	}
   229  	g_test_trap_subprocess(NULL, 0, 0);
   230  	g_test_trap_assert_failed();
   231  	g_test_trap_assert_stderr("cannot append string: string is NULL\n");
   232  }
   233  
   234  static void test_sc_string_init__normal(void)
   235  {
   236  	char buf[1] = { 0xFF };
   237  
   238  	sc_string_init(buf, sizeof buf);
   239  	g_assert_cmpint(buf[0], ==, 0);
   240  }
   241  
   242  static void test_sc_string_init__empty_buf(void)
   243  {
   244  	if (g_test_subprocess()) {
   245  		char buf[1] = { 0xFF };
   246  
   247  		sc_string_init(buf, 0);
   248  
   249  		g_test_message("expected sc_string_init not to return");
   250  		g_test_fail();
   251  		return;
   252  	}
   253  	g_test_trap_subprocess(NULL, 0, 0);
   254  	g_test_trap_assert_failed();
   255  	g_test_trap_assert_stderr
   256  	    ("cannot initialize string, buffer is too small\n");
   257  }
   258  
   259  static void test_sc_string_init__NULL_buf(void)
   260  {
   261  	if (g_test_subprocess()) {
   262  		sc_string_init(NULL, 1);
   263  
   264  		g_test_message("expected sc_string_init not to return");
   265  		g_test_fail();
   266  		return;
   267  	}
   268  	g_test_trap_subprocess(NULL, 0, 0);
   269  	g_test_trap_assert_failed();
   270  	g_test_trap_assert_stderr("cannot initialize string, buffer is NULL\n");
   271  }
   272  
   273  static void test_sc_string_append_char__uninitialized_buf(void)
   274  {
   275  	if (g_test_subprocess()) {
   276  		char buf[2] = { 0xFF, 0xFF };
   277  		sc_string_append_char(buf, sizeof buf, 'a');
   278  
   279  		g_test_message("expected sc_string_append_char not to return");
   280  		g_test_fail();
   281  		return;
   282  	}
   283  	g_test_trap_subprocess(NULL, 0, 0);
   284  	g_test_trap_assert_failed();
   285  	g_test_trap_assert_stderr
   286  	    ("cannot append character: dst is unterminated\n");
   287  }
   288  
   289  static void test_sc_string_append_char__NULL_buf(void)
   290  {
   291  	if (g_test_subprocess()) {
   292  		sc_string_append_char(NULL, 2, 'a');
   293  
   294  		g_test_message("expected sc_string_append_char not to return");
   295  		g_test_fail();
   296  		return;
   297  	}
   298  	g_test_trap_subprocess(NULL, 0, 0);
   299  	g_test_trap_assert_failed();
   300  	g_test_trap_assert_stderr("cannot append character: buffer is NULL\n");
   301  }
   302  
   303  static void test_sc_string_append_char__overflow(void)
   304  {
   305  	if (g_test_subprocess()) {
   306  		char buf[1] = { 0 };
   307  		sc_string_append_char(buf, sizeof buf, 'a');
   308  
   309  		g_test_message("expected sc_string_append_char not to return");
   310  		g_test_fail();
   311  		return;
   312  	}
   313  	g_test_trap_subprocess(NULL, 0, 0);
   314  	g_test_trap_assert_failed();
   315  	g_test_trap_assert_stderr
   316  	    ("cannot append character: not enough space\n");
   317  }
   318  
   319  static void test_sc_string_append_char__invalid_zero(void)
   320  {
   321  	if (g_test_subprocess()) {
   322  		char buf[2] = { 0 };
   323  		sc_string_append_char(buf, sizeof buf, '\0');
   324  
   325  		g_test_message("expected sc_string_append_char not to return");
   326  		g_test_fail();
   327  		return;
   328  	}
   329  	g_test_trap_subprocess(NULL, 0, 0);
   330  	g_test_trap_assert_failed();
   331  	g_test_trap_assert_stderr
   332  	    ("cannot append character: cannot append string terminator\n");
   333  }
   334  
   335  static void test_sc_string_append_char__normal(void)
   336  {
   337  	char buf[16];
   338  	size_t len;
   339  	sc_string_init(buf, sizeof buf);
   340  
   341  	len = sc_string_append_char(buf, sizeof buf, 'h');
   342  	g_assert_cmpstr(buf, ==, "h");
   343  	g_assert_cmpint(len, ==, 1);
   344  	len = sc_string_append_char(buf, sizeof buf, 'e');
   345  	g_assert_cmpstr(buf, ==, "he");
   346  	g_assert_cmpint(len, ==, 2);
   347  	len = sc_string_append_char(buf, sizeof buf, 'l');
   348  	g_assert_cmpstr(buf, ==, "hel");
   349  	g_assert_cmpint(len, ==, 3);
   350  	len = sc_string_append_char(buf, sizeof buf, 'l');
   351  	g_assert_cmpstr(buf, ==, "hell");
   352  	g_assert_cmpint(len, ==, 4);
   353  	len = sc_string_append_char(buf, sizeof buf, 'o');
   354  	g_assert_cmpstr(buf, ==, "hello");
   355  	g_assert_cmpint(len, ==, 5);
   356  }
   357  
   358  static void test_sc_string_append_char_pair__uninitialized_buf(void)
   359  {
   360  	if (g_test_subprocess()) {
   361  		char buf[3] = { 0xFF, 0xFF, 0xFF };
   362  		sc_string_append_char_pair(buf, sizeof buf, 'a', 'b');
   363  
   364  		g_test_message
   365  		    ("expected sc_string_append_char_pair not to return");
   366  		g_test_fail();
   367  		return;
   368  	}
   369  	g_test_trap_subprocess(NULL, 0, 0);
   370  	g_test_trap_assert_failed();
   371  	g_test_trap_assert_stderr
   372  	    ("cannot append character pair: dst is unterminated\n");
   373  }
   374  
   375  static void test_sc_string_append_char_pair__NULL_buf(void)
   376  {
   377  	if (g_test_subprocess()) {
   378  		sc_string_append_char_pair(NULL, 3, 'a', 'b');
   379  
   380  		g_test_message
   381  		    ("expected sc_string_append_char_pair not to return");
   382  		g_test_fail();
   383  		return;
   384  	}
   385  	g_test_trap_subprocess(NULL, 0, 0);
   386  	g_test_trap_assert_failed();
   387  	g_test_trap_assert_stderr
   388  	    ("cannot append character pair: buffer is NULL\n");
   389  }
   390  
   391  static void test_sc_string_append_char_pair__overflow(void)
   392  {
   393  	if (g_test_subprocess()) {
   394  		char buf[2] = { 0 };
   395  		sc_string_append_char_pair(buf, sizeof buf, 'a', 'b');
   396  
   397  		g_test_message
   398  		    ("expected sc_string_append_char_pair not to return");
   399  		g_test_fail();
   400  		return;
   401  	}
   402  	g_test_trap_subprocess(NULL, 0, 0);
   403  	g_test_trap_assert_failed();
   404  	g_test_trap_assert_stderr
   405  	    ("cannot append character pair: not enough space\n");
   406  }
   407  
   408  static void test_sc_string_append_char_pair__invalid_zero_c1(void)
   409  {
   410  	if (g_test_subprocess()) {
   411  		char buf[3] = { 0 };
   412  		sc_string_append_char_pair(buf, sizeof buf, '\0', 'a');
   413  
   414  		g_test_message
   415  		    ("expected sc_string_append_char_pair not to return");
   416  		g_test_fail();
   417  		return;
   418  	}
   419  	g_test_trap_subprocess(NULL, 0, 0);
   420  	g_test_trap_assert_failed();
   421  	g_test_trap_assert_stderr
   422  	    ("cannot append character pair: cannot append string terminator\n");
   423  }
   424  
   425  static void test_sc_string_append_char_pair__invalid_zero_c2(void)
   426  {
   427  	if (g_test_subprocess()) {
   428  		char buf[3] = { 0 };
   429  		sc_string_append_char_pair(buf, sizeof buf, 'a', '\0');
   430  
   431  		g_test_message
   432  		    ("expected sc_string_append_char_pair not to return");
   433  		g_test_fail();
   434  		return;
   435  	}
   436  	g_test_trap_subprocess(NULL, 0, 0);
   437  	g_test_trap_assert_failed();
   438  	g_test_trap_assert_stderr
   439  	    ("cannot append character pair: cannot append string terminator\n");
   440  }
   441  
   442  static void test_sc_string_append_char_pair__normal(void)
   443  {
   444  	char buf[16];
   445  	size_t len;
   446  	sc_string_init(buf, sizeof buf);
   447  
   448  	len = sc_string_append_char_pair(buf, sizeof buf, 'h', 'e');
   449  	g_assert_cmpstr(buf, ==, "he");
   450  	g_assert_cmpint(len, ==, 2);
   451  	len = sc_string_append_char_pair(buf, sizeof buf, 'l', 'l');
   452  	g_assert_cmpstr(buf, ==, "hell");
   453  	g_assert_cmpint(len, ==, 4);
   454  	len = sc_string_append_char_pair(buf, sizeof buf, 'o', '!');
   455  	g_assert_cmpstr(buf, ==, "hello!");
   456  	g_assert_cmpint(len, ==, 6);
   457  }
   458  
   459  static void test_sc_string_quote_NULL_str(void)
   460  {
   461  	if (g_test_subprocess()) {
   462  		char buf[16] = { 0 };
   463  		sc_string_quote(buf, sizeof buf, NULL);
   464  
   465  		g_test_message("expected sc_string_quote not to return");
   466  		g_test_fail();
   467  		return;
   468  	}
   469  	g_test_trap_subprocess(NULL, 0, 0);
   470  	g_test_trap_assert_failed();
   471  	g_test_trap_assert_stderr("cannot quote string: string is NULL\n");
   472  }
   473  
   474  static void test_quoting_of(bool tested[], int c, const char *expected)
   475  {
   476  	char buf[16];
   477  
   478  	g_assert_cmpint(c, >=, 0);
   479  	g_assert_cmpint(c, <=, 255);
   480  
   481  	// Create an input string with one character.
   482  	char input[2] = { (unsigned char)c, 0 };
   483  	sc_string_quote(buf, sizeof buf, input);
   484  
   485  	// Ensure it was quoted as we expected.
   486  	g_assert_cmpstr(buf, ==, expected);
   487  
   488  	tested[c] = true;
   489  }
   490  
   491  static void test_sc_string_quote(void)
   492  {
   493  #define DQ "\""
   494  	char buf[16];
   495  	bool is_tested[256] = { false };
   496  
   497  	// Exhaustive test for quoting of every 8bit input.  This is very verbose
   498  	// but the goal is to have a very obvious and correct test that ensures no
   499  	// edge case is lost.
   500  	//
   501  	// block 1: 0x00 - 0x0f
   502  	test_quoting_of(is_tested, 0x00, DQ "" DQ);
   503  	test_quoting_of(is_tested, 0x01, DQ "\\x01" DQ);
   504  	test_quoting_of(is_tested, 0x02, DQ "\\x02" DQ);
   505  	test_quoting_of(is_tested, 0x03, DQ "\\x03" DQ);
   506  	test_quoting_of(is_tested, 0x04, DQ "\\x04" DQ);
   507  	test_quoting_of(is_tested, 0x05, DQ "\\x05" DQ);
   508  	test_quoting_of(is_tested, 0x06, DQ "\\x06" DQ);
   509  	test_quoting_of(is_tested, 0x07, DQ "\\x07" DQ);
   510  	test_quoting_of(is_tested, 0x08, DQ "\\x08" DQ);
   511  	test_quoting_of(is_tested, 0x09, DQ "\\t" DQ);
   512  	test_quoting_of(is_tested, 0x0a, DQ "\\n" DQ);
   513  	test_quoting_of(is_tested, 0x0b, DQ "\\v" DQ);
   514  	test_quoting_of(is_tested, 0x0c, DQ "\\x0c" DQ);
   515  	test_quoting_of(is_tested, 0x0d, DQ "\\r" DQ);
   516  	test_quoting_of(is_tested, 0x0e, DQ "\\x0e" DQ);
   517  	test_quoting_of(is_tested, 0x0f, DQ "\\x0f" DQ);
   518  	// block 2: 0x10 - 0x1f
   519  	test_quoting_of(is_tested, 0x10, DQ "\\x10" DQ);
   520  	test_quoting_of(is_tested, 0x11, DQ "\\x11" DQ);
   521  	test_quoting_of(is_tested, 0x12, DQ "\\x12" DQ);
   522  	test_quoting_of(is_tested, 0x13, DQ "\\x13" DQ);
   523  	test_quoting_of(is_tested, 0x14, DQ "\\x14" DQ);
   524  	test_quoting_of(is_tested, 0x15, DQ "\\x15" DQ);
   525  	test_quoting_of(is_tested, 0x16, DQ "\\x16" DQ);
   526  	test_quoting_of(is_tested, 0x17, DQ "\\x17" DQ);
   527  	test_quoting_of(is_tested, 0x18, DQ "\\x18" DQ);
   528  	test_quoting_of(is_tested, 0x19, DQ "\\x19" DQ);
   529  	test_quoting_of(is_tested, 0x1a, DQ "\\x1a" DQ);
   530  	test_quoting_of(is_tested, 0x1b, DQ "\\x1b" DQ);
   531  	test_quoting_of(is_tested, 0x1c, DQ "\\x1c" DQ);
   532  	test_quoting_of(is_tested, 0x1d, DQ "\\x1d" DQ);
   533  	test_quoting_of(is_tested, 0x1e, DQ "\\x1e" DQ);
   534  	test_quoting_of(is_tested, 0x1f, DQ "\\x1f" DQ);
   535  	// block 3: 0x20 - 0x2f
   536  	test_quoting_of(is_tested, 0x20, DQ " " DQ);
   537  	test_quoting_of(is_tested, 0x21, DQ "!" DQ);
   538  	test_quoting_of(is_tested, 0x22, DQ "\\\"" DQ);
   539  	test_quoting_of(is_tested, 0x23, DQ "#" DQ);
   540  	test_quoting_of(is_tested, 0x24, DQ "$" DQ);
   541  	test_quoting_of(is_tested, 0x25, DQ "%" DQ);
   542  	test_quoting_of(is_tested, 0x26, DQ "&" DQ);
   543  	test_quoting_of(is_tested, 0x27, DQ "'" DQ);
   544  	test_quoting_of(is_tested, 0x28, DQ "(" DQ);
   545  	test_quoting_of(is_tested, 0x29, DQ ")" DQ);
   546  	test_quoting_of(is_tested, 0x2a, DQ "*" DQ);
   547  	test_quoting_of(is_tested, 0x2b, DQ "+" DQ);
   548  	test_quoting_of(is_tested, 0x2c, DQ "," DQ);
   549  	test_quoting_of(is_tested, 0x2d, DQ "-" DQ);
   550  	test_quoting_of(is_tested, 0x2e, DQ "." DQ);
   551  	test_quoting_of(is_tested, 0x2f, DQ "/" DQ);
   552  	// block 4: 0x30 - 0x3f
   553  	test_quoting_of(is_tested, 0x30, DQ "0" DQ);
   554  	test_quoting_of(is_tested, 0x31, DQ "1" DQ);
   555  	test_quoting_of(is_tested, 0x32, DQ "2" DQ);
   556  	test_quoting_of(is_tested, 0x33, DQ "3" DQ);
   557  	test_quoting_of(is_tested, 0x34, DQ "4" DQ);
   558  	test_quoting_of(is_tested, 0x35, DQ "5" DQ);
   559  	test_quoting_of(is_tested, 0x36, DQ "6" DQ);
   560  	test_quoting_of(is_tested, 0x37, DQ "7" DQ);
   561  	test_quoting_of(is_tested, 0x38, DQ "8" DQ);
   562  	test_quoting_of(is_tested, 0x39, DQ "9" DQ);
   563  	test_quoting_of(is_tested, 0x3a, DQ ":" DQ);
   564  	test_quoting_of(is_tested, 0x3b, DQ ";" DQ);
   565  	test_quoting_of(is_tested, 0x3c, DQ "<" DQ);
   566  	test_quoting_of(is_tested, 0x3d, DQ "=" DQ);
   567  	test_quoting_of(is_tested, 0x3e, DQ ">" DQ);
   568  	test_quoting_of(is_tested, 0x3f, DQ "?" DQ);
   569  	// block 5: 0x40 - 0x4f
   570  	test_quoting_of(is_tested, 0x40, DQ "@" DQ);
   571  	test_quoting_of(is_tested, 0x41, DQ "A" DQ);
   572  	test_quoting_of(is_tested, 0x42, DQ "B" DQ);
   573  	test_quoting_of(is_tested, 0x43, DQ "C" DQ);
   574  	test_quoting_of(is_tested, 0x44, DQ "D" DQ);
   575  	test_quoting_of(is_tested, 0x45, DQ "E" DQ);
   576  	test_quoting_of(is_tested, 0x46, DQ "F" DQ);
   577  	test_quoting_of(is_tested, 0x47, DQ "G" DQ);
   578  	test_quoting_of(is_tested, 0x48, DQ "H" DQ);
   579  	test_quoting_of(is_tested, 0x49, DQ "I" DQ);
   580  	test_quoting_of(is_tested, 0x4a, DQ "J" DQ);
   581  	test_quoting_of(is_tested, 0x4b, DQ "K" DQ);
   582  	test_quoting_of(is_tested, 0x4c, DQ "L" DQ);
   583  	test_quoting_of(is_tested, 0x4d, DQ "M" DQ);
   584  	test_quoting_of(is_tested, 0x4e, DQ "N" DQ);
   585  	test_quoting_of(is_tested, 0x4f, DQ "O" DQ);
   586  	// block 6: 0x50 - 0x5f
   587  	test_quoting_of(is_tested, 0x50, DQ "P" DQ);
   588  	test_quoting_of(is_tested, 0x51, DQ "Q" DQ);
   589  	test_quoting_of(is_tested, 0x52, DQ "R" DQ);
   590  	test_quoting_of(is_tested, 0x53, DQ "S" DQ);
   591  	test_quoting_of(is_tested, 0x54, DQ "T" DQ);
   592  	test_quoting_of(is_tested, 0x55, DQ "U" DQ);
   593  	test_quoting_of(is_tested, 0x56, DQ "V" DQ);
   594  	test_quoting_of(is_tested, 0x57, DQ "W" DQ);
   595  	test_quoting_of(is_tested, 0x58, DQ "X" DQ);
   596  	test_quoting_of(is_tested, 0x59, DQ "Y" DQ);
   597  	test_quoting_of(is_tested, 0x5a, DQ "Z" DQ);
   598  	test_quoting_of(is_tested, 0x5b, DQ "[" DQ);
   599  	test_quoting_of(is_tested, 0x5c, DQ "\\\\" DQ);
   600  	test_quoting_of(is_tested, 0x5d, DQ "]" DQ);
   601  	test_quoting_of(is_tested, 0x5e, DQ "^" DQ);
   602  	test_quoting_of(is_tested, 0x5f, DQ "_" DQ);
   603  	// block 7: 0x60 - 0x6f
   604  	test_quoting_of(is_tested, 0x60, DQ "`" DQ);
   605  	test_quoting_of(is_tested, 0x61, DQ "a" DQ);
   606  	test_quoting_of(is_tested, 0x62, DQ "b" DQ);
   607  	test_quoting_of(is_tested, 0x63, DQ "c" DQ);
   608  	test_quoting_of(is_tested, 0x64, DQ "d" DQ);
   609  	test_quoting_of(is_tested, 0x65, DQ "e" DQ);
   610  	test_quoting_of(is_tested, 0x66, DQ "f" DQ);
   611  	test_quoting_of(is_tested, 0x67, DQ "g" DQ);
   612  	test_quoting_of(is_tested, 0x68, DQ "h" DQ);
   613  	test_quoting_of(is_tested, 0x69, DQ "i" DQ);
   614  	test_quoting_of(is_tested, 0x6a, DQ "j" DQ);
   615  	test_quoting_of(is_tested, 0x6b, DQ "k" DQ);
   616  	test_quoting_of(is_tested, 0x6c, DQ "l" DQ);
   617  	test_quoting_of(is_tested, 0x6d, DQ "m" DQ);
   618  	test_quoting_of(is_tested, 0x6e, DQ "n" DQ);
   619  	test_quoting_of(is_tested, 0x6f, DQ "o" DQ);
   620  	// block 8: 0x70 - 0x7f
   621  	test_quoting_of(is_tested, 0x70, DQ "p" DQ);
   622  	test_quoting_of(is_tested, 0x71, DQ "q" DQ);
   623  	test_quoting_of(is_tested, 0x72, DQ "r" DQ);
   624  	test_quoting_of(is_tested, 0x73, DQ "s" DQ);
   625  	test_quoting_of(is_tested, 0x74, DQ "t" DQ);
   626  	test_quoting_of(is_tested, 0x75, DQ "u" DQ);
   627  	test_quoting_of(is_tested, 0x76, DQ "v" DQ);
   628  	test_quoting_of(is_tested, 0x77, DQ "w" DQ);
   629  	test_quoting_of(is_tested, 0x78, DQ "x" DQ);
   630  	test_quoting_of(is_tested, 0x79, DQ "y" DQ);
   631  	test_quoting_of(is_tested, 0x7a, DQ "z" DQ);
   632  	test_quoting_of(is_tested, 0x7b, DQ "{" DQ);
   633  	test_quoting_of(is_tested, 0x7c, DQ "|" DQ);
   634  	test_quoting_of(is_tested, 0x7d, DQ "}" DQ);
   635  	test_quoting_of(is_tested, 0x7e, DQ "~" DQ);
   636  	test_quoting_of(is_tested, 0x7f, DQ "\\x7f" DQ);
   637  	// block 9 (8-bit): 0x80 - 0x8f
   638  	test_quoting_of(is_tested, 0x80, DQ "\\x80" DQ);
   639  	test_quoting_of(is_tested, 0x81, DQ "\\x81" DQ);
   640  	test_quoting_of(is_tested, 0x82, DQ "\\x82" DQ);
   641  	test_quoting_of(is_tested, 0x83, DQ "\\x83" DQ);
   642  	test_quoting_of(is_tested, 0x84, DQ "\\x84" DQ);
   643  	test_quoting_of(is_tested, 0x85, DQ "\\x85" DQ);
   644  	test_quoting_of(is_tested, 0x86, DQ "\\x86" DQ);
   645  	test_quoting_of(is_tested, 0x87, DQ "\\x87" DQ);
   646  	test_quoting_of(is_tested, 0x88, DQ "\\x88" DQ);
   647  	test_quoting_of(is_tested, 0x89, DQ "\\x89" DQ);
   648  	test_quoting_of(is_tested, 0x8a, DQ "\\x8a" DQ);
   649  	test_quoting_of(is_tested, 0x8b, DQ "\\x8b" DQ);
   650  	test_quoting_of(is_tested, 0x8c, DQ "\\x8c" DQ);
   651  	test_quoting_of(is_tested, 0x8d, DQ "\\x8d" DQ);
   652  	test_quoting_of(is_tested, 0x8e, DQ "\\x8e" DQ);
   653  	test_quoting_of(is_tested, 0x8f, DQ "\\x8f" DQ);
   654  	// block 10 (8-bit): 0x90 - 0x9f
   655  	test_quoting_of(is_tested, 0x90, DQ "\\x90" DQ);
   656  	test_quoting_of(is_tested, 0x91, DQ "\\x91" DQ);
   657  	test_quoting_of(is_tested, 0x92, DQ "\\x92" DQ);
   658  	test_quoting_of(is_tested, 0x93, DQ "\\x93" DQ);
   659  	test_quoting_of(is_tested, 0x94, DQ "\\x94" DQ);
   660  	test_quoting_of(is_tested, 0x95, DQ "\\x95" DQ);
   661  	test_quoting_of(is_tested, 0x96, DQ "\\x96" DQ);
   662  	test_quoting_of(is_tested, 0x97, DQ "\\x97" DQ);
   663  	test_quoting_of(is_tested, 0x98, DQ "\\x98" DQ);
   664  	test_quoting_of(is_tested, 0x99, DQ "\\x99" DQ);
   665  	test_quoting_of(is_tested, 0x9a, DQ "\\x9a" DQ);
   666  	test_quoting_of(is_tested, 0x9b, DQ "\\x9b" DQ);
   667  	test_quoting_of(is_tested, 0x9c, DQ "\\x9c" DQ);
   668  	test_quoting_of(is_tested, 0x9d, DQ "\\x9d" DQ);
   669  	test_quoting_of(is_tested, 0x9e, DQ "\\x9e" DQ);
   670  	test_quoting_of(is_tested, 0x9f, DQ "\\x9f" DQ);
   671  	// block 11 (8-bit): 0xa0 - 0xaf
   672  	test_quoting_of(is_tested, 0xa0, DQ "\\xa0" DQ);
   673  	test_quoting_of(is_tested, 0xa1, DQ "\\xa1" DQ);
   674  	test_quoting_of(is_tested, 0xa2, DQ "\\xa2" DQ);
   675  	test_quoting_of(is_tested, 0xa3, DQ "\\xa3" DQ);
   676  	test_quoting_of(is_tested, 0xa4, DQ "\\xa4" DQ);
   677  	test_quoting_of(is_tested, 0xa5, DQ "\\xa5" DQ);
   678  	test_quoting_of(is_tested, 0xa6, DQ "\\xa6" DQ);
   679  	test_quoting_of(is_tested, 0xa7, DQ "\\xa7" DQ);
   680  	test_quoting_of(is_tested, 0xa8, DQ "\\xa8" DQ);
   681  	test_quoting_of(is_tested, 0xa9, DQ "\\xa9" DQ);
   682  	test_quoting_of(is_tested, 0xaa, DQ "\\xaa" DQ);
   683  	test_quoting_of(is_tested, 0xab, DQ "\\xab" DQ);
   684  	test_quoting_of(is_tested, 0xac, DQ "\\xac" DQ);
   685  	test_quoting_of(is_tested, 0xad, DQ "\\xad" DQ);
   686  	test_quoting_of(is_tested, 0xae, DQ "\\xae" DQ);
   687  	test_quoting_of(is_tested, 0xaf, DQ "\\xaf" DQ);
   688  	// block 12 (8-bit): 0xb0 - 0xbf
   689  	test_quoting_of(is_tested, 0xb0, DQ "\\xb0" DQ);
   690  	test_quoting_of(is_tested, 0xb1, DQ "\\xb1" DQ);
   691  	test_quoting_of(is_tested, 0xb2, DQ "\\xb2" DQ);
   692  	test_quoting_of(is_tested, 0xb3, DQ "\\xb3" DQ);
   693  	test_quoting_of(is_tested, 0xb4, DQ "\\xb4" DQ);
   694  	test_quoting_of(is_tested, 0xb5, DQ "\\xb5" DQ);
   695  	test_quoting_of(is_tested, 0xb6, DQ "\\xb6" DQ);
   696  	test_quoting_of(is_tested, 0xb7, DQ "\\xb7" DQ);
   697  	test_quoting_of(is_tested, 0xb8, DQ "\\xb8" DQ);
   698  	test_quoting_of(is_tested, 0xb9, DQ "\\xb9" DQ);
   699  	test_quoting_of(is_tested, 0xba, DQ "\\xba" DQ);
   700  	test_quoting_of(is_tested, 0xbb, DQ "\\xbb" DQ);
   701  	test_quoting_of(is_tested, 0xbc, DQ "\\xbc" DQ);
   702  	test_quoting_of(is_tested, 0xbd, DQ "\\xbd" DQ);
   703  	test_quoting_of(is_tested, 0xbe, DQ "\\xbe" DQ);
   704  	test_quoting_of(is_tested, 0xbf, DQ "\\xbf" DQ);
   705  	// block 13 (8-bit): 0xc0 - 0xcf
   706  	test_quoting_of(is_tested, 0xc0, DQ "\\xc0" DQ);
   707  	test_quoting_of(is_tested, 0xc1, DQ "\\xc1" DQ);
   708  	test_quoting_of(is_tested, 0xc2, DQ "\\xc2" DQ);
   709  	test_quoting_of(is_tested, 0xc3, DQ "\\xc3" DQ);
   710  	test_quoting_of(is_tested, 0xc4, DQ "\\xc4" DQ);
   711  	test_quoting_of(is_tested, 0xc5, DQ "\\xc5" DQ);
   712  	test_quoting_of(is_tested, 0xc6, DQ "\\xc6" DQ);
   713  	test_quoting_of(is_tested, 0xc7, DQ "\\xc7" DQ);
   714  	test_quoting_of(is_tested, 0xc8, DQ "\\xc8" DQ);
   715  	test_quoting_of(is_tested, 0xc9, DQ "\\xc9" DQ);
   716  	test_quoting_of(is_tested, 0xca, DQ "\\xca" DQ);
   717  	test_quoting_of(is_tested, 0xcb, DQ "\\xcb" DQ);
   718  	test_quoting_of(is_tested, 0xcc, DQ "\\xcc" DQ);
   719  	test_quoting_of(is_tested, 0xcd, DQ "\\xcd" DQ);
   720  	test_quoting_of(is_tested, 0xce, DQ "\\xce" DQ);
   721  	test_quoting_of(is_tested, 0xcf, DQ "\\xcf" DQ);
   722  	// block 14 (8-bit): 0xd0 - 0xdf
   723  	test_quoting_of(is_tested, 0xd0, DQ "\\xd0" DQ);
   724  	test_quoting_of(is_tested, 0xd1, DQ "\\xd1" DQ);
   725  	test_quoting_of(is_tested, 0xd2, DQ "\\xd2" DQ);
   726  	test_quoting_of(is_tested, 0xd3, DQ "\\xd3" DQ);
   727  	test_quoting_of(is_tested, 0xd4, DQ "\\xd4" DQ);
   728  	test_quoting_of(is_tested, 0xd5, DQ "\\xd5" DQ);
   729  	test_quoting_of(is_tested, 0xd6, DQ "\\xd6" DQ);
   730  	test_quoting_of(is_tested, 0xd7, DQ "\\xd7" DQ);
   731  	test_quoting_of(is_tested, 0xd8, DQ "\\xd8" DQ);
   732  	test_quoting_of(is_tested, 0xd9, DQ "\\xd9" DQ);
   733  	test_quoting_of(is_tested, 0xda, DQ "\\xda" DQ);
   734  	test_quoting_of(is_tested, 0xdb, DQ "\\xdb" DQ);
   735  	test_quoting_of(is_tested, 0xdc, DQ "\\xdc" DQ);
   736  	test_quoting_of(is_tested, 0xdd, DQ "\\xdd" DQ);
   737  	test_quoting_of(is_tested, 0xde, DQ "\\xde" DQ);
   738  	test_quoting_of(is_tested, 0xdf, DQ "\\xdf" DQ);
   739  	// block 15 (8-bit): 0xe0 - 0xef
   740  	test_quoting_of(is_tested, 0xe0, DQ "\\xe0" DQ);
   741  	test_quoting_of(is_tested, 0xe1, DQ "\\xe1" DQ);
   742  	test_quoting_of(is_tested, 0xe2, DQ "\\xe2" DQ);
   743  	test_quoting_of(is_tested, 0xe3, DQ "\\xe3" DQ);
   744  	test_quoting_of(is_tested, 0xe4, DQ "\\xe4" DQ);
   745  	test_quoting_of(is_tested, 0xe5, DQ "\\xe5" DQ);
   746  	test_quoting_of(is_tested, 0xe6, DQ "\\xe6" DQ);
   747  	test_quoting_of(is_tested, 0xe7, DQ "\\xe7" DQ);
   748  	test_quoting_of(is_tested, 0xe8, DQ "\\xe8" DQ);
   749  	test_quoting_of(is_tested, 0xe9, DQ "\\xe9" DQ);
   750  	test_quoting_of(is_tested, 0xea, DQ "\\xea" DQ);
   751  	test_quoting_of(is_tested, 0xeb, DQ "\\xeb" DQ);
   752  	test_quoting_of(is_tested, 0xec, DQ "\\xec" DQ);
   753  	test_quoting_of(is_tested, 0xed, DQ "\\xed" DQ);
   754  	test_quoting_of(is_tested, 0xee, DQ "\\xee" DQ);
   755  	test_quoting_of(is_tested, 0xef, DQ "\\xef" DQ);
   756  	// block 16 (8-bit): 0xf0 - 0xff
   757  	test_quoting_of(is_tested, 0xf0, DQ "\\xf0" DQ);
   758  	test_quoting_of(is_tested, 0xf1, DQ "\\xf1" DQ);
   759  	test_quoting_of(is_tested, 0xf2, DQ "\\xf2" DQ);
   760  	test_quoting_of(is_tested, 0xf3, DQ "\\xf3" DQ);
   761  	test_quoting_of(is_tested, 0xf4, DQ "\\xf4" DQ);
   762  	test_quoting_of(is_tested, 0xf5, DQ "\\xf5" DQ);
   763  	test_quoting_of(is_tested, 0xf6, DQ "\\xf6" DQ);
   764  	test_quoting_of(is_tested, 0xf7, DQ "\\xf7" DQ);
   765  	test_quoting_of(is_tested, 0xf8, DQ "\\xf8" DQ);
   766  	test_quoting_of(is_tested, 0xf9, DQ "\\xf9" DQ);
   767  	test_quoting_of(is_tested, 0xfa, DQ "\\xfa" DQ);
   768  	test_quoting_of(is_tested, 0xfb, DQ "\\xfb" DQ);
   769  	test_quoting_of(is_tested, 0xfc, DQ "\\xfc" DQ);
   770  	test_quoting_of(is_tested, 0xfd, DQ "\\xfd" DQ);
   771  	test_quoting_of(is_tested, 0xfe, DQ "\\xfe" DQ);
   772  	test_quoting_of(is_tested, 0xff, DQ "\\xff" DQ);
   773  
   774  	// Ensure the search was exhaustive.
   775  	for (int i = 0; i <= 0xff; ++i) {
   776  		g_assert_true(is_tested[i]);
   777  	}
   778  
   779  	// Few extra tests (repeated) for specific things.
   780  
   781  	// Smoke test
   782  	sc_string_quote(buf, sizeof buf, "hello 123");
   783  	g_assert_cmpstr(buf, ==, DQ "hello 123" DQ);
   784  
   785  	// Whitespace
   786  	sc_string_quote(buf, sizeof buf, "\n");
   787  	g_assert_cmpstr(buf, ==, DQ "\\n" DQ);
   788  	sc_string_quote(buf, sizeof buf, "\r");
   789  	g_assert_cmpstr(buf, ==, DQ "\\r" DQ);
   790  	sc_string_quote(buf, sizeof buf, "\t");
   791  	g_assert_cmpstr(buf, ==, DQ "\\t" DQ);
   792  	sc_string_quote(buf, sizeof buf, "\v");
   793  	g_assert_cmpstr(buf, ==, DQ "\\v" DQ);
   794  
   795  	// Escape character itself
   796  	sc_string_quote(buf, sizeof buf, "\\");
   797  	g_assert_cmpstr(buf, ==, DQ "\\\\" DQ);
   798  
   799  	// Double quote character
   800  	sc_string_quote(buf, sizeof buf, "\"");
   801  	g_assert_cmpstr(buf, ==, DQ "\\\"" DQ);
   802  
   803  #undef DQ
   804  }
   805  
   806  static void test_sc_strdup(void)
   807  {
   808  	char *s = sc_strdup("snap install everything");
   809  	g_assert_nonnull(s);
   810  	g_assert_cmpstr(s, ==, "snap install everything");
   811  	free(s);
   812  }
   813  
   814  static void __attribute__((constructor)) init(void)
   815  {
   816  	g_test_add_func("/string-utils/sc_streq", test_sc_streq);
   817  	g_test_add_func("/string-utils/sc_endswith", test_sc_endswith);
   818  	g_test_add_func("/string-utils/sc_startswith", test_sc_startswith);
   819  	g_test_add_func("/string-utils/sc_must_snprintf",
   820  			test_sc_must_snprintf);
   821  	g_test_add_func("/string-utils/sc_must_snprintf/fail",
   822  			test_sc_must_snprintf__fail);
   823  	g_test_add_func("/string-utils/sc_string_append/normal",
   824  			test_sc_string_append);
   825  	g_test_add_func("/string-utils/sc_string_append/empty_to_full",
   826  			test_sc_string_append__empty_to_full);
   827  	g_test_add_func("/string-utils/sc_string_append/overflow",
   828  			test_sc_string_append__overflow);
   829  	g_test_add_func("/string-utils/sc_string_append/uninitialized_buf",
   830  			test_sc_string_append__uninitialized_buf);
   831  	g_test_add_func("/string-utils/sc_string_append/NULL_buf",
   832  			test_sc_string_append__NULL_buf);
   833  	g_test_add_func("/string-utils/sc_string_append/NULL_str",
   834  			test_sc_string_append__NULL_str);
   835  	g_test_add_func("/string-utils/sc_string_init/normal",
   836  			test_sc_string_init__normal);
   837  	g_test_add_func("/string-utils/sc_string_init/empty_buf",
   838  			test_sc_string_init__empty_buf);
   839  	g_test_add_func("/string-utils/sc_string_init/NULL_buf",
   840  			test_sc_string_init__NULL_buf);
   841  	g_test_add_func
   842  	    ("/string-utils/sc_string_append_char__uninitialized_buf",
   843  	     test_sc_string_append_char__uninitialized_buf);
   844  	g_test_add_func("/string-utils/sc_string_append_char__NULL_buf",
   845  			test_sc_string_append_char__NULL_buf);
   846  	g_test_add_func("/string-utils/sc_string_append_char__overflow",
   847  			test_sc_string_append_char__overflow);
   848  	g_test_add_func("/string-utils/sc_string_append_char__invalid_zero",
   849  			test_sc_string_append_char__invalid_zero);
   850  	g_test_add_func("/string-utils/sc_string_append_char__normal",
   851  			test_sc_string_append_char__normal);
   852  	g_test_add_func
   853  	    ("/string-utils/sc_string_append_char_pair__NULL_buf",
   854  	     test_sc_string_append_char_pair__NULL_buf);
   855  	g_test_add_func("/string-utils/sc_string_append_char_pair__overflow",
   856  			test_sc_string_append_char_pair__overflow);
   857  	g_test_add_func
   858  	    ("/string-utils/sc_string_append_char_pair__invalid_zero_c1",
   859  	     test_sc_string_append_char_pair__invalid_zero_c1);
   860  	g_test_add_func
   861  	    ("/string-utils/sc_string_append_char_pair__invalid_zero_c2",
   862  	     test_sc_string_append_char_pair__invalid_zero_c2);
   863  	g_test_add_func("/string-utils/sc_string_append_char_pair__normal",
   864  			test_sc_string_append_char_pair__normal);
   865  	g_test_add_func("/string-utils/sc_string_quote__NULL_buf",
   866  			test_sc_string_quote_NULL_str);
   867  	g_test_add_func
   868  	    ("/string-utils/sc_string_append_char_pair__uninitialized_buf",
   869  	     test_sc_string_append_char_pair__uninitialized_buf);
   870  	g_test_add_func("/string-utils/sc_string_quote", test_sc_string_quote);
   871  	g_test_add_func("/string-utils/sc_strdup", test_sc_strdup);
   872  }