Re: [FFmpeg-devel] [PATCH v2 1/2] avformat/url: fix logic for removing ".." path components
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
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".