• R/O
  • SSH
  • HTTPS

yash: 提交


Commit MetaInfo

修訂4101 (tree)
時間2020-10-04 22:45:13
作者magicant

Log Message

Correct escaping in quote removal in expand_single_with_glob

Unescaping the result of quote_removal(..., ES_QUOTED_HARD) is not the
same as quote_removal(..., ES_NONE).

Change Summary

差異

--- yash/trunk/expand.c (revision 4100)
+++ yash/trunk/expand.c (revision 4101)
@@ -320,12 +320,13 @@
320320 return quote_removal_free(e.value, e.cc, escaping);
321321 }
322322
323-/* Expands a single word: the four expansions, glob, quote removal and unescape.
324- * This function doesn't perform brace expansion and field splitting.
325- * If the result of glob is more than one word,
326- * - returns the pre-glob pattern string if in the POSIXly correct mode
327- * - treats as an error otherwise.
328- * If the "glob" shell option is off, glob is not performed.
323+/* Expands a single word: the four expansions, pathname expansion, and quote
324+ * removal.
325+ * This function doesn't perform brace expansion or field splitting.
326+ * If the result of pathname expansion is more than one word, this function
327+ * - returns the original pattern string if in the POSIXly correct mode
328+ * - treats it as an error otherwise.
329+ * If the "glob" shell option is off, pathname expansion is not performed.
329330 * The "nullglob" shell option is ignored.
330331 * If successful, the resulting word is returned as a newly malloced string.
331332 * On error, an error message is printed and NULL is returned.
@@ -332,51 +333,62 @@
332333 * On error in a non-interactive shell, the shell exits. */
333334 char *expand_single_with_glob(const wordunit_T *arg)
334335 {
335- wchar_t *exp = expand_single(arg, TT_SINGLE, Q_WORD, ES_QUOTED_HARD);
336- char *result;
336+ cc_word_T e = expand_single_cc(arg, TT_SINGLE, Q_WORD);
337+ if (e.value == NULL)
338+ goto return_null;
337339
338- if (exp == NULL)
339- return NULL;
340+ if (!shopt_glob)
341+ goto quote_removal;
340342
341- /* glob */
342- if (shopt_glob && is_pathname_matching_pattern(exp)) {
343- plist_T list;
344- bool ok;
343+ wchar_t *pattern = quote_removal(e.value, e.cc, ES_QUOTED_HARD);
344+ if (!is_pathname_matching_pattern(pattern)) {
345+ free(pattern);
346+ goto quote_removal;
347+ }
345348
346- pl_init(&list);
347- set_interruptible_by_sigint(true);
348- ok = wglob(exp, get_wglobflags(), &list);
349- set_interruptible_by_sigint(false);
350- if (!ok) {
351- free(exp);
352- plfree(pl_toary(&list), free);
353- xerror(EINTR, Ngt("redirection"));
354- result = NULL;
355- } else if (list.length == 1) {
356- free(exp);
357- result = realloc_wcstombs(list.contents[0]);
358- if (result == NULL)
359- xerror(EILSEQ, Ngt("redirection"));
360- pl_destroy(&list);
361- } else {
362- plfree(pl_toary(&list), free);
363- if (posixly_correct) {
364- goto noglob;
365- } else {
366- exp = unescapefree(exp);
367- xerror(0, Ngt("filename `%ls' matches more than one file"),
368- exp);
369- free(exp);
370- result = NULL;
371- }
349+ plist_T globresults;
350+ bool ok;
351+
352+ /* perform pathname expansion */
353+ pl_init(&globresults);
354+ set_interruptible_by_sigint(true);
355+ ok = wglob(pattern, get_wglobflags(), &globresults);
356+ set_interruptible_by_sigint(false);
357+ free(pattern);
358+ if (!ok) {
359+ plfree(pl_toary(&globresults), free);
360+ xerror(EINTR, Ngt("redirection"));
361+ goto return_null;
362+ }
363+
364+ /* examine the expansion results */
365+ wchar_t *wresult;
366+ if (globresults.length == 1) {
367+ wresult = globresults.contents[0];
368+ pl_destroy(&globresults);
369+ } else {
370+ plfree(pl_toary(&globresults), free);
371+ if (!posixly_correct) {
372+ wchar_t *word = quote_removal(e.value, e.cc, ES_NONE);
373+ xerror(0, Ngt("filename `%ls' matches more than one file"), word);
374+ free(word);
375+ goto return_null;
372376 }
373- } else {
374-noglob:
375- result = realloc_wcstombs(unescapefree(exp));
376- if (result == NULL)
377- xerror(EILSEQ, Ngt("redirection"));
377+quote_removal:
378+ wresult = quote_removal(e.value, e.cc, ES_NONE);
378379 }
379- return result;
380+
381+ char *mbresult = realloc_wcstombs(wresult);
382+ if (mbresult == NULL)
383+ xerror(EILSEQ, Ngt("redirection"));
384+ free(e.value);
385+ free(e.cc);
386+ return mbresult;
387+
388+return_null:
389+ free(e.value);
390+ free(e.cc);
391+ return NULL;
380392 }
381393
382394
@@ -1746,6 +1758,7 @@
17461758 return wb_towcs(&buf);
17471759 }
17481760
1761+#if 0
17491762 /* Same as `unescape', except that the first argument is freed. */
17501763 wchar_t *unescapefree(wchar_t *s)
17511764 {
@@ -1756,6 +1769,7 @@
17561769 free(s);
17571770 return result;
17581771 }
1772+#endif
17591773
17601774 /* Quotes the specified string using backslashes and single-quotes. The result
17611775 * is suitable for re-parsing as a shell command word that would expand to the
Show on old repository browser