Bump to 1.14.1
[platform/upstream/augeas.git] / tests / test-quotearg-simple.c
1 /* Test of quotearg family of functions.
2    Copyright (C) 2008-2016 Free Software Foundation, Inc.
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 as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Eric Blake <ebb9@byu.net>, 2008.  */
18
19 #include <config.h>
20
21 #include "quotearg.h"
22
23 #include <ctype.h>
24 #include <stdbool.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "localcharset.h"
30 #include "macros.h"
31 #include "zerosize-ptr.h"
32
33 #include "test-quotearg.h"
34
35 static struct result_groups results_g[] = {
36   /* literal_quoting_style */
37   { { "", "\0""1\0", 3, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b",
38       "a' b", LQ RQ, LQ RQ },
39     { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b",
40       "a' b", LQ RQ, LQ RQ },
41     { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b",
42       "a' b", LQ RQ, LQ RQ } },
43
44   /* shell_quoting_style */
45   { { "''", "\0""1\0", 3, "simple", "' \t\n'\\''\"\033?""?/\\'", "a:b",
46       "'a\\b'", "\"a' b\"", LQ RQ, LQ RQ },
47     { "''", "1", 1, "simple", "' \t\n'\\''\"\033?""?/\\'", "a:b",
48       "'a\\b'", "\"a' b\"", LQ RQ, LQ RQ },
49     { "''", "1", 1, "simple", "' \t\n'\\''\"\033?""?/\\'", "'a:b'",
50       "'a\\b'", "\"a' b\"", LQ RQ, LQ RQ } },
51
52   /* shell_always_quoting_style */
53   { { "''", "'\0""1\0'", 5, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'",
54       "'a\\b'", "\"a' b\"", "'" LQ RQ "'", "'" LQ RQ "'" },
55     { "''", "'1'", 3, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'",
56       "'a\\b'", "\"a' b\"", "'" LQ RQ "'", "'" LQ RQ "'" },
57     { "''", "'1'", 3, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'",
58       "'a\\b'", "\"a' b\"", "'" LQ RQ "'", "'" LQ RQ "'" } },
59
60   /* shell_escape_quoting_style */
61   { { "''", "''$'\\0''1'$'\\0'", 15, "simple",
62       "' '$'\\t\\n'\\''\"'$'\\033''?""?/\\'", "a:b",
63       "'a\\b'", "\"a' b\"", "''$'" LQ_ENC RQ_ENC "'", LQ RQ },
64     { "''", "''$'\\0''1'$'\\0'", 15, "simple",
65       "' '$'\\t\\n'\\''\"'$'\\033''?""?/\\'", "a:b",
66       "'a\\b'", "\"a' b\"", "''$'" LQ_ENC RQ_ENC "'", LQ RQ },
67     { "''", "''$'\\0''1'$'\\0'", 15, "simple",
68       "' '$'\\t\\n'\\''\"'$'\\033''?""?/\\'", "'a:b'",
69       "'a\\b'", "\"a' b\"", "''$'" LQ_ENC RQ_ENC "'", LQ RQ } },
70
71   /* shell_escape_always_quoting_style */
72   { { "''", "''$'\\0''1'$'\\0'", 15, "'simple'",
73       "' '$'\\t\\n'\\''\"'$'\\033''?""?/\\'", "'a:b'",
74       "'a\\b'", "\"a' b\"", "''$'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" },
75     { "''", "''$'\\0''1'$'\\0'", 15, "'simple'",
76       "' '$'\\t\\n'\\''\"'$'\\033''?""?/\\'", "'a:b'",
77       "'a\\b'", "\"a' b\"", "''$'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" },
78     { "''", "''$'\\0''1'$'\\0'", 15, "'simple'",
79       "' '$'\\t\\n'\\''\"'$'\\033''?""?/\\'", "'a:b'",
80       "'a\\b'", "\"a' b\"", "''$'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" } },
81
82   /* c_quoting_style */
83   { { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
84       "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
85       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" },
86     { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
87       "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
88       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" },
89     { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
90       "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"",
91       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" } },
92
93   /* c_maybe_quoting_style */
94   { { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
95       "a:b", "a\\b", "a' b", "\"" LQ_ENC RQ_ENC "\"", LQ RQ },
96     { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
97       "a:b", "a\\b", "a' b", "\"" LQ_ENC RQ_ENC "\"", LQ RQ },
98     { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
99       "\"a:b\"", "a\\b", "a' b", "\"" LQ_ENC RQ_ENC "\"", LQ RQ } },
100
101   /* escape_quoting_style */
102   { { "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a:b",
103       "a\\\\b", "a' b", LQ_ENC RQ_ENC, LQ RQ },
104     { "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a:b",
105       "a\\\\b", "a' b", LQ_ENC RQ_ENC, LQ RQ },
106     { "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a\\:b",
107       "a\\\\b", "a' b", LQ_ENC RQ_ENC, LQ RQ } },
108
109   /* locale_quoting_style */
110   { { "''", "'\\0001\\0'", 9, "'simple'", "' \\t\\n\\'\"\\033?""?/\\\\'",
111       "'a:b'", "'a\\\\b'", "'a\\' b'", "'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" },
112     { "''", "'\\0001\\0'", 9, "'simple'", "' \\t\\n\\'\"\\033?""?/\\\\'",
113       "'a:b'", "'a\\\\b'", "'a\\' b'", "'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" },
114     { "''", "'\\0001\\0'", 9, "'simple'", "' \\t\\n\\'\"\\033?""?/\\\\'",
115       "'a\\:b'", "'a\\\\b'", "'a\\' b'",
116       "'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" } },
117
118   /* clocale_quoting_style */
119   { { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
120       "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
121       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" },
122     { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
123       "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
124       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" },
125     { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
126       "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"",
127       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" } }
128 };
129
130 static struct result_groups flag_results[] = {
131   /* literal_quoting_style and QA_ELIDE_NULL_BYTES */
132   { { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b", "a' b",
133       LQ RQ, LQ RQ },
134     { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b", "a' b",
135       LQ RQ, LQ RQ },
136     { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b", "a' b",
137       LQ RQ, LQ RQ } },
138
139   /* c_quoting_style and QA_ELIDE_OUTER_QUOTES */
140   { { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
141       "a:b", "a\\b", "a' b", "\"" LQ_ENC RQ_ENC "\"", LQ RQ },
142     { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
143       "a:b", "a\\b", "a' b", "\"" LQ_ENC RQ_ENC "\"", LQ RQ },
144     { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
145       "\"a:b\"", "a\\b", "a' b", "\"" LQ_ENC RQ_ENC "\"", LQ RQ } },
146
147   /* c_quoting_style and QA_SPLIT_TRIGRAPHS */
148   { { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
149       "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
150       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" },
151     { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
152       "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
153       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" },
154     { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
155       "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"",
156       "\"a' b\"", "\"" LQ_ENC RQ_ENC "\"", "\"" LQ RQ "\"" } }
157 };
158
159 static char const *custom_quotes[][2] = {
160   { "", ""  },
161   { "'", "'"  },
162   { "(", ")"  },
163   { ":", " "  },
164   { " ", ":"  },
165   { "# ", "\n" },
166   { "\"'", "'\"" }
167 };
168
169 static struct result_groups custom_results[] = {
170   /* left_quote = right_quote = "" */
171   { { "", "\\0001\\0", 7, "simple",
172       " \\t\\n'\"\\033?""?/\\\\", "a:b", "a\\\\b",
173       "a' b", LQ_ENC RQ_ENC, LQ RQ },
174     { "", "\\0001\\0", 7, "simple",
175       " \\t\\n'\"\\033?""?/\\\\", "a:b", "a\\\\b",
176       "a' b", LQ_ENC RQ_ENC, LQ RQ },
177     { "", "\\0001\\0", 7, "simple",
178       " \\t\\n'\"\\033?""?/\\\\", "a\\:b", "a\\\\b",
179       "a' b", LQ_ENC RQ_ENC, LQ RQ } },
180
181   /* left_quote = right_quote = "'" */
182   { { "''", "'\\0001\\0'", 9, "'simple'",
183       "' \\t\\n\\'\"\\033?""?/\\\\'", "'a:b'", "'a\\\\b'",
184       "'a\\' b'", "'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" },
185     { "''", "'\\0001\\0'", 9, "'simple'",
186       "' \\t\\n\\'\"\\033?""?/\\\\'", "'a:b'", "'a\\\\b'",
187       "'a\\' b'", "'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" },
188     { "''", "'\\0001\\0'", 9, "'simple'",
189       "' \\t\\n\\'\"\\033?""?/\\\\'", "'a\\:b'", "'a\\\\b'",
190       "'a\\' b'", "'" LQ_ENC RQ_ENC "'", "'" LQ RQ "'" } },
191
192   /* left_quote = "(" and right_quote = ")" */
193   { { "()", "(\\0001\\0)", 9, "(simple)",
194       "( \\t\\n'\"\\033?""?/\\\\)", "(a:b)", "(a\\\\b)",
195       "(a' b)", "(" LQ_ENC RQ_ENC ")", "(" LQ RQ ")" },
196     { "()", "(\\0001\\0)", 9, "(simple)",
197       "( \\t\\n'\"\\033?""?/\\\\)", "(a:b)", "(a\\\\b)",
198       "(a' b)", "(" LQ_ENC RQ_ENC ")", "(" LQ RQ ")" },
199     { "()", "(\\0001\\0)", 9, "(simple)",
200       "( \\t\\n'\"\\033?""?/\\\\)", "(a\\:b)", "(a\\\\b)",
201       "(a' b)", "(" LQ_ENC RQ_ENC ")", "(" LQ RQ ")" } },
202
203   /* left_quote = ":" and right_quote = " " */
204   { { ": ", ":\\0001\\0 ", 9, ":simple ",
205       ":\\ \\t\\n'\"\\033?""?/\\\\ ", ":a:b ", ":a\\\\b ",
206       ":a'\\ b ", ":" LQ_ENC RQ_ENC " ", ":" LQ RQ " " },
207     { ": ", ":\\0001\\0 ", 9, ":simple ",
208       ":\\ \\t\\n'\"\\033?""?/\\\\ ", ":a:b ", ":a\\\\b ",
209       ":a'\\ b ", ":" LQ_ENC RQ_ENC " ", ":" LQ RQ " " },
210     { ": ", ":\\0001\\0 ", 9, ":simple ",
211       ":\\ \\t\\n'\"\\033?""?/\\\\ ", ":a\\:b ", ":a\\\\b ",
212       ":a'\\ b ", ":" LQ_ENC RQ_ENC " ", ":" LQ RQ " " } },
213
214   /* left_quote = " " and right_quote = ":" */
215   { { " :", " \\0001\\0:", 9, " simple:",
216       "  \\t\\n'\"\\033?""?/\\\\:", " a\\:b:", " a\\\\b:",
217       " a' b:", " " LQ_ENC RQ_ENC ":", " " LQ RQ ":" },
218     { " :", " \\0001\\0:", 9, " simple:",
219       "  \\t\\n'\"\\033?""?/\\\\:", " a\\:b:", " a\\\\b:",
220       " a' b:", " " LQ_ENC RQ_ENC ":", " " LQ RQ ":" },
221     { " :", " \\0001\\0:", 9, " simple:",
222       "  \\t\\n'\"\\033?""?/\\\\:", " a\\:b:", " a\\\\b:",
223       " a' b:", " " LQ_ENC RQ_ENC ":", " " LQ RQ ":" } },
224
225   /* left_quote = "# " and right_quote = "\n" */
226   { { "# \n", "# \\0001\\0\n", 10, "# simple\n",
227       "#  \\t\\n'\"\\033?""?/\\\\\n", "# a:b\n", "# a\\\\b\n",
228       "# a' b\n", "# " LQ_ENC RQ_ENC "\n", "# " LQ RQ "\n" },
229     { "# \n", "# \\0001\\0\n", 10, "# simple\n",
230       "#  \\t\\n'\"\\033?""?/\\\\\n", "# a:b\n", "# a\\\\b\n",
231       "# a' b\n", "# " LQ_ENC RQ_ENC "\n", "# " LQ RQ "\n" },
232     { "# \n", "# \\0001\\0\n", 10, "# simple\n",
233       "#  \\t\\n'\"\\033?""?/\\\\\n", "# a\\:b\n", "# a\\\\b\n",
234       "# a' b\n", "# " LQ_ENC RQ_ENC "\n", "# " LQ RQ "\n" } },
235
236   /* left_quote = "\"'" and right_quote = "'\"" */
237   { { "\"''\"", "\"'\\0001\\0'\"", 11, "\"'simple'\"",
238       "\"' \\t\\n\\'\"\\033?""?/\\\\'\"", "\"'a:b'\"", "\"'a\\\\b'\"",
239       "\"'a' b'\"", "\"'" LQ_ENC RQ_ENC "'\"", "\"'" LQ RQ "'\"" },
240     { "\"''\"", "\"'\\0001\\0'\"", 11, "\"'simple'\"",
241       "\"' \\t\\n\\'\"\\033?""?/\\\\'\"", "\"'a:b'\"", "\"'a\\\\b'\"",
242       "\"'a' b'\"", "\"'" LQ_ENC RQ_ENC "'\"", "\"'" LQ RQ "'\"" },
243     { "\"''\"", "\"'\\0001\\0'\"", 11, "\"'simple'\"",
244       "\"' \\t\\n\\'\"\\033?""?/\\\\'\"", "\"'a\\:b'\"", "\"'a\\\\b'\"",
245       "\"'a' b'\"", "\"'" LQ_ENC RQ_ENC "'\"", "\"'" LQ RQ "'\"" } }
246 };
247
248 int
249 main (int argc _GL_UNUSED, char *argv[])
250 {
251   int i;
252   bool ascii_only = MB_CUR_MAX == 1 && !isprint ((unsigned char) LQ[0]);
253
254   /* This part of the program is hard-wired to the C locale since it
255      does not call setlocale.  However, according to POSIX, the use of
256      8-bit bytes in a character context in the C locale gives
257      unspecified results (that is, the C locale charset is allowed to
258      be unibyte with 8-bit bytes rejected [ASCII], unibyte with 8-bit
259      bytes being characters [often ISO-8859-1], or multibyte [often
260      UTF-8]).  We assume that the latter two cases will be
261      indistinguishable in this test - that is, the LQ and RQ sequences
262      will pass through unchanged in either type of charset.  So when
263      testing for quoting of str7, use the ascii_only flag to decide
264      what to expect for the 8-bit data being quoted.  */
265   ASSERT (!isprint ('\033'));
266   for (i = literal_quoting_style; i <= clocale_quoting_style; i++)
267     {
268       set_quoting_style (NULL, (enum quoting_style) i);
269       if (!(i == locale_quoting_style || i == clocale_quoting_style)
270           || (strcmp (locale_charset (), "ASCII") == 0
271               || strcmp (locale_charset (), "ANSI_X3.4-1968") == 0))
272         {
273           compare_strings (use_quotearg_buffer, &results_g[i].group1,
274                            ascii_only);
275           compare_strings (use_quotearg, &results_g[i].group2,
276                            ascii_only);
277           if (i == c_quoting_style)
278             compare_strings (use_quote_double_quotes, &results_g[i].group2,
279                              ascii_only);
280           compare_strings (use_quotearg_colon, &results_g[i].group3,
281                            ascii_only);
282         }
283     }
284
285   set_quoting_style (NULL, literal_quoting_style);
286   ASSERT (set_quoting_flags (NULL, QA_ELIDE_NULL_BYTES) == 0);
287   compare_strings (use_quotearg_buffer, &flag_results[0].group1, ascii_only);
288   compare_strings (use_quotearg, &flag_results[0].group2, ascii_only);
289   compare_strings (use_quotearg_colon, &flag_results[0].group3, ascii_only);
290
291   set_quoting_style (NULL, c_quoting_style);
292   ASSERT (set_quoting_flags (NULL, QA_ELIDE_OUTER_QUOTES)
293           == QA_ELIDE_NULL_BYTES);
294   compare_strings (use_quotearg_buffer, &flag_results[1].group1, ascii_only);
295   compare_strings (use_quotearg, &flag_results[1].group2, ascii_only);
296   compare_strings (use_quote_double_quotes, &flag_results[1].group2,
297                    ascii_only);
298   compare_strings (use_quotearg_colon, &flag_results[1].group3, ascii_only);
299
300   ASSERT (set_quoting_flags (NULL, QA_SPLIT_TRIGRAPHS)
301           == QA_ELIDE_OUTER_QUOTES);
302   compare_strings (use_quotearg_buffer, &flag_results[2].group1, ascii_only);
303   compare_strings (use_quotearg, &flag_results[2].group2, ascii_only);
304   compare_strings (use_quote_double_quotes, &flag_results[2].group2,
305                    ascii_only);
306   compare_strings (use_quotearg_colon, &flag_results[2].group3, ascii_only);
307
308   ASSERT (set_quoting_flags (NULL, 0) == QA_SPLIT_TRIGRAPHS);
309
310   for (i = 0; i < sizeof custom_quotes / sizeof *custom_quotes; ++i)
311     {
312       set_custom_quoting (NULL,
313                           custom_quotes[i][0], custom_quotes[i][1]);
314       compare_strings (use_quotearg_buffer, &custom_results[i].group1,
315                        ascii_only);
316       compare_strings (use_quotearg, &custom_results[i].group2, ascii_only);
317       compare_strings (use_quotearg_colon, &custom_results[i].group3,
318                        ascii_only);
319     }
320
321   {
322     /* Trigger the bug whereby quotearg_buffer would read beyond the NUL
323        that defines the end of the string being quoted.  Use an input
324        string whose NUL is the last byte before an unreadable page.  */
325     char *z = zerosize_ptr ();
326
327     if (z)
328       {
329         size_t q_len = 1024;
330         char *q = malloc (q_len + 1);
331         char buf[10];
332         memset (q, 'Q', q_len);
333         q[q_len] = 0;
334
335         /* Z points to the boundary between a readable/writable page
336            and one that is neither readable nor writable.  Position
337            our string so its NUL is at the end of the writable one.  */
338         char const *str = "____";
339         size_t s_len = strlen (str);
340         z -= s_len + 1;
341         memcpy (z, str, s_len + 1);
342
343         set_custom_quoting (NULL, q, q);
344         /* Whether this actually triggers a SEGV depends on the
345            implementation of memcmp: whether it compares only byte-at-
346            a-time, and from left to right (no SEGV) or some other way.  */
347         size_t n = quotearg_buffer (buf, sizeof buf, z, SIZE_MAX, NULL);
348         ASSERT (n == s_len + 2 * q_len);
349         ASSERT (memcmp (buf, q, sizeof buf) == 0);
350         free (q);
351       }
352   }
353
354   quotearg_free ();
355
356   return 0;
357 }