diff mbox series

[FFmpeg-devel,v2,1/2] avformat/url: fix logic for removing ".." path components

Message ID 20200727121457.7500-1-josef@pex.com
State Superseded
Headers show
Series [FFmpeg-devel,v2,1/2] avformat/url: fix logic for removing ".." path components | expand

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Zlomek, Josef July 27, 2020, 12:14 p.m. UTC
Fixes: 8814

The logic for removing ".." path components and their corresponding
upper directories was reworked.

Now, the function trim_double_dot_url splits the path by "/" into
components, and processes the components one ny one:
- if the component is "..", the last path component in tmp_path is removed
- if the component is not empty, it is added to tmp_path

The duplicate logic was removed from ff_make_absolute_url.

Signed-off-by: Josef Zlomek <josef@pex.com>
---
 libavformat/url.c | 90 ++++++++++++++++++++++-------------------------
 1 file changed, 43 insertions(+), 47 deletions(-)

Comments

Steven Liu July 27, 2020, 1:09 p.m. UTC | #1
Josef Zlomek <josef@pex.com> 于2020年7月27日周一 下午8:15写道:
>
> Fixes: 8814
>
> The logic for removing ".." path components and their corresponding
> upper directories was reworked.
>
> Now, the function trim_double_dot_url splits the path by "/" into
> components, and processes the components one ny one:
> - if the component is "..", the last path component in tmp_path is removed
> - if the component is not empty, it is added to tmp_path
>
> The duplicate logic was removed from ff_make_absolute_url.
>
> Signed-off-by: Josef Zlomek <josef@pex.com>
> ---
>  libavformat/url.c | 90 ++++++++++++++++++++++-------------------------
>  1 file changed, 43 insertions(+), 47 deletions(-)
>
> diff --git a/libavformat/url.c b/libavformat/url.c
> index 20463a6674..343cbca9b9 100644
> --- a/libavformat/url.c
> +++ b/libavformat/url.c
> @@ -83,8 +83,10 @@ static void trim_double_dot_url(char *buf, const char *rel, int size)
>      const char *p = rel;
>      const char *root = rel;
>      char tmp_path[MAX_URL_SIZE] = {0, };
> -    char *sep;
> -    char *node;
> +    int tmp_len = 0;
> +    const char *sep;
> +    const char *next;
> +    int last_is_dir;
>
>      /* Get the path root of the url which start by "://" */
>      if (p && (sep = strstr(p, "://"))) {
> @@ -93,29 +95,45 @@ static void trim_double_dot_url(char *buf, const char *rel, int size)
>          if (!root)
>              return;
>      }
> +    if (*root == '/')
> +        ++root;
> +
> +    /* Split the path by "/" and remove ".." and its corresponding directory. */
> +    last_is_dir = 1;
> +    for (p = root; *p; p = next) {
> +        next = strchr(p, '/');
> +        if (!next) {
> +            next = p + strlen(p);
> +            last_is_dir = 0;
> +        }
>
> -    /* set new current position if the root node is changed */
> -    p = root;
> -    while (p && (node = strstr(p, ".."))) {
> -        av_strlcat(tmp_path, p, node - p + strlen(tmp_path));
> -        p = node + 3;
> -        sep = strrchr(tmp_path, '/');
> -        if (sep)
> -            sep[0] = '\0';
> -        else
> -            tmp_path[0] = '\0';
> -    }
> +        if (next - p == 2 && !strncmp(p, "..", 2)) {
> +            /* remove the last directory from tmp_path */
> +            while (tmp_len > 0 && tmp_path[--tmp_len] != '/')
> +                ;
> +            tmp_path[tmp_len] = '\0';
> +            last_is_dir = 1;
> +        } else if (next > p) {
> +            /* copy the current path component to tmp_path (including '/') */
> +            if (tmp_len) {
> +                av_strlcpy(tmp_path + tmp_len, "/", sizeof(tmp_path) - tmp_len);
> +                ++tmp_len;
> +            }
> +            av_strlcpy(tmp_path + tmp_len, p, FFMIN(sizeof(tmp_path) - tmp_len,
> +                                                    next - p + 1));
> +            tmp_len += next - p;
> +            tmp_path[tmp_len] = '\0';
> +        }
>
> -    if (!av_stristart(p, "/", NULL) && root != rel)
> -        av_strlcat(tmp_path, "/", size);
> +        /* skip "/" */
> +        while (*next == '/')
> +            ++next;
> +    }
> +    if (last_is_dir && tmp_len)
> +        av_strlcpy(tmp_path + tmp_len, "/", sizeof(tmp_path) - tmp_len);
>
> -    av_strlcat(tmp_path, p, size);
>      /* start set buf after temp path process. */
>      av_strlcpy(buf, rel, root - rel + 1);
> -
> -    if (!av_stristart(tmp_path, "/", NULL) && root != rel)
> -        av_strlcat(buf, "/", size);
> -
>      av_strlcat(buf, tmp_path, size);
>  }
>
> @@ -175,14 +193,11 @@ void ff_make_absolute_url(char *buf, int size, const char *base,
>
>      root = p = buf;
>      /* Get the path root of the url which start by "://" */
> -    if (p && strstr(p, "://")) {
> -        sep = strstr(p, "://");
> -        if (sep) {
> -            sep += 3;
> -            root = strchr(sep, '/');
> -            if (!root)
> -                return;
> -        }
> +    if (p && (sep = strstr(p, "://"))) {
> +        sep += 3;
> +        root = strchr(sep, '/');
> +        if (!root)
> +            return;
>      }
>
>      /* Remove the file name from the base url */
> @@ -194,26 +209,7 @@ void ff_make_absolute_url(char *buf, int size, const char *base,
>          sep[1] = '\0';
>      else
>          buf[0] = '\0';
> -    while (av_strstart(rel, "..", NULL) && sep) {
> -        /* Remove the path delimiter at the end */
> -        if (sep > root) {
> -            sep[0] = '\0';
> -            sep = strrchr(buf, '/');
> -        }
>
> -        /* If the next directory name to pop off is "..", break here */
> -        if (!strcmp(sep ? &sep[1] : buf, "..")) {
> -            /* Readd the slash we just removed */
> -            av_strlcat(buf, "/", size);
> -            break;
> -        }
> -        /* Cut off the directory name */
> -        if (sep)
> -            sep[1] = '\0';
> -        else
> -            buf[0] = '\0';
> -        rel += 3;
> -    }
>      av_strlcat(buf, rel, size);
>      trim_double_dot_url(tmp_path, buf, size);
>      memset(buf, 0, size);
> --
> 2.17.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
I have resubmit new patch v3 to the old thread, you can try that.

Thanks
Steven
diff mbox series

Patch

diff --git a/libavformat/url.c b/libavformat/url.c
index 20463a6674..343cbca9b9 100644
--- a/libavformat/url.c
+++ b/libavformat/url.c
@@ -83,8 +83,10 @@  static void trim_double_dot_url(char *buf, const char *rel, int size)
     const char *p = rel;
     const char *root = rel;
     char tmp_path[MAX_URL_SIZE] = {0, };
-    char *sep;
-    char *node;
+    int tmp_len = 0;
+    const char *sep;
+    const char *next;
+    int last_is_dir;
 
     /* Get the path root of the url which start by "://" */
     if (p && (sep = strstr(p, "://"))) {
@@ -93,29 +95,45 @@  static void trim_double_dot_url(char *buf, const char *rel, int size)
         if (!root)
             return;
     }
+    if (*root == '/')
+        ++root;
+
+    /* Split the path by "/" and remove ".." and its corresponding directory. */
+    last_is_dir = 1;
+    for (p = root; *p; p = next) {
+        next = strchr(p, '/');
+        if (!next) {
+            next = p + strlen(p);
+            last_is_dir = 0;
+        }
 
-    /* set new current position if the root node is changed */
-    p = root;
-    while (p && (node = strstr(p, ".."))) {
-        av_strlcat(tmp_path, p, node - p + strlen(tmp_path));
-        p = node + 3;
-        sep = strrchr(tmp_path, '/');
-        if (sep)
-            sep[0] = '\0';
-        else
-            tmp_path[0] = '\0';
-    }
+        if (next - p == 2 && !strncmp(p, "..", 2)) {
+            /* remove the last directory from tmp_path */
+            while (tmp_len > 0 && tmp_path[--tmp_len] != '/')
+                ;
+            tmp_path[tmp_len] = '\0';
+            last_is_dir = 1;
+        } else if (next > p) {
+            /* copy the current path component to tmp_path (including '/') */
+            if (tmp_len) {
+                av_strlcpy(tmp_path + tmp_len, "/", sizeof(tmp_path) - tmp_len);
+                ++tmp_len;
+            }
+            av_strlcpy(tmp_path + tmp_len, p, FFMIN(sizeof(tmp_path) - tmp_len,
+                                                    next - p + 1));
+            tmp_len += next - p;
+            tmp_path[tmp_len] = '\0';
+        }
 
-    if (!av_stristart(p, "/", NULL) && root != rel)
-        av_strlcat(tmp_path, "/", size);
+        /* skip "/" */
+        while (*next == '/')
+            ++next;
+    }
+    if (last_is_dir && tmp_len)
+        av_strlcpy(tmp_path + tmp_len, "/", sizeof(tmp_path) - tmp_len);
 
-    av_strlcat(tmp_path, p, size);
     /* start set buf after temp path process. */
     av_strlcpy(buf, rel, root - rel + 1);
-
-    if (!av_stristart(tmp_path, "/", NULL) && root != rel)
-        av_strlcat(buf, "/", size);
-
     av_strlcat(buf, tmp_path, size);
 }
 
@@ -175,14 +193,11 @@  void ff_make_absolute_url(char *buf, int size, const char *base,
 
     root = p = buf;
     /* Get the path root of the url which start by "://" */
-    if (p && strstr(p, "://")) {
-        sep = strstr(p, "://");
-        if (sep) {
-            sep += 3;
-            root = strchr(sep, '/');
-            if (!root)
-                return;
-        }
+    if (p && (sep = strstr(p, "://"))) {
+        sep += 3;
+        root = strchr(sep, '/');
+        if (!root)
+            return;
     }
 
     /* Remove the file name from the base url */
@@ -194,26 +209,7 @@  void ff_make_absolute_url(char *buf, int size, const char *base,
         sep[1] = '\0';
     else
         buf[0] = '\0';
-    while (av_strstart(rel, "..", NULL) && sep) {
-        /* Remove the path delimiter at the end */
-        if (sep > root) {
-            sep[0] = '\0';
-            sep = strrchr(buf, '/');
-        }
 
-        /* If the next directory name to pop off is "..", break here */
-        if (!strcmp(sep ? &sep[1] : buf, "..")) {
-            /* Readd the slash we just removed */
-            av_strlcat(buf, "/", size);
-            break;
-        }
-        /* Cut off the directory name */
-        if (sep)
-            sep[1] = '\0';
-        else
-            buf[0] = '\0';
-        rel += 3;
-    }
     av_strlcat(buf, rel, size);
     trim_double_dot_url(tmp_path, buf, size);
     memset(buf, 0, size);