1 /* Test of quotearg family of functions.
2 Copyright (C) 2008-2017 Free Software Foundation, Inc.
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)
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.
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/>. */
17 /* Written by Eric Blake <ebb9@byu.net>, 2008. */
29 #include "localcharset.h"
31 #include "zerosize-ptr.h"
33 #include "test-quotearg.h"
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
} },
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
} },
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
"'" } },
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
} },
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
"'" } },
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
"\"" } },
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
} },
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
} },
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
"'" } },
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
"\"" } }
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",
134 { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b", "a' b",
136 { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b", "a' b",
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
} },
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
"\"" } }
159 static char const *custom_quotes
[][2] = {
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
} },
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
"'" } },
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
")" } },
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
" " } },
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
":" } },
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" } },
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
"'\"" } }
249 use_quote_double_quotes (const char *str
, size_t *len
)
251 char *p
= *len
== SIZE_MAX
? quotearg_char (str
, '"')
252 : quotearg_char_mem (str
, *len
, '"');
258 main (int argc _GL_UNUSED
, char *argv
[])
261 bool ascii_only
= MB_CUR_MAX
== 1 && !isprint ((unsigned char) LQ
[0]);
263 /* This part of the program is hard-wired to the C locale since it
264 does not call setlocale. However, according to POSIX, the use of
265 8-bit bytes in a character context in the C locale gives
266 unspecified results (that is, the C locale charset is allowed to
267 be unibyte with 8-bit bytes rejected [ASCII], unibyte with 8-bit
268 bytes being characters [often ISO-8859-1], or multibyte [often
269 UTF-8]). We assume that the latter two cases will be
270 indistinguishable in this test - that is, the LQ and RQ sequences
271 will pass through unchanged in either type of charset. So when
272 testing for quoting of str7, use the ascii_only flag to decide
273 what to expect for the 8-bit data being quoted. */
274 ASSERT (!isprint ('\033'));
275 for (i
= literal_quoting_style
; i
<= clocale_quoting_style
; i
++)
277 set_quoting_style (NULL
, (enum quoting_style
) i
);
278 if (!(i
== locale_quoting_style
|| i
== clocale_quoting_style
)
279 || (strcmp (locale_charset (), "ASCII") == 0
280 || strcmp (locale_charset (), "ANSI_X3.4-1968") == 0))
282 compare_strings (use_quotearg_buffer
, &results_g
[i
].group1
,
284 compare_strings (use_quotearg
, &results_g
[i
].group2
,
286 if (i
== c_quoting_style
)
287 compare_strings (use_quote_double_quotes
, &results_g
[i
].group2
,
289 compare_strings (use_quotearg_colon
, &results_g
[i
].group3
,
294 set_quoting_style (NULL
, literal_quoting_style
);
295 ASSERT (set_quoting_flags (NULL
, QA_ELIDE_NULL_BYTES
) == 0);
296 compare_strings (use_quotearg_buffer
, &flag_results
[0].group1
, ascii_only
);
297 compare_strings (use_quotearg
, &flag_results
[0].group2
, ascii_only
);
298 compare_strings (use_quotearg_colon
, &flag_results
[0].group3
, ascii_only
);
300 set_quoting_style (NULL
, c_quoting_style
);
301 ASSERT (set_quoting_flags (NULL
, QA_ELIDE_OUTER_QUOTES
)
302 == QA_ELIDE_NULL_BYTES
);
303 compare_strings (use_quotearg_buffer
, &flag_results
[1].group1
, ascii_only
);
304 compare_strings (use_quotearg
, &flag_results
[1].group2
, ascii_only
);
305 compare_strings (use_quote_double_quotes
, &flag_results
[1].group2
,
307 compare_strings (use_quotearg_colon
, &flag_results
[1].group3
, ascii_only
);
309 ASSERT (set_quoting_flags (NULL
, QA_SPLIT_TRIGRAPHS
)
310 == QA_ELIDE_OUTER_QUOTES
);
311 compare_strings (use_quotearg_buffer
, &flag_results
[2].group1
, ascii_only
);
312 compare_strings (use_quotearg
, &flag_results
[2].group2
, ascii_only
);
313 compare_strings (use_quote_double_quotes
, &flag_results
[2].group2
,
315 compare_strings (use_quotearg_colon
, &flag_results
[2].group3
, ascii_only
);
317 ASSERT (set_quoting_flags (NULL
, 0) == QA_SPLIT_TRIGRAPHS
);
319 for (i
= 0; i
< sizeof custom_quotes
/ sizeof *custom_quotes
; ++i
)
321 set_custom_quoting (NULL
,
322 custom_quotes
[i
][0], custom_quotes
[i
][1]);
323 compare_strings (use_quotearg_buffer
, &custom_results
[i
].group1
,
325 compare_strings (use_quotearg
, &custom_results
[i
].group2
, ascii_only
);
326 compare_strings (use_quotearg_colon
, &custom_results
[i
].group3
,
331 /* Trigger the bug whereby quotearg_buffer would read beyond the NUL
332 that defines the end of the string being quoted. Use an input
333 string whose NUL is the last byte before an unreadable page. */
334 char *z
= zerosize_ptr ();
339 char *q
= malloc (q_len
+ 1);
341 memset (q
, 'Q', q_len
);
344 /* Z points to the boundary between a readable/writable page
345 and one that is neither readable nor writable. Position
346 our string so its NUL is at the end of the writable one. */
347 char const *str
= "____";
348 size_t s_len
= strlen (str
);
350 memcpy (z
, str
, s_len
+ 1);
352 set_custom_quoting (NULL
, q
, q
);
353 /* Whether this actually triggers a SEGV depends on the
354 implementation of memcmp: whether it compares only byte-at-
355 a-time, and from left to right (no SEGV) or some other way. */
356 size_t n
= quotearg_buffer (buf
, sizeof buf
, z
, SIZE_MAX
, NULL
);
357 ASSERT (n
== s_len
+ 2 * q_len
);
358 ASSERT (memcmp (buf
, q
, sizeof buf
) == 0);