diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-06-19 15:59:12 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-06-20 10:26:39 +0200 | 
| commit | f2981c2ff581e4e425c7b23da43aee29f25232c5 (patch) | |
| tree | 5e809b9d7aff2db64edcd89afdf1ed4b40f054d5 | |
| parent | 2f172ede7115d0a2730a3b689131042ba559e272 (diff) | |
simplify and improve canonicalize_name
 - Replace scan and memmove with simple automaton
 - Convert forward to back slashes, lots of file systems treat them
   equivalenty, this saves us a few more checks down the road
 - Remove './' path components. We can saveley remove them in a string
   processing step instead of throwing an error. Also they actually appear
   often in tar balls, possibly not under user control.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
| -rw-r--r-- | include/util.h | 6 | ||||
| -rw-r--r-- | lib/util/canonicalize_name.c | 78 | 
2 files changed, 41 insertions, 43 deletions
diff --git a/include/util.h b/include/util.h index 28d21bc..d5b20dd 100644 --- a/include/util.h +++ b/include/util.h @@ -6,9 +6,9 @@  #include <stdint.h>  /* -  Removes all preceeding and trailing slashes, shortens all sequences of -  slashes to a single slash and returns failure state if one of the path -  components is '..' or '.'. +  Convert back to forward slashed, remove all preceeding and trailing slashes, +  collapse all sequences of slashes, remove all path components that are '.' +  and returns failure state if one of the path components is '..'.    Returns 0 on success.  */ diff --git a/lib/util/canonicalize_name.c b/lib/util/canonicalize_name.c index 6703b66..57e4d66 100644 --- a/lib/util/canonicalize_name.c +++ b/lib/util/canonicalize_name.c @@ -1,56 +1,54 @@  /* SPDX-License-Identifier: GPL-3.0-or-later */ -#include <string.h> -  #include "util.h" -int canonicalize_name(char *filename) +static void normalize_slashes(char *filename)  { -	char *ptr = filename; -	int i; - -	while (*ptr == '/') -		++ptr; - -	if (ptr != filename) { -		memmove(filename, ptr, strlen(ptr) + 1); -		ptr = filename; -	} - -	while (*ptr != '\0') { -		if (*ptr == '/') { -			for (i = 0; ptr[i] == '/'; ++i) -				; - -			if (i > 1) -				memmove(ptr + 1, ptr + i, strlen(ptr + i) + 1); -		} - -		if (ptr[0] == '/' && ptr[1] == '\0') { -			*ptr = '\0'; -			break; +	char *dst = filename, *src = filename; + +	while (*src == '/' || *src == '\\') +		++src; + +	while (*src != '\0') { +		if (*src == '/' || *src == '\\') { +			while (*src == '/' || *src == '\\') +				++src; +			if (*src == '\0') +				break; +			*(dst++) = '/'; +		} else { +			*(dst++) = *(src++);  		} - -		++ptr;  	} -	ptr = filename; +	*dst = '\0'; +} -	while (*ptr != '\0') { -		if (ptr[0] == '.') { -			if (ptr[1] == '/' || ptr[1] == '\0') -				return -1; +int canonicalize_name(char *filename) +{ +	char *dst = filename, *src = filename; -			if (ptr[1] == '.' && -			    (ptr[2] == '/' || ptr[2] == '\0')) { -				return -1; +	normalize_slashes(filename); + +	while (*src != '\0') { +		if (src[0] == '.') { +			if (src[1] == '\0') +				break; +			if (src[1] == '/') { +				src += 2; +				continue;  			} +			if (src[1] == '.' && (src[2] == '/' || src[2] == '\0')) +				return -1;  		} -		while (*ptr != '\0' && *ptr != '/') -			++ptr; -		if (*ptr == '/') -			++ptr; +		while (*src != '\0' && *src != '/') +			*(dst++) = *(src++); + +		if (*src == '/') +			*(dst++) = *(src++);  	} +	*dst = '\0'; +	normalize_slashes(filename);  	return 0;  }  | 
