diff mbox series

[v2] expand: Fix naked backslah leakage

Message ID ZjIHe+fg42+MivAy@gondor.apana.org.au (mailing list archive)
State Accepted
Delegated to: Herbert Xu
Headers show
Series [v2] expand: Fix naked backslah leakage | expand

Commit Message

Herbert Xu May 1, 2024, 9:12 a.m. UTC
v2 adjusts qchars to skip the backslash.

---8<---
Naked backslashes in patterns may incorrectly unquote subsequent
wild characters that are themselves quoted.  Fix this by adding
an extra backslash when necessary.

Test case:

	a="\\*bc"; b="\\"; c="*"; echo "<${a##$b"$c"}>"

Old result:

	<>

New result:

	<bc>

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 src/expand.c   | 10 ++++++++--
 src/mystring.c |  1 +
 src/mystring.h |  2 +-
 3 files changed, 10 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/src/expand.c b/src/expand.c
index 2ed02d6..0db2b29 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -1658,6 +1658,7 @@  _rmescapes(char *str, int flag)
 	char *p, *q, *r;
 	int notescaped;
 	int globbing;
+	int inquotes;
 
 	p = strpbrk(str, cqchars);
 	if (!p) {
@@ -1692,16 +1693,17 @@  _rmescapes(char *str, int flag)
 			q = mempcpy(q, str, len);
 		}
 	}
+	inquotes = 0;
 	notescaped = globbing;
 	while (*p) {
 		if (*p == (char)CTLQUOTEMARK) {
 			p++;
-			notescaped = globbing;
+			inquotes ^= globbing;
 			continue;
 		}
 		if (*p == '\\') {
 			/* naked back slash */
-			notescaped = 0;
+			notescaped ^= globbing;
 			goto copy;
 		}
 		if (FNMATCH_IS_ENABLED && *p == '^')
@@ -1711,6 +1713,10 @@  _rmescapes(char *str, int flag)
 add_escape:
 			if (notescaped)
 				*q++ = '\\';
+			else if (inquotes) {
+				*q++ = '\\';
+				*q++ = '\\';
+			}
 		}
 		notescaped = globbing;
 copy:
diff --git a/src/mystring.c b/src/mystring.c
index f651521..5eace6c 100644
--- a/src/mystring.c
+++ b/src/mystring.c
@@ -63,6 +63,7 @@  const char snlfmt[] = "%s\n";
 const char dolatstr[] = { CTLQUOTEMARK, CTLVAR, VSNORMAL | VSBIT, '@', '=',
 			  CTLQUOTEMARK, '\0' };
 const char cqchars[] = {
+	'\\',
 #ifdef HAVE_FNMATCH
 	'^',
 #endif
diff --git a/src/mystring.h b/src/mystring.h
index 564b911..d0ec9dd 100644
--- a/src/mystring.h
+++ b/src/mystring.h
@@ -48,7 +48,7 @@  extern const char spcstr[];
 extern const char dolatstr[];
 #define DOLATSTRLEN 6
 extern const char cqchars[];
-#define qchars (cqchars + FNMATCH_IS_ENABLED)
+#define qchars (cqchars + FNMATCH_IS_ENABLED + 1)
 extern const char illnum[];
 extern const char homestr[];