eina_vpath do not pass things through snprintf when not expected.
authorMarcel Hollerbach <mail@marcel-hollerbach.de>
Sat, 27 Apr 2019 09:57:50 +0000 (11:57 +0200)
committerWoochanlee <wc0917.lee@samsung.com>
Tue, 30 Apr 2019 01:03:06 +0000 (10:03 +0900)
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 <dave@gurumeditation.it>
Differential Revision: https://phab.enlightenment.org/D8753

src/lib/eina/eina_vpath.c

index 16c4129..d12541d 100644 (file)
@@ -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);