diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/common/hardlink.c | 10 | ||||
| -rw-r--r-- | lib/sqfs/dir_reader/get_path.c | 73 | 
2 files changed, 63 insertions, 20 deletions
diff --git a/lib/common/hardlink.c b/lib/common/hardlink.c index 031724b..f8d4d4a 100644 --- a/lib/common/hardlink.c +++ b/lib/common/hardlink.c @@ -49,9 +49,9 @@ static int map_nodes(rbtree_t *inumtree, sqfs_hard_link_t **out,  		goto fail_oom;  	lnk->inode_number = idx; -	lnk->target = sqfs_tree_node_get_path(target); -	if (lnk->target == NULL) -		goto fail_oom; +	ret = sqfs_tree_node_get_path(target, &lnk->target); +	if (ret != 0) +		goto fail_path;  	if (canonicalize_name(lnk->target) == 0) {  		lnk->next = (*out); @@ -61,6 +61,10 @@ static int map_nodes(rbtree_t *inumtree, sqfs_hard_link_t **out,  		free(lnk);  	}  	return 0; +fail_path: +	sqfs_perror(NULL, "re-constructing hard link path", ret); +	free(lnk); +	return -1;  fail_oom:  	fputs("detecting hard links in file system tree: out of memory\n",  	      stderr); diff --git a/lib/sqfs/dir_reader/get_path.c b/lib/sqfs/dir_reader/get_path.c index bdd8317..847bfd3 100644 --- a/lib/sqfs/dir_reader/get_path.c +++ b/lib/sqfs/dir_reader/get_path.c @@ -10,33 +10,72 @@  #include <string.h>  #include <stdlib.h> -char *sqfs_tree_node_get_path(const sqfs_tree_node_t *node) +int sqfs_tree_node_get_path(const sqfs_tree_node_t *node, char **out)  {  	const sqfs_tree_node_t *it; +	size_t clen, len = 0;  	char *str, *ptr; -	size_t len = 0; -	if (node->parent == NULL) -		return strdup("/"); +	*out = NULL; -	for (it = node; it != NULL && it->parent != NULL; it = it->parent) { -		len += strlen((const char *)it->name) + 1; +	if (node == NULL) +		return SQFS_ERROR_ARG_INVALID; + +	for (it = node; it->parent != NULL; it = it->parent) { +		if (it->parent == node) +			return SQFS_ERROR_LINK_LOOP; + +		/* non-root nodes must have a valid name */ +		clen = strlen((const char *)it->name); + +		if (clen == 0) +			return SQFS_ERROR_CORRUPTED; + +		if (strchr((const char *)it->name, '/') != NULL) +			return SQFS_ERROR_CORRUPTED; + +		if (it->name[0] == '.') { +			if (clen == 1 || (clen == 2 && it->name[1] == '.')) +				return SQFS_ERROR_CORRUPTED; +		} + +		/* compute total path length */ +		if (SZ_ADD_OV(clen, 1, &clen)) +			return SQFS_ERROR_OVERFLOW; + +		if (SZ_ADD_OV(len, clen, &len)) +			return SQFS_ERROR_OVERFLOW;  	} -	str = malloc(len + 1); -	if (str == NULL) -		return NULL; +	/* root node must not have a name */ +	if (it->name[0] != '\0') +		return SQFS_ERROR_ARG_INVALID; + +	/* generate the path */ +	if (node->parent == NULL) { +		str = strdup("/"); +		if (str == NULL) +			return SQFS_ERROR_ALLOC; +	} else { +		if (SZ_ADD_OV(len, 1, &len)) +			return SQFS_ERROR_OVERFLOW; + +		str = malloc(len); +		if (str == NULL) +			return SQFS_ERROR_ALLOC; -	ptr = str + len; -	*ptr = '\0'; +		ptr = str + len - 1; +		*ptr = '\0'; -	for (it = node; it != NULL && it->parent != NULL; it = it->parent) { -		len = strlen((const char *)it->name); -		ptr -= len; +		for (it = node; it->parent != NULL; it = it->parent) { +			len = strlen((const char *)it->name); +			ptr -= len; -		memcpy(ptr, (const char *)it->name, len); -		*(--ptr) = '/'; +			memcpy(ptr, (const char *)it->name, len); +			*(--ptr) = '/'; +		}  	} -	return str; +	*out = str; +	return 0;  }  | 
