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