summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2018-03-28 18:37:51 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2018-04-19 18:19:29 +0800
commit3311816551591b60ab0e14f94701bb0f2e19a71f (patch)
tree2ec5a00c1f7b4ea7b43c89fadbe22e6c103ebb56 /src
parentshell: Add subdir-objects to AM_INIT_AUTOMAKE (diff)
downloaddash-3311816551591b60ab0e14f94701bb0f2e19a71f.tar.gz
dash-3311816551591b60ab0e14f94701bb0f2e19a71f.zip
expand: Do not quote backslashes in unquoted parameter expansion
On Mon, Mar 26, 2018 at 07:25:20PM +0200, Martijn Dekker wrote:
> Op 26-03-18 om 17:38 schreef Harald van Dijk:
> > And not by dash 0.5.4. Like I wrote, dash 0.5.5 had some bugs that were
> > fixed in 0.5.6, which mostly restored the behaviour to match <0.5.5.
>
> Ah, sorry. dash 0.5.4 and earlier don't compile on my system, so they
> are not included in my conveniently accessible arsenal of test shells.
>
> > As for my patches, that was by accident and doesn't work reliably. When
> > the shell sees no metacharacters, pathname expansion is bypassed, and
> > backslash isn't considered a metacharacter. Which got me to my original
> > example of /de\v: there are no metacharacters in there, so the shell
> > doesn't look to see if it matches anything. Which seems highly
> > desirable: the shell shouldn't need to hit the file system for words not
> > containing metacharacters. The only way then to get consistent behaviour
> > is if the backslash is taken as quoted, so I'm not tempted to argue for
> > the behaviour you're hoping for, sorry. :)

Here is a better example:

	a="/*/\nullx" b="/*/\null"; printf "%s\n" $a $b

dash currently prints

	/*/\nullx
	/*/\null

bash prints

	/*/\nullx
	/dev/null

You may argue the bash behaviour is inconsistent but it actually
makes sense.  What happens is that quote removal only applies to
the original token as seen by the shell.  It is never applied to
the result of parameter expansion.

Now you may ask why on earth does the second line say "/dev/null"
instead of "/dev/\null".  Well that's because it is not the quote
removal step that removed the backslash, but the pathname expansion.

The fact that the /de\v does not become /dev even though it exists
is just the result of the optimisation to avoid unnecessarily
calling stat(2).  I have checked POSIX and I don't see anything
that forbids this behaviour.

So going back to dash yes I think we should adopt the bash behaviour
for pathname expansion and keep the existing case semantics.

This patch does exactly that.  Note that this patch does not work
unless you have already applied

	https://patchwork.kernel.org/patch/10306507/

because otherwise the optimisation mentioned above does not get
detected correctly and we will end up doing quote removal twice.

This patch also updates expmeta to handle naked backslashes at
the end of the pattern which is now possible.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'src')
-rw-r--r--src/expand.c9
1 files changed, 4 insertions, 5 deletions
diff --git a/src/expand.c b/src/expand.c
index ee077a7..7ed259a 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -849,8 +849,7 @@ memtodest(const char *p, size_t len, const char *syntax, int quotes) {
 		if (c) {
 			if ((quotes & QUOTES_ESC) &&
 			    ((syntax[c] == CCTL) ||
-			     (((quotes & EXP_FULL) || syntax != BASESYNTAX) &&
-			      syntax[c] == CBACK)))
+			     (syntax != BASESYNTAX && syntax[c] == CBACK)))
 				USTPUTC(CTLESC, q);
 		} else if (!(quotes & QUOTES_KEEPNUL))
 			continue;
@@ -1341,7 +1340,7 @@ expmeta(char *name, unsigned name_len, unsigned expdir_len)
 				}
 			}
 		} else {
-			if (*p == '\\')
+			if (*p == '\\' && p[1])
 				esc++;
 			if (p[esc] == '/') {
 				if (metaflag)
@@ -1355,7 +1354,7 @@ expmeta(char *name, unsigned name_len, unsigned expdir_len)
 			return;
 		p = name;
 		do {
-			if (*p == '\\')
+			if (*p == '\\' && p[1])
 				p++;
 			*enddir++ = *p;
 		} while (*p++);
@@ -1367,7 +1366,7 @@ expmeta(char *name, unsigned name_len, unsigned expdir_len)
 	if (name < start) {
 		p = name;
 		do {
-			if (*p == '\\')
+			if (*p == '\\' && p[1])
 				p++;
 			*enddir++ = *p++;
 		} while (p < start);
0100'>2006-12-16Make repo header a link to summary pageLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-16Move cgit_print_date into ui-shared, reuse in ui-summaryLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-16Add ui-commit.c + misc ui cleanupsLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-15Add a common commit parserLars Hjemli Make a better commit parser, replacing the ugly one in ui-log.c Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-14Add simple pager to log pageLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-13Add separate makefile-rule to clear current cacheLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-13Remove implementation details from READMELars Hjemli Let README describe the "bigger picture" instead. Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-13Small layout adjustments to summary and blob viewLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-13Add display of tree content w/ui-tree.cLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-12cache_lock: do xstrdup/free on lockfileLars Hjemli Since fmt() uses 8 alternating static buffers, and cache_lock might call cache_create_dirs() multiple times, which in turn might call fmt() twice, after four iterations lockfile would be overwritten by a cachedirectory path. In worst case, this could cause the cachedirectory to be unlinked and replaced by a cachefile. Fix: use xstrdup() on the result from fmt() before assigning to lockfile, and call free(lockfile) before exit. Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Don't truncate valid cachefilesLars Hjemli An embarrassing thinko in cgit_check_cache() would truncate valid cachefiles in the following situation: 1) process A notices a missing/expired cachefile 2) process B gets scheduled, locks, fills and unlocks the cachefile 3) process A gets scheduled, locks the cachefile, notices that the cachefile now exist/is not expired anymore, and continues to overwrite it with an empty lockfile. Thanks to Linus for noticing (again). Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Move global variables + callback functions into shared.cLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Move functions for generic object output into ui-view.cLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Move log-functions into ui-log.cLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Move repo summary functions into ui-summary.cLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Move functions for repolist output into ui-repolist.cLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Move common output-functions into ui-shared.cLars Hjemli While at it, replace the cgit_[lib_]error constants with a proper function Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Rename config.c to parsing.c + move cgit_parse_query from cgit.c to parsing.cLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Avoid infinite loops in caching layerLars Hjemli Add a global variable, cgit_max_lock_attemps, to avoid the possibility of infinite loops when failing to acquire a lockfile. This could happen on broken setups or under crazy server load. Incidentally, this also fixes a lurking bug in cache_lock() where an uninitialized returnvalue was used. Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Let 'make install' clear all cachefilesLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-11Fix cache algorithm loopholeLars Hjemli This closes the door for unneccessary calls to cgit_fill_cache(). Noticed by Linus. Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-10Add version identifier in generated filesLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-10Add license file and copyright noticesLars Hjemli Signed-off-by: Lars Hjemli <hjemli@gmail.com> 2006-12-10Add caching infrastructureLars Hjemli