• R/O
  • SSH
  • HTTPS

yash: 提交


Commit MetaInfo

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

Log Message

Correct escaping in quote removal in double bracket command

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

Change Summary

差異

--- yash/trunk/builtins/test.c (revision 4101)
+++ yash/trunk/builtins/test.c (revision 4102)
@@ -77,18 +77,21 @@
7777 #if YASH_ENABLE_DOUBLE_BRACKET
7878 static int eval_dbexp(const dbexp_T *e)
7979 __attribute__((nonnull));
80-static inline wchar_t *expand_double_bracket_operand_escaped(
81- const wordunit_T *w)
82- __attribute__((nonnull,malloc,warn_unused_result));
80+static inline cc_word_T expand_double_bracket_operand(const wordunit_T *w)
81+ __attribute__((nonnull,warn_unused_result));
8382 static inline wchar_t *expand_double_bracket_operand_unescaped(
8483 const wordunit_T *w)
8584 __attribute__((nonnull,malloc,warn_unused_result));
86-static bool test_triple_db(
87- const wchar_t *lhs, const wchar_t *op, const wchar_t *rhs_escaped)
85+static bool test_triple_db(const wchar_t *lhs, const wchar_t *op,
86+ const wchar_t *rhsvalue, const char *rhscc)
8887 __attribute__((nonnull));
89-static bool test_triple_args(
90- const wchar_t *left, const wchar_t *op, const wchar_t *right)
88+static bool quote_removal_and_test_triple(
89+ const wchar_t *lhs, const wchar_t *op,
90+ const wchar_t *rhsvalue, const char *rhscc, escaping_T escaping)
9191 __attribute__((nonnull));
92+static bool quote_removal_and_pattern_matching(
93+ const wchar_t *lhs, const wchar_t *rhsvalue, const char *rhscc)
94+ __attribute__((nonnull));
9295 #endif
9396
9497
@@ -725,7 +728,8 @@
725728 {
726729 int lhs_result;
727730 bool result;
728- wchar_t *lhs = NULL, *rhs = NULL;
731+ wchar_t *lhs = NULL;
732+ cc_word_T rhs = { NULL, NULL };
729733
730734 switch (e->type) {
731735 case DBE_OR:
@@ -746,25 +750,27 @@
746750 }
747751
748752 case DBE_UNARY:
749- rhs = expand_double_bracket_operand_unescaped(e->rhs.word);
750- if (rhs == NULL)
753+ rhs.value = expand_double_bracket_operand_unescaped(e->rhs.word);
754+ if (rhs.value == NULL)
751755 return Exit_TESTERROR;
752- result = test_double((void *[]) { e->operator, rhs });
756+ result = test_double((void *[]) { e->operator, rhs.value });
753757 break;
754758 case DBE_BINARY:
755759 lhs = expand_double_bracket_operand_unescaped(e->lhs.word);
756760 if (lhs == NULL)
757761 return Exit_TESTERROR;
758- rhs = expand_double_bracket_operand_escaped(e->rhs.word);
759- if (rhs == NULL)
762+ rhs = expand_double_bracket_operand(e->rhs.word);
763+ if (rhs.value == NULL) {
764+ free(lhs);
760765 return Exit_TESTERROR;
761- result = test_triple_db(lhs, e->operator, rhs);
766+ }
767+ result = test_triple_db(lhs, e->operator, rhs.value, rhs.cc);
762768 break;
763769 case DBE_STRING:
764- rhs = expand_double_bracket_operand_unescaped(e->rhs.word);
765- if (rhs == NULL)
770+ rhs.value = expand_double_bracket_operand_unescaped(e->rhs.word);
771+ if (rhs.value == NULL)
766772 return Exit_TESTERROR;
767- result = test_single((void *[]) { rhs });
773+ result = test_single((void *[]) { rhs.value });
768774 break;
769775
770776 default:
@@ -772,17 +778,17 @@
772778 }
773779
774780 free(lhs);
775- free(rhs);
781+ free(rhs.value);
782+ free(rhs.cc);
776783 if (yash_error_message_count > 0)
777784 return Exit_TESTERROR;
778785 return result ? Exit_TRUE : Exit_FALSE;
779786 }
780787
781-/* Expands the operand of a primary.
782- * The result may contain backslash escapes. */
783-wchar_t *expand_double_bracket_operand_escaped(const wordunit_T *w)
788+/* Expands the operand of a primary, but without quote removal. */
789+cc_word_T expand_double_bracket_operand(const wordunit_T *w)
784790 {
785- return expand_single(w, TT_SINGLE, Q_WORD, ES_QUOTED);
791+ return expand_single_cc(w, TT_SINGLE, Q_WORD);
786792 }
787793
788794 /* Expands the operand of a primary.
@@ -793,10 +799,10 @@
793799 }
794800
795801 /* Tests the specified three-token (binary) primary in the double-bracket
796- * command. The left-hand-side must be given literal while the right-hand-side
797- * backslash-escaped. */
798-bool test_triple_db(
799- const wchar_t *lhs, const wchar_t *op, const wchar_t *rhs_escaped)
802+ * command. The left-hand-side must be given literal (with quote removal already
803+ * performed) while the right-hand-side quoted (without quote removal). */
804+bool test_triple_db(const wchar_t *lhs, const wchar_t *op,
805+ const wchar_t *rhsvalue, const char *rhscc)
800806 {
801807 /* Some string comparison primaries in the double-bracket command are
802808 * different from those in the test built-in. */
@@ -804,30 +810,44 @@
804810 case L'=':
805811 if (op[1] == L'~') {
806812 assert(op[2] == L'\0');
807- return test_triple_args(lhs, op, rhs_escaped);
813+ return quote_removal_and_test_triple(
814+ lhs, op, rhsvalue, rhscc, ES_QUOTED);
808815 }
809816 if (op[1] == L'\0' || (op[1] == L'=' && op[2] == L'\0'))
810- return match_pattern(lhs, rhs_escaped);
817+ return quote_removal_and_pattern_matching(lhs, rhsvalue, rhscc);
811818 break;
812819 case L'!':
813820 assert(op[1] == L'=');
814821 if (op[2] == L'\0')
815- return !match_pattern(lhs, rhs_escaped);
822+ return
823+ !quote_removal_and_pattern_matching(lhs, rhsvalue, rhscc);
816824 break;
817825 }
818826
819- wchar_t *rhs = unescape(rhs_escaped);
820- bool result = test_triple_args(lhs, op, rhs);
827+ return quote_removal_and_test_triple(lhs, op, rhsvalue, rhscc, ES_NONE);
828+}
829+
830+/* Performs quote removal on the right hand side and then applies `test_triple'.
831+ */
832+bool quote_removal_and_test_triple(
833+ const wchar_t *lhs, const wchar_t *op,
834+ const wchar_t *rhsvalue, const char *rhscc, escaping_T escaping)
835+{
836+ wchar_t *rhs = quote_removal(rhsvalue, rhscc, escaping);
837+ void *args[] = { (void *) lhs, (void *) op, (void *) rhs, };
838+ bool result = test_triple(args);
821839 free(rhs);
822840 return result;
823841 }
824842
825-/* Tests the specified three-token expression. */
826-bool test_triple_args(
827- const wchar_t *left, const wchar_t *op, const wchar_t *right)
843+/* Performs quote removal on the right hand side and then pattern matching. */
844+bool quote_removal_and_pattern_matching(
845+ const wchar_t *lhs, const wchar_t *rhsvalue, const char *rhscc)
828846 {
829- void *args[] = { (void *) left, (void *) op, (void *) right, };
830- return test_triple(args);
847+ wchar_t *rhs = quote_removal(rhsvalue, rhscc, ES_QUOTED);
848+ bool result = match_pattern(lhs, rhs);
849+ free(rhs);
850+ return result;
831851 }
832852
833853 #endif /* YASH_ENABLE_DOUBLE_BRACKET */
--- yash/trunk/expand.c (revision 4101)
+++ yash/trunk/expand.c (revision 4102)
@@ -142,9 +142,6 @@
142142 __attribute__((nonnull));
143143 static inline bool should_escape(char c, charcategory_T cc, escaping_T escaping)
144144 __attribute__((const));
145-static wchar_t *quote_removal(
146- const wchar_t *restrict s, const char *restrict cc, escaping_T escaping)
147- __attribute__((nonnull,malloc,warn_unused_result));
148145 static wchar_t *quote_removal_free(
149146 wchar_t *restrict s, char *restrict cc, escaping_T escaping)
150147 __attribute__((nonnull,malloc,warn_unused_result));
--- yash/trunk/expand.h (revision 4101)
+++ yash/trunk/expand.h (revision 4102)
@@ -124,6 +124,9 @@
124124 __attribute__((nonnull));
125125 extern wchar_t *unquote(const wchar_t *s)
126126 __attribute__((nonnull,malloc,warn_unused_result));
127+extern wchar_t *quote_removal(
128+ const wchar_t *restrict s, const char *restrict cc, escaping_T escaping)
129+ __attribute__((nonnull,malloc,warn_unused_result));
127130
128131 extern wchar_t *parse_and_expand_string(
129132 const wchar_t *s, const char *name, _Bool esc)
Show on old repository browser