From afbc36cf86c59f2f0d97775c019ef37c103ad3a6 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Sat, 27 Apr 2019 11:57:50 +0200 Subject: [PATCH] eina_vpath do not pass things through snprintf when not expected. lets assume a user passes in a string like "blabla%dehydra" then %d will be resolved by snprintf. Which is probebly not what we want. This resolves this case and ensures that eina_vpath_resolve does not get piped through snprintf Reviewed-by: Dave Andreoli Differential Revision: https://phab.enlightenment.org/D8753 --- src/lib/eina/eina_vpath.c | 177 ++++++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 83 deletions(-) diff --git a/src/lib/eina/eina_vpath.c b/src/lib/eina/eina_vpath.c index 16c4129..d12541d 100644 --- a/src/lib/eina/eina_vpath.c +++ b/src/lib/eina/eina_vpath.c @@ -234,37 +234,9 @@ _fetch_user_homedir(char **str, const char *name, const char *error) #endif } - -EAPI char * -eina_vpath_resolve(const char* path) -{ - char buf[PATH_MAX]; - - if (eina_vpath_resolve_snprintf(buf, sizeof(buf), path) > 0) - return strdup(buf); - return NULL; -} - -EAPI int -eina_vpath_resolve_snprintf(char *str, size_t size, const char *format, ...) +static int +_eina_vpath_resolve(const char *path, char *str, size_t size) { - va_list args; - char *path; - // XXX: implement parse of path then look up in hash if not just create - // object where path and result are the same and return that with - // path set and result set to resolved path - return obj handler calls - // "do" on object to get the result inside fetched or failed callback. - // if it's a url then we need a new classs that overrides the do and - // begins a fetch and on finish calls the event cb or when wait is called - /* FIXME: not working for WIndows */ - // /* <- full path - - path = alloca(size + 1); - - va_start(args, format); - vsnprintf(path, size, format, args); - va_end(args); - if (path[0] == '~') { char *home = NULL; @@ -277,7 +249,8 @@ eina_vpath_resolve_snprintf(char *str, size_t size, const char *format, ...) // ~username/ <- homedir of user "username" else { - char *p, *name; + const char *p; + char *name; for (p = path + 1; *p; p++) { @@ -295,60 +268,98 @@ eina_vpath_resolve_snprintf(char *str, size_t size, const char *format, ...) { return snprintf(str, size, "%s%s", home, path); } - } - // (:xxx:)/* ... <- meta hash table - else if ((path[0] == '(') && (path[1] == ':')) - { - const char *p, *end, *meta; - char *name; - int max_len = strlen(path); - Eina_Bool found = EINA_FALSE; - - for (p = path + 2; p <= path + max_len - 2; p++) - { - if ((p[0] ==':') && (p[1] == ')')) - { - end = p; - found = EINA_TRUE; - break; - } - } - p += 2; - - if (!found) - { - ERR("(: Needs to have a matching ':)'\nThe string was: %s", path); - return 0; - } - - if (*p != '/') - { - ERR("A / is expected after :)\nThe string was: %s", path); - return 0; - } - - if (found) - { - name = alloca(end - path); - strncpy(name, path + 2, end - path - 2); - name[end - path - 2] = 0; - meta = _eina_vpath_data_get(name); - if (meta) - { - return snprintf(str, size, "%s%s", meta, end + 2); - } - else - { - ERR("Meta key '%s' was not registered!\nThe string was: %s", name, path); - return 0; - } - } - } + } + // (:xxx:)/* ... <- meta hash table + else if ((path[0] == '(') && (path[1] == ':')) + { + const char *p, *end, *meta; + char *name; + int max_len = strlen(path); + Eina_Bool found = EINA_FALSE; + + for (p = path + 2; p <= path + max_len - 2; p++) + { + if ((p[0] ==':') && (p[1] == ')')) + { + end = p; + found = EINA_TRUE; + break; + } + } + p += 2; + + if (!found) + { + ERR("(: Needs to have a matching ':)'\nThe string was: %s", path); + return 0; + } + + if (*p != '/') + { + ERR("A / is expected after :)\nThe string was: %s", path); + return 0; + } + + if (found) + { + name = alloca(end - path); + strncpy(name, path + 2, end - path - 2); + name[end - path - 2] = 0; + meta = _eina_vpath_data_get(name); + if (meta) + { + return snprintf(str, size, "%s%s", meta, end + 2); + } + else + { + ERR("Meta key '%s' was not registered!\nThe string was: %s", name, path); + return 0; + } + } + } //just return the path, since we assume that this is a normal path else - { - return snprintf(str, size, "%s", path); - } + { + return snprintf(str, size, "%s", path); + } + str[0] = '\0'; + return 0; +} + +EAPI char * +eina_vpath_resolve(const char* path) +{ + char buf[PATH_MAX]; + + if (_eina_vpath_resolve(path, buf, sizeof(buf)) > 0) + return strdup(buf); + return NULL; +} + +EAPI int +eina_vpath_resolve_snprintf(char *str, size_t size, const char *format, ...) +{ + va_list args; + char *path; + int r; + + // XXX: implement parse of path then look up in hash if not just create + // object where path and result are the same and return that with + // path set and result set to resolved path - return obj handler calls + // "do" on object to get the result inside fetched or failed callback. + // if it's a url then we need a new classs that overrides the do and + // begins a fetch and on finish calls the event cb or when wait is called + /* FIXME: not working for WIndows */ + // /* <- full path + + path = alloca(size + 1); + + va_start(args, format); + vsnprintf(path, size, format, args); + va_end(args); + + r = _eina_vpath_resolve(path, str, size); + if (r > 0) return r; ERR("The path has to start with either '~/' or '(:NAME:)/' or be a normal path \nThe string was: %s", path); -- 2.7.4