[FFmpeg-devel] [PATCH v3 1/2] avformat/url: fix logic for removing ".." path components
Josef Zlomek
josef at pex.com
Tue Jul 28 07:10:57 EEST 2020
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 output buffer is removed
- if the component is not empty, it is added to the output buffer
No temporary buffers are used anymore.
Also the path containing no '/' after '://' is returned as it is.
The duplicate logic was removed from ff_make_absolute_url.
Signed-off-by: Josef Zlomek <josef at pex.com>
---
libavformat/url.c | 101 +++++++++++++++++++++++-----------------------
1 file changed, 50 insertions(+), 51 deletions(-)
diff --git a/libavformat/url.c b/libavformat/url.c
index 20463a6674..46a08e88e3 100644
--- a/libavformat/url.c
+++ b/libavformat/url.c
@@ -82,41 +82,62 @@ 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;
+ char *dst;
+ int dst_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, "://"))) {
sep += 3;
root = strchr(sep, '/');
- if (!root)
+ if (!root) {
+ av_strlcpy(buf, rel, size);
return;
+ }
}
+ if (*root == '/')
+ ++root;
- /* 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 (!av_stristart(p, "/", NULL) && root != rel)
- av_strlcat(tmp_path, "/", size);
-
- av_strlcat(tmp_path, p, size);
- /* start set buf after temp path process. */
+ /* Copy the root to the output buffer */
av_strlcpy(buf, rel, root - rel + 1);
+ size -= root - rel;
+ dst = &buf[root - rel];
+
+ /* 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;
+ }
- if (!av_stristart(tmp_path, "/", NULL) && root != rel)
- av_strlcat(buf, "/", size);
+ if (next - p == 2 && !strncmp(p, "..", 2)) {
+ /* remove the last directory from dst */
+ while (dst_len > 0 && dst[--dst_len] != '/')
+ ;
+ dst[dst_len] = '\0';
+ last_is_dir = 1;
+ } else if (next > p) {
+ int len_including_zero;
+ /* copy the current path component to dst (including '/') */
+ if (dst_len) {
+ av_strlcpy(dst + dst_len, "/", size - dst_len);
+ ++dst_len;
+ }
+ len_including_zero = FFMIN(size - dst_len, next - p + 1);
+ av_strlcpy(dst + dst_len, p, len_including_zero);
+ dst_len += len_including_zero - 1;
+ }
- av_strlcat(buf, tmp_path, size);
+ /* skip "/" */
+ while (*next == '/')
+ ++next;
+ }
+ if (last_is_dir && dst_len)
+ av_strlcpy(dst + dst_len, "/", size - dst_len);
}
void ff_make_absolute_url(char *buf, int size, const char *base,
@@ -175,14 +196,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 +212,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
More information about the ffmpeg-devel
mailing list