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

2020-07-27 Thread Steven Liu
Josef Zlomek  于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 
> ---
>  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 ? [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);
>  

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

2020-07-27 Thread Josef Zlomek
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 
---
 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 ? [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-requ...@ffmpeg.org with subject "unsubscribe".