From 0bc9c6fc7af7e7f053dbc27582bc95017c2a6b03 Mon Sep 17 00:00:00 2001 From: "S.J.R. van Schaik" Date: Sun, 11 Jun 2017 16:26:48 +0200 Subject: [PATCH] mufs: add mufs_abspath() to sanitise paths --- source/fs/mufs/dir.c | 74 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/source/fs/mufs/dir.c b/source/fs/mufs/dir.c index b75a35e..7cbdde3 100644 --- a/source/fs/mufs/dir.c +++ b/source/fs/mufs/dir.c @@ -17,6 +17,54 @@ struct mufs_dir { uint32_t va; }; +static char *mufs_abspath(const char *path) +{ + char *s, *p, *next, *prev; + + if (!(s = malloc(strlen(path) + 2))) + return NULL; + + strcpy(s, path); + + for (p = s, next = p + strcspn(p, "/"); *p != '\0'; next = p + strcspn(p, "/")) { + char c = *next; + + *next = '\0'; + + if (*p == '\0' || strcmp(p, ".") == 0) { + memmove(p, next + 1, strlen(next + 1) + 1); + continue; + } + + if (strcmp(p, "..") == 0) { + if (!(prev = strrchr(s, '/'))) { + memmove(p, next + 1, strlen(next + 1) + 1); + continue; + } + + *prev = '\0'; + + if (!(prev = strrchr(s, '/'))) { + memmove(s, next + 1, strlen(next + 1) + 1); + p = s; + continue; + } + + memmove(prev + 1, next + 1, strlen(next + 1) + 1); + p = prev + 1; + continue; + } + + *next = c; + p = next + 1; + } + + memmove(s + 1, s, strlen(s) + 1); + *s = '/'; + + return s; +} + static struct mufs_dir *mufs_opendir2(struct mufs *fs, struct mufs_dirent *entry) { struct mufs_dir *dir; @@ -54,22 +102,19 @@ static struct mufs_tree *resolve_path(struct mufs *fs, const char *path) if (!path || *path == '\0') return NULL; - while (*path == '/') - ++path; + if (!(s = mufs_abspath(path))) + return NULL; - if (*path == '\0') + if (strcmp(s, "/") == 0) return &fs->root; - if (!(s = strdup(path))) - return NULL; - if (!(dir = mufs_opendir2(fs, NULL))) goto err_free_s; - for (p = s; *p != '\0'; p = end) { + for (p = s + 1; *p != '\0'; p = end) { end = p + strcspn(p, "/"); - while (*end == '/') + if (*end == '/') *end++ = '\0'; while ((ret = mufs_readdir(dir, &entry)) == 0) { @@ -250,15 +295,14 @@ int mufs_mkdir(struct mufs *fs, const char *path) if (!path || *path == '\0') return -1; + if (!(s = mufs_abspath(path))) + return -1; + /* TODO: already exists. */ - if (resolve_path(fs, path)) + if (resolve_path(fs, s)) { + free(s); return 0; - - while (*path == '/') - ++path; - - if (!(s = strdup(path))) - return -1; + } if (!(name = strrchr(s, '/'))) { name = s;