[PATCH] erofs-utils: lib: consolidate erofs_rebuild_get_dentry()

Gao Xiang hsiangkao at linux.alibaba.com
Fri Jun 20 13:26:16 AEST 2025


 - Avoid `memcmps`, which could cause potential out-of-range read risks;

 - Replace `strlen()` and `memchr()` with `strchr()`.

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 lib/rebuild.c | 71 +++++++++++++++++++++++++++------------------------
 1 file changed, 37 insertions(+), 34 deletions(-)

diff --git a/lib/rebuild.c b/lib/rebuild.c
index d428573..6ae5ddf 100644
--- a/lib/rebuild.c
+++ b/lib/rebuild.c
@@ -71,18 +71,27 @@ static struct erofs_dentry *erofs_rebuild_mkdir(struct erofs_inode *dir,
 	return d;
 }
 
+struct erofs_dentry *erofs_d_lookup(struct erofs_inode *dir, const char *name)
+{
+	struct erofs_dentry *d;
+
+	list_for_each_entry(d, &dir->i_subdirs, d_child)
+		if (!strcmp(d->name, name))
+			return d;
+	return NULL;
+}
+
 struct erofs_dentry *erofs_rebuild_get_dentry(struct erofs_inode *pwd,
 		char *path, bool aufs, bool *whout, bool *opq, bool to_head)
 {
 	struct erofs_dentry *d = NULL;
-	unsigned int len = strlen(path);
 	char *s = path;
 
 	*whout = false;
 	*opq = false;
 
-	while (s < path + len) {
-		char *slash = memchr(s, '/', path + len - s);
+	while (1) {
+		char *slash = strchr(s, '/');
 
 		if (slash) {
 			if (s == slash) {
@@ -90,60 +99,54 @@ struct erofs_dentry *erofs_rebuild_get_dentry(struct erofs_inode *pwd,
 				continue;
 			}
 			*slash = '\0';
+		} else if (*s == '\0') {
+			break;
 		}
 
-		if (!memcmp(s, ".", 2)) {
-			/* null */
-		} else if (!memcmp(s, "..", 3)) {
-			pwd = pwd->i_parent;
+		if (__erofs_unlikely(is_dot_dotdot(s))) {
+			if (s[1] == '.') {
+				pwd = pwd->i_parent;
+			}
 		} else {
-			struct erofs_inode *inode = NULL;
-
 			if (aufs && !slash) {
-				if (!memcmp(s, AUFS_WH_DIROPQ, sizeof(AUFS_WH_DIROPQ))) {
+				if (!strcmp(s, AUFS_WH_DIROPQ)) {
 					*opq = true;
 					break;
 				}
-				if (!memcmp(s, AUFS_WH_PFX, sizeof(AUFS_WH_PFX) - 1)) {
+				if (!strcmp(s, AUFS_WH_PFX)) {
 					s += sizeof(AUFS_WH_PFX) - 1;
 					*whout = true;
 				}
 			}
 
-			list_for_each_entry(d, &pwd->i_subdirs, d_child) {
-				if (!strcmp(d->name, s)) {
-					if (d->type != EROFS_FT_DIR && slash)
-						return ERR_PTR(-EIO);
-					inode = d->inode;
-					break;
-				}
-			}
-
-			if (inode) {
-				if (to_head) {
+			d = erofs_d_lookup(pwd, s);
+			if (d) {
+				if (d->type != EROFS_FT_DIR) {
+					if (slash)
+						return ERR_PTR(-ENOTDIR);
+				} else if (to_head) {
 					list_del(&d->d_child);
 					list_add(&d->d_child, &pwd->i_subdirs);
 				}
-				pwd = inode;
-			} else if (!slash) {
-				d = erofs_d_alloc(pwd, s);
+				pwd = d->inode;
+			} else if (slash) {
+				d = erofs_rebuild_mkdir(pwd, s);
 				if (IS_ERR(d))
 					return d;
-				d->type = EROFS_FT_UNKNOWN;
-				d->inode = pwd;
 			} else {
-				d = erofs_rebuild_mkdir(pwd, s);
+				d = erofs_d_alloc(pwd, s);
 				if (IS_ERR(d))
 					return d;
-				pwd = d->inode;
+				d->type = EROFS_FT_UNKNOWN;
+				d->inode = pwd;
 			}
+			pwd = d->inode;
 		}
-		if (slash) {
-			*slash = '/';
-			s = slash + 1;
-		} else {
+
+		if (!slash)
 			break;
-		}
+		*slash = '/';
+		s = slash + 1;
 	}
 	return d;
 }
-- 
2.43.5



More information about the Linux-erofs mailing list