sq_dequote: fix extra consumption of source string
[git] / quote.c
1 #include "cache.h"
2 #include "quote.h"
3 #include "argv-array.h"
4
5 int quote_path_fully = 1;
6
7 static inline int need_bs_quote(char c)
8 {
9         return (c == '\'' || c == '!');
10 }
11
12 /* Help to copy the thing properly quoted for the shell safety.
13  * any single quote is replaced with '\'', any exclamation point
14  * is replaced with '\!', and the whole thing is enclosed in a
15  * single quote pair.
16  *
17  * E.g.
18  *  original     sq_quote     result
19  *  name     ==> name      ==> 'name'
20  *  a b      ==> a b       ==> 'a b'
21  *  a'b      ==> a'\''b    ==> 'a'\''b'
22  *  a!b      ==> a'\!'b    ==> 'a'\!'b'
23  */
24 void sq_quote_buf(struct strbuf *dst, const char *src)
25 {
26         char *to_free = NULL;
27
28         if (dst->buf == src)
29                 to_free = strbuf_detach(dst, NULL);
30
31         strbuf_addch(dst, '\'');
32         while (*src) {
33                 size_t len = strcspn(src, "'!");
34                 strbuf_add(dst, src, len);
35                 src += len;
36                 while (need_bs_quote(*src)) {
37                         strbuf_addstr(dst, "'\\");
38                         strbuf_addch(dst, *src++);
39                         strbuf_addch(dst, '\'');
40                 }
41         }
42         strbuf_addch(dst, '\'');
43         free(to_free);
44 }
45
46 void sq_quotef(struct strbuf *dst, const char *fmt, ...)
47 {
48         struct strbuf src = STRBUF_INIT;
49
50         va_list ap;
51         va_start(ap, fmt);
52         strbuf_vaddf(&src, fmt, ap);
53         va_end(ap);
54
55         sq_quote_buf(dst, src.buf);
56         strbuf_release(&src);
57 }
58
59 void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
60 {
61         int i;
62
63         /* Copy into destination buffer. */
64         strbuf_grow(dst, 255);
65         for (i = 0; argv[i]; ++i) {
66                 strbuf_addch(dst, ' ');
67                 sq_quote_buf(dst, argv[i]);
68                 if (maxlen && dst->len > maxlen)
69                         die("Too many or long arguments");
70         }
71 }
72
73 static char *sq_dequote_step(char *arg, char **next)
74 {
75         char *dst = arg;
76         char *src = arg;
77         char c;
78
79         if (*src != '\'')
80                 return NULL;
81         for (;;) {
82                 c = *++src;
83                 if (!c)
84                         return NULL;
85                 if (c != '\'') {
86                         *dst++ = c;
87                         continue;
88                 }
89                 /* We stepped out of sq */
90                 switch (*++src) {
91                 case '\0':
92                         *dst = 0;
93                         if (next)
94                                 *next = NULL;
95                         return arg;
96                 case '\\':
97                         /*
98                          * Allow backslashed characters outside of
99                          * single-quotes only if they need escaping,
100                          * and only if we resume the single-quoted part
101                          * afterward.
102                          */
103                         if (need_bs_quote(src[1]) && src[2] == '\'') {
104                                 *dst++ = src[1];
105                                 src += 2;
106                                 continue;
107                         }
108                 /* Fallthrough */
109                 default:
110                         if (!next || !isspace(*src))
111                                 return NULL;
112                         do {
113                                 c = *++src;
114                         } while (isspace(c));
115                         *dst = 0;
116                         *next = src;
117                         return arg;
118                 }
119         }
120 }
121
122 char *sq_dequote(char *arg)
123 {
124         return sq_dequote_step(arg, NULL);
125 }
126
127 static int sq_dequote_to_argv_internal(char *arg,
128                                        const char ***argv, int *nr, int *alloc,
129                                        struct argv_array *array)
130 {
131         char *next = arg;
132
133         if (!*arg)
134                 return 0;
135         do {
136                 char *dequoted = sq_dequote_step(next, &next);
137                 if (!dequoted)
138                         return -1;
139                 if (argv) {
140                         ALLOC_GROW(*argv, *nr + 1, *alloc);
141                         (*argv)[(*nr)++] = dequoted;
142                 }
143                 if (array)
144                         argv_array_push(array, dequoted);
145         } while (next);
146
147         return 0;
148 }
149
150 int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
151 {
152         return sq_dequote_to_argv_internal(arg, argv, nr, alloc, NULL);
153 }
154
155 int sq_dequote_to_argv_array(char *arg, struct argv_array *array)
156 {
157         return sq_dequote_to_argv_internal(arg, NULL, NULL, NULL, array);
158 }
159
160 /* 1 means: quote as octal
161  * 0 means: quote as octal if (quote_path_fully)
162  * -1 means: never quote
163  * c: quote as "\\c"
164  */
165 #define X8(x)   x, x, x, x, x, x, x, x
166 #define X16(x)  X8(x), X8(x)
167 static signed char const sq_lookup[256] = {
168         /*           0    1    2    3    4    5    6    7 */
169         /* 0x00 */   1,   1,   1,   1,   1,   1,   1, 'a',
170         /* 0x08 */ 'b', 't', 'n', 'v', 'f', 'r',   1,   1,
171         /* 0x10 */ X16(1),
172         /* 0x20 */  -1,  -1, '"',  -1,  -1,  -1,  -1,  -1,
173         /* 0x28 */ X16(-1), X16(-1), X16(-1),
174         /* 0x58 */  -1,  -1,  -1,  -1,'\\',  -1,  -1,  -1,
175         /* 0x60 */ X16(-1), X8(-1),
176         /* 0x78 */  -1,  -1,  -1,  -1,  -1,  -1,  -1,   1,
177         /* 0x80 */ /* set to 0 */
178 };
179
180 static inline int sq_must_quote(char c)
181 {
182         return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
183 }
184
185 /* returns the longest prefix not needing a quote up to maxlen if positive.
186    This stops at the first \0 because it's marked as a character needing an
187    escape */
188 static size_t next_quote_pos(const char *s, ssize_t maxlen)
189 {
190         size_t len;
191         if (maxlen < 0) {
192                 for (len = 0; !sq_must_quote(s[len]); len++);
193         } else {
194                 for (len = 0; len < maxlen && !sq_must_quote(s[len]); len++);
195         }
196         return len;
197 }
198
199 /*
200  * C-style name quoting.
201  *
202  * (1) if sb and fp are both NULL, inspect the input name and counts the
203  *     number of bytes that are needed to hold c_style quoted version of name,
204  *     counting the double quotes around it but not terminating NUL, and
205  *     returns it.
206  *     However, if name does not need c_style quoting, it returns 0.
207  *
208  * (2) if sb or fp are not NULL, it emits the c_style quoted version
209  *     of name, enclosed with double quotes if asked and needed only.
210  *     Return value is the same as in (1).
211  */
212 static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
213                                     struct strbuf *sb, FILE *fp, int no_dq)
214 {
215 #undef EMIT
216 #define EMIT(c)                                 \
217         do {                                        \
218                 if (sb) strbuf_addch(sb, (c));          \
219                 if (fp) fputc((c), fp);                 \
220                 count++;                                \
221         } while (0)
222 #define EMITBUF(s, l)                           \
223         do {                                        \
224                 if (sb) strbuf_add(sb, (s), (l));       \
225                 if (fp) fwrite((s), (l), 1, fp);        \
226                 count += (l);                           \
227         } while (0)
228
229         size_t len, count = 0;
230         const char *p = name;
231
232         for (;;) {
233                 int ch;
234
235                 len = next_quote_pos(p, maxlen);
236                 if (len == maxlen || (maxlen < 0 && !p[len]))
237                         break;
238
239                 if (!no_dq && p == name)
240                         EMIT('"');
241
242                 EMITBUF(p, len);
243                 EMIT('\\');
244                 p += len;
245                 ch = (unsigned char)*p++;
246                 if (maxlen >= 0)
247                         maxlen -= len + 1;
248                 if (sq_lookup[ch] >= ' ') {
249                         EMIT(sq_lookup[ch]);
250                 } else {
251                         EMIT(((ch >> 6) & 03) + '0');
252                         EMIT(((ch >> 3) & 07) + '0');
253                         EMIT(((ch >> 0) & 07) + '0');
254                 }
255         }
256
257         EMITBUF(p, len);
258         if (p == name)   /* no ending quote needed */
259                 return 0;
260
261         if (!no_dq)
262                 EMIT('"');
263         return count;
264 }
265
266 size_t quote_c_style(const char *name, struct strbuf *sb, FILE *fp, int nodq)
267 {
268         return quote_c_style_counted(name, -1, sb, fp, nodq);
269 }
270
271 void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path, int nodq)
272 {
273         if (quote_c_style(prefix, NULL, NULL, 0) ||
274             quote_c_style(path, NULL, NULL, 0)) {
275                 if (!nodq)
276                         strbuf_addch(sb, '"');
277                 quote_c_style(prefix, sb, NULL, 1);
278                 quote_c_style(path, sb, NULL, 1);
279                 if (!nodq)
280                         strbuf_addch(sb, '"');
281         } else {
282                 strbuf_addstr(sb, prefix);
283                 strbuf_addstr(sb, path);
284         }
285 }
286
287 void write_name_quoted(const char *name, FILE *fp, int terminator)
288 {
289         if (terminator) {
290                 quote_c_style(name, NULL, fp, 0);
291         } else {
292                 fputs(name, fp);
293         }
294         fputc(terminator, fp);
295 }
296
297 void write_name_quoted_relative(const char *name, const char *prefix,
298                                 FILE *fp, int terminator)
299 {
300         struct strbuf sb = STRBUF_INIT;
301
302         name = relative_path(name, prefix, &sb);
303         write_name_quoted(name, fp, terminator);
304
305         strbuf_release(&sb);
306 }
307
308 /* quote path as relative to the given prefix */
309 char *quote_path_relative(const char *in, const char *prefix,
310                           struct strbuf *out)
311 {
312         struct strbuf sb = STRBUF_INIT;
313         const char *rel = relative_path(in, prefix, &sb);
314         strbuf_reset(out);
315         quote_c_style_counted(rel, strlen(rel), out, NULL, 0);
316         strbuf_release(&sb);
317
318         return out->buf;
319 }
320
321 /*
322  * C-style name unquoting.
323  *
324  * Quoted should point at the opening double quote.
325  * + Returns 0 if it was able to unquote the string properly, and appends the
326  *   result in the strbuf `sb'.
327  * + Returns -1 in case of error, and doesn't touch the strbuf. Though note
328  *   that this function will allocate memory in the strbuf, so calling
329  *   strbuf_release is mandatory whichever result unquote_c_style returns.
330  *
331  * Updates endp pointer to point at one past the ending double quote if given.
332  */
333 int unquote_c_style(struct strbuf *sb, const char *quoted, const char **endp)
334 {
335         size_t oldlen = sb->len, len;
336         int ch, ac;
337
338         if (*quoted++ != '"')
339                 return -1;
340
341         for (;;) {
342                 len = strcspn(quoted, "\"\\");
343                 strbuf_add(sb, quoted, len);
344                 quoted += len;
345
346                 switch (*quoted++) {
347                   case '"':
348                         if (endp)
349                                 *endp = quoted;
350                         return 0;
351                   case '\\':
352                         break;
353                   default:
354                         goto error;
355                 }
356
357                 switch ((ch = *quoted++)) {
358                 case 'a': ch = '\a'; break;
359                 case 'b': ch = '\b'; break;
360                 case 'f': ch = '\f'; break;
361                 case 'n': ch = '\n'; break;
362                 case 'r': ch = '\r'; break;
363                 case 't': ch = '\t'; break;
364                 case 'v': ch = '\v'; break;
365
366                 case '\\': case '"':
367                         break; /* verbatim */
368
369                 /* octal values with first digit over 4 overflow */
370                 case '0': case '1': case '2': case '3':
371                                         ac = ((ch - '0') << 6);
372                         if ((ch = *quoted++) < '0' || '7' < ch)
373                                 goto error;
374                                         ac |= ((ch - '0') << 3);
375                         if ((ch = *quoted++) < '0' || '7' < ch)
376                                 goto error;
377                                         ac |= (ch - '0');
378                                         ch = ac;
379                                         break;
380                                 default:
381                         goto error;
382                         }
383                 strbuf_addch(sb, ch);
384                 }
385
386   error:
387         strbuf_setlen(sb, oldlen);
388         return -1;
389 }
390
391 /* quoting as a string literal for other languages */
392
393 void perl_quote_buf(struct strbuf *sb, const char *src)
394 {
395         const char sq = '\'';
396         const char bq = '\\';
397         char c;
398
399         strbuf_addch(sb, sq);
400         while ((c = *src++)) {
401                 if (c == sq || c == bq)
402                         strbuf_addch(sb, bq);
403                 strbuf_addch(sb, c);
404         }
405         strbuf_addch(sb, sq);
406 }
407
408 void python_quote_buf(struct strbuf *sb, const char *src)
409 {
410         const char sq = '\'';
411         const char bq = '\\';
412         const char nl = '\n';
413         char c;
414
415         strbuf_addch(sb, sq);
416         while ((c = *src++)) {
417                 if (c == nl) {
418                         strbuf_addch(sb, bq);
419                         strbuf_addch(sb, 'n');
420                         continue;
421                 }
422                 if (c == sq || c == bq)
423                         strbuf_addch(sb, bq);
424                 strbuf_addch(sb, c);
425         }
426         strbuf_addch(sb, sq);
427 }
428
429 void tcl_quote_buf(struct strbuf *sb, const char *src)
430 {
431         char c;
432
433         strbuf_addch(sb, '"');
434         while ((c = *src++)) {
435                 switch (c) {
436                 case '[': case ']':
437                 case '{': case '}':
438                 case '$': case '\\': case '"':
439                         strbuf_addch(sb, '\\');
440                 default:
441                         strbuf_addch(sb, c);
442                         break;
443                 case '\f':
444                         strbuf_addstr(sb, "\\f");
445                         break;
446                 case '\r':
447                         strbuf_addstr(sb, "\\r");
448                         break;
449                 case '\n':
450                         strbuf_addstr(sb, "\\n");
451                         break;
452                 case '\t':
453                         strbuf_addstr(sb, "\\t");
454                         break;
455                 case '\v':
456                         strbuf_addstr(sb, "\\v");
457                         break;
458                 }
459         }
460         strbuf_addch(sb, '"');
461 }
462
463 void basic_regex_quote_buf(struct strbuf *sb, const char *src)
464 {
465         char c;
466
467         if (*src == '^') {
468                 /* only beginning '^' is special and needs quoting */
469                 strbuf_addch(sb, '\\');
470                 strbuf_addch(sb, *src++);
471         }
472         if (*src == '*')
473                 /* beginning '*' is not special, no quoting */
474                 strbuf_addch(sb, *src++);
475
476         while ((c = *src++)) {
477                 switch (c) {
478                 case '[':
479                 case '.':
480                 case '\\':
481                 case '*':
482                         strbuf_addch(sb, '\\');
483                         strbuf_addch(sb, c);
484                         break;
485
486                 case '$':
487                         /* only the end '$' is special and needs quoting */
488                         if (*src == '\0')
489                                 strbuf_addch(sb, '\\');
490                         strbuf_addch(sb, c);
491                         break;
492
493                 default:
494                         strbuf_addch(sb, c);
495                         break;
496                 }
497         }
498 }