Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
On Thu, Jan 04, 2018 at 00:42:43 +, Colin NG wrote: > @@ -1315,6 +1426,7 @@ static int read_from_url(struct representation *pls, > struct fragment *seg, > } else { > ret = avio_read(pls->input, buf, buf_size); > } > + > if (ret > 0) > pls->cur_seg_offset += ret; > Spurious change. Moritz ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
> On 4 Jan 2018, at 08:42, Colin NG wrote: > > - Add function 'resolve_content_path' to propagate the baseURL from upper > level nodes. > * if no baseURL is available, the path of mpd file will be set as the baseURL. > - Remove checking for newly established connection. > - Establish the communication protocol in each connection rather than > applying one protocol to all connection. > --- > libavformat/dashdec.c | 126 -- > 1 file changed, 113 insertions(+), 13 deletions(-) > > diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c > index 3798649..5345f91 100644 > --- a/libavformat/dashdec.c > +++ b/libavformat/dashdec.c > @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) > return av_gettime() / 100; > } > > +static int ishttp(char *url) { > +const char *proto_name = avio_find_protocol_name(url); > +return av_strstart(proto_name, "http", NULL); > +} > + > static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char > *datetime) > { > struct tm timeinfo; > @@ -392,7 +397,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, > const char *url, > else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) > return AVERROR_INVALIDDATA; > > -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); > +av_freep(pb); > +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); > if (ret >= 0) { > // update cookies on http response with setcookies. > char *new_cookies = NULL; > @@ -639,6 +645,103 @@ static int > parse_manifest_segmenttimeline(AVFormatContext *s, struct representat > return 0; > } > > +static int resolve_content_path(AVFormatContext *s, const char *url, > xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { > + > +char *tmp_str = NULL; > +char *path = NULL; > +char *mpdName = NULL; > +xmlNodePtr node = NULL; > +char *baseurl = NULL; > +char *root_url = NULL; > +char *text = NULL; > + > +int isRootHttp = 0; > +char token ='/'; > +int start = 0; > +int rootId = 0; > +int updated = 0; > +int size = 0; > +int i; > +int max_url_size = strlen(url); > + > +for (i = n_baseurl_nodes-1; i >= 0 ; i--) { > +text = xmlNodeGetContent(baseurl_nodes[i]); > +if (!text) > +continue; > +max_url_size += strlen(text); > +if (ishttp(text)) { > +xmlFree(text); > +break; > +} > +xmlFree(text); > +} > + > +text = av_mallocz(max_url_size); > +if (!text) { > +updated = AVERROR(ENOMEM); > +goto end; > +} > +av_strlcpy(text, url, strlen(url)+1); > +while (mpdName = av_strtok(text, "/", &text)) { > +size = strlen(mpdName); > +} > + > +path = av_mallocz(max_url_size); > +tmp_str = av_mallocz(max_url_size); > +if (!tmp_str || !path) { > +updated = AVERROR(ENOMEM); > +goto end; > +} > + > +av_strlcpy (path, url, strlen(url) - size + 1); > +for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) { > +if (!(node = baseurl_nodes[rootId])) { > +continue; > +} > +if (ishttp(xmlNodeGetContent(node))) { > +break; > +} > +} > + > +node = baseurl_nodes[rootId]; > +baseurl = xmlNodeGetContent(node); > +root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path; > +if (node) { > +xmlNodeSetContent(node, root_url); > +} > + > +size = strlen(root_url); > +isRootHttp = ishttp(root_url); > + > +if (root_url[size - 1] != token) { > +av_strlcat(root_url, "/", size + 2); > +size += 2; > +} > + > +for (i = 0; i < n_baseurl_nodes; ++i) { > +if (i == rootId) { > +continue; > +} > +text = xmlNodeGetContent(baseurl_nodes[i]); > +if (text) { > +memset(tmp_str, 0, strlen(tmp_str)); > +if (!ishttp(text) && isRootHttp) { > +av_strlcpy(tmp_str, root_url, size + 1); > +} > +start = (text[0] == token); > +av_strlcat(tmp_str, text + start, max_url_size); > +xmlNodeSetContent(baseurl_nodes[i], tmp_str); > +updated = 1; > +xmlFree(text); > +} > +} > + > +end: > +av_free(path); > +av_free(tmp_str); > +return updated; > + > +} > static int parse_manifest_representation(AVFormatContext *s, const char *url, > xmlNodePtr node, > xmlNodePtr adaptionset_node, > @@ -698,6 +801,11 @@ static int parse_manifest_representation(AVFormatContext > *s, const char *url, > baseurl_nodes[2] = adaptionset_baseurl_node; > baseurl_nodes[3] = representation_baseurl_node; > > +ret = resolve_content_path(s, url, baseurl_nodes, 4); > +if (ret == AVERROR(ENOMEM)
[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
- Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is available, the path of mpd file will be set as the baseURL. - Remove checking for newly established connection. - Establish the communication protocol in each connection rather than applying one protocol to all connection. --- libavformat/dashdec.c | 126 -- 1 file changed, 113 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 3798649..5345f91 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) return av_gettime() / 100; } +static int ishttp(char *url) { +const char *proto_name = avio_find_protocol_name(url); +return av_strstart(proto_name, "http", NULL); +} + static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char *datetime) { struct tm timeinfo; @@ -392,7 +397,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); +av_freep(pb); +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); if (ret >= 0) { // update cookies on http response with setcookies. char *new_cookies = NULL; @@ -639,6 +645,103 @@ static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representat return 0; } +static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { + +char *tmp_str = NULL; +char *path = NULL; +char *mpdName = NULL; +xmlNodePtr node = NULL; +char *baseurl = NULL; +char *root_url = NULL; +char *text = NULL; + +int isRootHttp = 0; +char token ='/'; +int start = 0; +int rootId = 0; +int updated = 0; +int size = 0; +int i; +int max_url_size = strlen(url); + +for (i = n_baseurl_nodes-1; i >= 0 ; i--) { +text = xmlNodeGetContent(baseurl_nodes[i]); +if (!text) +continue; +max_url_size += strlen(text); +if (ishttp(text)) { +xmlFree(text); +break; +} +xmlFree(text); +} + +text = av_mallocz(max_url_size); +if (!text) { +updated = AVERROR(ENOMEM); +goto end; +} +av_strlcpy(text, url, strlen(url)+1); +while (mpdName = av_strtok(text, "/", &text)) { +size = strlen(mpdName); +} + +path = av_mallocz(max_url_size); +tmp_str = av_mallocz(max_url_size); +if (!tmp_str || !path) { +updated = AVERROR(ENOMEM); +goto end; +} + +av_strlcpy (path, url, strlen(url) - size + 1); +for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) { +if (!(node = baseurl_nodes[rootId])) { +continue; +} +if (ishttp(xmlNodeGetContent(node))) { +break; +} +} + +node = baseurl_nodes[rootId]; +baseurl = xmlNodeGetContent(node); +root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path; +if (node) { +xmlNodeSetContent(node, root_url); +} + +size = strlen(root_url); +isRootHttp = ishttp(root_url); + +if (root_url[size - 1] != token) { +av_strlcat(root_url, "/", size + 2); +size += 2; +} + +for (i = 0; i < n_baseurl_nodes; ++i) { +if (i == rootId) { +continue; +} +text = xmlNodeGetContent(baseurl_nodes[i]); +if (text) { +memset(tmp_str, 0, strlen(tmp_str)); +if (!ishttp(text) && isRootHttp) { +av_strlcpy(tmp_str, root_url, size + 1); +} +start = (text[0] == token); +av_strlcat(tmp_str, text + start, max_url_size); +xmlNodeSetContent(baseurl_nodes[i], tmp_str); +updated = 1; +xmlFree(text); +} +} + +end: +av_free(path); +av_free(tmp_str); +return updated; + +} static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr node, xmlNodePtr adaptionset_node, @@ -698,6 +801,11 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; +ret = resolve_content_path(s, url, baseurl_nodes, 4); +if (ret == AVERROR(ENOMEM) || ret == 0) { +goto end; +} + if (representation_segmenttemplate_node || fragment_template_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; @@ -993,6 +1101,9 @@ static int parse_manifest(AVFormatContext *s, const ch
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
tis 2017-12-26 klockan 01:12 + skrev Colin NG: > +static int resolve_content_path(AVFormatContext *s, const char *url, > xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { > + > +char *tmp_str = av_mallocz(MAX_URL_SIZE); > +char *path = av_mallocz(MAX_URL_SIZE); > +char *mpdName = NULL; > +xmlNodePtr node = NULL; > +char *baseurl = NULL; > +char *root_url = NULL; > +char *text = NULL; > + > +int isRootHttp = 0; > +char token ='/'; > +int start = 0; > +int rootId = 0; > +int updated = 0; > +int size = 0; > +int i; > + > +if (!tmp_str || !path) { > +updated = AVERROR(ENOMEM); > +goto end; > +} > + > +av_strlcpy(tmp_str, url, strlen(url) + 1); MAX_URL_SIZE maybe? Is there some way url can be too long? > +mpdName = strtok (tmp_str, "/"); > +while (mpdName = strtok (NULL, "/")) { > +size = strlen(mpdName); > +} strtok() isn't thread safe. I forget if we guarantee thread safeness at this stage in lavf > + > +av_strlcpy (path, url, strlen(url) - size + 1); Similarly here. Plus strlen(url) being computed again > +for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) { > +if (!(node = baseurl_nodes[rootId])) { > +continue; > +} > +if (ishttp(xmlNodeGetContent(node))) { > +break; > +} > +} > + > +node = baseurl_nodes[rootId]; > +baseurl = xmlNodeGetContent(node); > +root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path; > +if (node) { > +xmlNodeSetContent(node, root_url); > +} > + > +size = strlen(root_url); > +isRootHttp = ishttp(root_url); > + > +if (root_url[size - 1] == token) { > +av_strlcat(root_url, "/", size + 2); > +size += 2; > +} > + > +for (i = 0; i < n_baseurl_nodes; ++i) { > +if (i == rootId) { > +continue; > +} > +text = xmlNodeGetContent(baseurl_nodes[i]); > +if (text) { > +memset(tmp_str, 0, strlen(tmp_str)); > +if (!ishttp(text) && isRootHttp) { > +av_strlcpy(tmp_str, root_url, size + 1); > +} > +start = (text[0] == token); > +av_strlcat(tmp_str, text + start, MAX_URL_SIZE); > +xmlNodeSetContent(baseurl_nodes[i], tmp_str); > +updated = 1; > +xmlFree(text); > +} > +} > + > +end: > +av_free(path); > +av_free(tmp_str); > +return updated; > + > +} I don't really like lavf doing URL parsing/manipulation like this when there's (supposedly) mature libraries to do it. Especially after this year's Blackhat revelations of exploits making use of how whitespace, unicode, slashes, percent encoding etc are handled differently in every library [1]. But I'm also not familiar with DASH so can't say what would be the typical thing to do /Tomas [1] https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-O f-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf signature.asc Description: This is a digitally signed message part ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
- Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is available, the path of mpd file will be set as the baseURL. - Remove checking for newly established connection. - Establish the communication protocol in each connection rather than applying one protocol to all connection. --- libavformat/dashdec.c | 107 -- 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 3798649..e41ba96 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) return av_gettime() / 100; } +static int ishttp(char *url) { +const char *proto_name = avio_find_protocol_name(url); +return av_strstart(proto_name, "http", NULL); +} + static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char *datetime) { struct tm timeinfo; @@ -392,7 +397,8 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); +av_freep(pb); +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); if (ret >= 0) { // update cookies on http response with setcookies. char *new_cookies = NULL; @@ -639,6 +645,84 @@ static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representat return 0; } +static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { + +char *tmp_str = av_mallocz(MAX_URL_SIZE); +char *path = av_mallocz(MAX_URL_SIZE); +char *mpdName = NULL; +xmlNodePtr node = NULL; +char *baseurl = NULL; +char *root_url = NULL; +char *text = NULL; + +int isRootHttp = 0; +char token ='/'; +int start = 0; +int rootId = 0; +int updated = 0; +int size = 0; +int i; + +if (!tmp_str || !path) { +updated = AVERROR(ENOMEM); +goto end; +} + +av_strlcpy(tmp_str, url, strlen(url) + 1); +mpdName = strtok (tmp_str, "/"); +while (mpdName = strtok (NULL, "/")) { +size = strlen(mpdName); +} + +av_strlcpy (path, url, strlen(url) - size + 1); +for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId --) { +if (!(node = baseurl_nodes[rootId])) { +continue; +} +if (ishttp(xmlNodeGetContent(node))) { +break; +} +} + +node = baseurl_nodes[rootId]; +baseurl = xmlNodeGetContent(node); +root_url = (av_strcasecmp(baseurl, "")) ? baseurl : path; +if (node) { +xmlNodeSetContent(node, root_url); +} + +size = strlen(root_url); +isRootHttp = ishttp(root_url); + +if (root_url[size - 1] == token) { +av_strlcat(root_url, "/", size + 2); +size += 2; +} + +for (i = 0; i < n_baseurl_nodes; ++i) { +if (i == rootId) { +continue; +} +text = xmlNodeGetContent(baseurl_nodes[i]); +if (text) { +memset(tmp_str, 0, strlen(tmp_str)); +if (!ishttp(text) && isRootHttp) { +av_strlcpy(tmp_str, root_url, size + 1); +} +start = (text[0] == token); +av_strlcat(tmp_str, text + start, MAX_URL_SIZE); +xmlNodeSetContent(baseurl_nodes[i], tmp_str); +updated = 1; +xmlFree(text); +} +} + +end: +av_free(path); +av_free(tmp_str); +return updated; + +} static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr node, xmlNodePtr adaptionset_node, @@ -698,6 +782,11 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; +ret = resolve_content_path(s, url, baseurl_nodes, 4); +if (ret == AVERROR(ENOMEM) || ret == 0) { +goto end; +} + if (representation_segmenttemplate_node || fragment_template_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; @@ -993,6 +1082,9 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) } mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); +if (!mpd_baseurl_node) { +mpd_baseurl_node = xmlNewNode(NULL, "BaseURL"); +} // at now we can handle only one period, with the longest duration node = xmlFirstElementChild(node); @@ -1315,6 +1407,7 @@ static int read_from_url(struct representation *pls, struct fragment *seg, } else { ret = av
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is av
On Sat, Dec 23, 2017 at 21:47:05 +, Colin NG wrote: > Subject: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 > (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate > the baseURL from upper level > nodes. * if no baseURL is available, the path of mpd file will be set > as the baseURL. - Remove chec... In the commit message, you need to separate the subsequent lines from the first line with an empty line, otherwise everything gets wrapped into one subject line. > +static int resolve_content_path(AVFormatContext *s, const char *url, > xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { ffmpeg functions have their opening bracket on the first column of a new line. > +av_strlcpy (path, url, strlen(url) - size + 1); [...] > +root_url = (av_strcasecmp(baseurl, ""))? baseurl: path; [...] > +if (root_url[size-1]==token) { > +av_strlcat(root_url, "/", size+2); > +size+=2; There are still quite a few style issues in your code. Have a look at the ffmpeg contribution info for details: https://ffmpeg.org/developer.html#Code-formatting-conventions The operators "?" and ":" also need to be surrounded by whitespace, as do "==", "+", "+=", and so on. On the other hand, the function name such as av_strlcpy isn't separated by a space from its bracket. > +start = (text[0] == token) ? 1: 0; start = (text[0] == token); is sufficient. Moritz ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is av
On Sat, Dec 23, 2017 at 09:47:05PM +, Colin NG wrote: > --- > libavformat/dashdec.c | 110 > -- > 1 file changed, 97 insertions(+), 13 deletions(-) seems my git doesnt like this patch: Applying: libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is available, the path of mpd file will be set as the baseURL. - Remove che... error: corrupt patch at line 20 error: could not build fake ancestor Patch failed at 0001 libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is available, the path of mpd file will be set as the baseURL. - Remove che... The copy of the patch that failed is found in: .git/rebase-apply/patch When you have resolved this problem, run "git am --continue". If you prefer to skip this patch, run "git am --skip" instead. To restore the original branch and stop patching, run "git am --abort". [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB "You are 36 times more likely to die in a bathtub than at the hands of a terrorist. Also, you are 2.5 times more likely to become a president and 2 times more likely to become an astronaut, than to die in a terrorist attack." -- Thoughty2 signature.asc Description: PGP signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is availa
--- libavformat/dashdec.c | 110 -- 1 file changed, 97 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 3798649..6574e56 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) return av_gettime() / 100; } +static int ishttp(char *url) { +const char *proto_name = avio_find_protocol_name(url); +return av_strstart(proto_name, "http", NULL); +} static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char *datetime) { struct tm timeinfo; @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); +av_freep(pb); +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); if (ret >= 0) { // update cookies on http response with setcookies. char *new_cookies = NULL; @@ -639,6 +646,85 @@ static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representat return 0; } +static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { + +char *tmp_str = av_mallocz(MAX_URL_SIZE); +char *path = av_mallocz(MAX_URL_SIZE); +char *mpdName = NULL; +xmlNodePtr node = NULL; +char *baseurl = NULL; +char *root_url = NULL; +char *text = NULL; + +int isRootHttp = 0; +char token ='/'; +int start = 0; +int rootId = 0; +int updated = 0; +int size = 0; +int i; + +if (!tmp_str || !path) { +updated = AVERROR(ENOMEM); +goto end; +} + +av_strlcpy(tmp_str, url, strlen(url) + 1); +mpdName = strtok (tmp_str, "/"); +while (mpdName = strtok (NULL, "/")) { +size = strlen(mpdName); +} + +av_strlcpy (path, url, strlen(url) - size + 1); + +for (rootId = n_baseurl_nodes - 1; rootId > 0; rootId--) { +if (!(node = baseurl_nodes[rootId])) { +continue; +} +if (ishttp(xmlNodeGetContent(node))) { +break; +} +} + +node = baseurl_nodes[rootId]; +baseurl = xmlNodeGetContent(node); +root_url = (av_strcasecmp(baseurl, ""))? baseurl: path; +if (node) { +xmlNodeSetContent(node, root_url); +} + +size = strlen(root_url); +isRootHttp= ishttp(root_url); + +if (root_url[size-1]==token) { +av_strlcat(root_url, "/", size+2); +size+=2; +} + +for (i = 0; i < n_baseurl_nodes; ++i) { +if (i == rootId) { +continue; +} +text = xmlNodeGetContent(baseurl_nodes[i]); +if (text) { +memset(tmp_str, 0, strlen(tmp_str)); +if (!ishttp(text) && isRootHttp) { +av_strlcpy(tmp_str, root_url, size + 1); +} +start = (text[0] == token) ? 1: 0; +av_strlcat(tmp_str, text + start, MAX_URL_SIZE); +xmlNodeSetContent(baseurl_nodes[i], tmp_str); +updated = 1; +xmlFree(text); +} +} + +end: +av_free(path); +av_free(tmp_str); +return updated; + +} static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr node, xmlNodePtr adaptionset_node, @@ -698,6 +784,12 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; +ret = resolve_content_path(s, url, baseurl_nodes, 4); +if (ret == AVERROR(ENOMEM) || ret == 0) { +goto end; +} + if (representation_segmenttemplate_node || fragment_template_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; @@ -993,6 +1085,9 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) } mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); +if (!mpd_baseurl_node) { +mpd_baseurl_node = xmlNewNode(NULL, "BaseURL"); +} // at now we can handle only one period, with the longest duration node = xmlFirstElementChild(node); @@ -1315,6 +1410,7 @@ static int read_from_url(struct representation *pls, struct fragment *seg, } else { ret = avio_read(pls->input, buf, buf_size); } if (ret > 0) pls->cur_seg_offset += ret; @@ -1343,18 +1439,6 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen goto cleanup; } -/* Seek to the requested position. If this was a HTTP request, the offset - * should alre
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is av
> On 21 Dec 2017, at 10:39, Colin NG wrote: > > --- > libavformat/dashdec.c | 116 -- > 1 file changed, 103 insertions(+), 13 deletions(-) > > diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c > index 3798649..cdb9f67 100644 > --- a/libavformat/dashdec.c > +++ b/libavformat/dashdec.c > @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) > return av_gettime() / 100; > } > > +static int ishttp(char *url) { > +const char *proto_name = avio_find_protocol_name(url); > +return av_strstart(proto_name, "http", NULL); > +} > + > static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char > *datetime) > { > struct tm timeinfo; > @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, > const char *url, > else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) > return AVERROR_INVALIDDATA; > > -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); > +av_freep(pb); > +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); > + > if (ret >= 0) { > // update cookies on http response with setcookies. > char *new_cookies = NULL; > @@ -639,6 +646,91 @@ static int > parse_manifest_segmenttimeline(AVFormatContext *s, struct representat > return 0; > } > > +static int resolve_content_path(AVFormatContext *s, const char *url, > xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { > + > +char *tmp_str = av_mallocz(MAX_URL_SIZE); > +char *tmp_str_2= av_mallocz(MAX_URL_SIZE); > +char *path = av_mallocz(MAX_URL_SIZE); > +char *mpdName = NULL; > +xmlNodePtr node = NULL; > +char *baseurl = NULL; > +char *root_url = NULL; > +char *text = NULL; > + > +int isRootHttp = 0; > +char token ='/'; > +int start = 0; > +int rootId = 0; > +int updated = 0; > +int size = 0; > +int i; > + > +if (!tmp_str || !tmp_str_2 || !path) { > +updated = AVERROR(ENOMEM); > +goto end; > +} > + > +av_strlcpy(tmp_str, url, strlen(url)+1); space code style > +mpdName = strtok (tmp_str," /"); > + > +while ((mpdName =strtok (NULL, "/"))) { > +size = strlen(mpdName); > +} > + > +av_strlcpy (path, url, strlen(url)-size+1); strlen(url) - size + 1; *space code style*, > + > +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) { > +if (!(node = baseurl_nodes[rootId])) { > +continue; > +} > +if (ishttp(xmlNodeGetContent(node))) { > +break; > +} > +} > + > +node = baseurl_nodes[rootId]; > +baseurl = xmlNodeGetContent(node); > +root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl; root_url = av_strcasecmp(baseurl, “") ? baseurl : path; > + > +if (node) { > +xmlNodeSetContent(node, root_url); > +} > + > +size = strlen(root_url); > +isRootHttp= ishttp(root_url); > + > +if (root_url[size-1]==token) { if (root_url[size - 1] == token) { > +av_strlcat(root_url, "/", size+2); > +size+=2; av_strlcat(root_url, “/“, size + 2); size += 2; > +} > + > +for (i = 0; i < n_baseurl_nodes; ++i) { > +if (i==rootId) { i == rootId > +continue; > +} > +text = xmlNodeGetContent(baseurl_nodes[i]); > +if (text) { > +memset(tmp_str, 0, strlen(tmp_str)); this line maybe no need, because you have use av_mallocz, that can memset the tmp_str to 0; > + > +if (!ishttp(text) && isRootHttp) { > +av_strlcpy(tmp_str, root_url, size+1); > +} > +start = (text[0]==token) ? 1: 0; > +memset(tmp_str_2, 0, strlen(tmp_str_2)); ditto. > +av_strlcat(tmp_str, text+start, MAX_URL_SIZE); > +xmlNodeSetContent(baseurl_nodes[i], tmp_str); > +updated = 1; > +xmlFree(text); > +} > +} > + > +end: > +av_free(path); > +av_free(tmp_str); > +av_free(tmp_str_2); > +return updated; > + > +} > static int parse_manifest_representation(AVFormatContext *s, const char *url, > xmlNodePtr node, > xmlNodePtr adaptionset_node, > @@ -698,6 +790,12 @@ static int parse_manifest_representation(AVFormatContext > *s, const char *url, > baseurl_nodes[2] = adaptionset_baseurl_node; > baseurl_nodes[3] = representation_baseurl_node; > > +ret = resolve_content_path(s, url, baseurl_nodes, 4); > + > +if (ret == AVERROR(ENOMEM) || ret == 0) { can this use if (ret <= 0) { ? > +goto end; > +} > + > if (representation_segmenttemplate_node || fragment_template_node) { > fragment_timeline_node = NULL; > fragment_templates_tab[0] = representation_segmenttemplate_node; > @@ -993,6 +1091,9 @@ static int parse_manifest(AVFormatContext *s, const char
[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is availa
--- libavformat/dashdec.c | 116 -- 1 file changed, 103 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 3798649..cdb9f67 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) return av_gettime() / 100; } +static int ishttp(char *url) { +const char *proto_name = avio_find_protocol_name(url); +return av_strstart(proto_name, "http", NULL); +} + static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char *datetime) { struct tm timeinfo; @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); +av_freep(pb); +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); + if (ret >= 0) { // update cookies on http response with setcookies. char *new_cookies = NULL; @@ -639,6 +646,91 @@ static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representat return 0; } +static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { + +char *tmp_str = av_mallocz(MAX_URL_SIZE); +char *tmp_str_2= av_mallocz(MAX_URL_SIZE); +char *path = av_mallocz(MAX_URL_SIZE); +char *mpdName = NULL; +xmlNodePtr node = NULL; +char *baseurl = NULL; +char *root_url = NULL; +char *text = NULL; + +int isRootHttp = 0; +char token ='/'; +int start = 0; +int rootId = 0; +int updated = 0; +int size = 0; +int i; + +if (!tmp_str || !tmp_str_2 || !path) { +updated = AVERROR(ENOMEM); +goto end; +} + +av_strlcpy(tmp_str, url, strlen(url)+1); +mpdName = strtok (tmp_str," /"); + +while ((mpdName =strtok (NULL, "/"))) { +size = strlen(mpdName); +} + +av_strlcpy (path, url, strlen(url)-size+1); + +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) { +if (!(node = baseurl_nodes[rootId])) { +continue; +} +if (ishttp(xmlNodeGetContent(node))) { +break; +} +} + +node = baseurl_nodes[rootId]; +baseurl = xmlNodeGetContent(node); +root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl; + +if (node) { +xmlNodeSetContent(node, root_url); +} + +size = strlen(root_url); +isRootHttp= ishttp(root_url); + +if (root_url[size-1]==token) { +av_strlcat(root_url, "/", size+2); +size+=2; +} + +for (i = 0; i < n_baseurl_nodes; ++i) { +if (i==rootId) { +continue; +} +text = xmlNodeGetContent(baseurl_nodes[i]); +if (text) { +memset(tmp_str, 0, strlen(tmp_str)); + +if (!ishttp(text) && isRootHttp) { +av_strlcpy(tmp_str, root_url, size+1); +} +start = (text[0]==token) ? 1: 0; +memset(tmp_str_2, 0, strlen(tmp_str_2)); +av_strlcat(tmp_str, text+start, MAX_URL_SIZE); +xmlNodeSetContent(baseurl_nodes[i], tmp_str); +updated = 1; +xmlFree(text); +} +} + +end: +av_free(path); +av_free(tmp_str); +av_free(tmp_str_2); +return updated; + +} static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr node, xmlNodePtr adaptionset_node, @@ -698,6 +790,12 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; +ret = resolve_content_path(s, url, baseurl_nodes, 4); + +if (ret == AVERROR(ENOMEM) || ret == 0) { +goto end; +} + if (representation_segmenttemplate_node || fragment_template_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; @@ -993,6 +1091,9 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) } mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); +if (!mpd_baseurl_node) { +mpd_baseurl_node = xmlNewNode(NULL, "BaseURL"); +} // at now we can handle only one period, with the longest duration node = xmlFirstElementChild(node); @@ -1315,6 +1416,7 @@ static int read_from_url(struct representation *pls, struct fragment *seg, } else { ret = avio_read(pls->input, buf, buf_size); } + if (ret > 0) pls->cur_seg_offset += ret; @@ -1343,18 +1445,6 @@ static int open_input(DASHContext *c, struct representation *pls, stru
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is av
2017-12-06 9:42 GMT+08:00 Colin NG : > --- > libavformat/dashdec.c | 111 > -- > 1 file changed, 98 insertions(+), 13 deletions(-) > > diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c > index 3798649..6e35e91 100644 > --- a/libavformat/dashdec.c > +++ b/libavformat/dashdec.c > @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) > return av_gettime() / 100; > } > > +static char * ishttp(char *url) { > +char *proto_name = avio_find_protocol_name(url); > +return av_strstart(proto_name, "http", NULL); > +} > + > static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char > *datetime) > { > struct tm timeinfo; > @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, > const char *url, > else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) > return AVERROR_INVALIDDATA; > > -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); > +av_freep(pb); > +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); > + > if (ret >= 0) { > // update cookies on http response with setcookies. > char *new_cookies = NULL; > @@ -639,6 +646,86 @@ static int > parse_manifest_segmenttimeline(AVFormatContext *s, struct representat > return 0; > } > > +static int resolve_content_path(AVFormatContext *s, const char *url, > xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { > + > +int i; > +char *text; > +char *tmp_str = av_mallocz(MAX_URL_SIZE); > +char *tmp_str_2= av_mallocz(MAX_URL_SIZE); > + > +char *path = av_mallocz(MAX_URL_SIZE); > +int nameSize = 0; > +int updated = 0; > + > +if (!tmp_str || !tmp_str_2 || !path) { > +updated = AVERROR(ENOMEM); > +goto end; > +} > + > +av_strlcpy(tmp_str, url, strlen(url)+1); > +char *mpdName = strtok (tmp_str," /"); > + > +while ((mpdName =strtok (NULL, "/"))) { > +nameSize = strlen(mpdName); > +} > + > +av_strlcpy (path, url, strlen(url)-nameSize+1); > + > +int rootId = 0; > +xmlNodePtr *node = NULL; > +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) { > +if (!(node = baseurl_nodes[rootId])) { > +continue; > +} > +if (ishttp(xmlNodeGetContent(node))) { > +break; > +} > +} > + > +node = baseurl_nodes[rootId]; > +char *baseurl = xmlNodeGetContent(node); > +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl; > + > +if (node) { > +xmlNodeSetContent(node, root_url); > +} > + > +int size = strlen(root_url); > +char *isRootHttp = ishttp(root_url); > + > +char token ='/'; > +if (root_url[size] == token) { > +av_strlcat(root_url, "/", size+2); > +size+=2; > +} > + > +for (i = 0; i < n_baseurl_nodes; ++i) { > +if (i == rootId) { > +continue; > +} > +text = xmlNodeGetContent(baseurl_nodes[i]); > +if (text) { > +memset(tmp_str, 0, strlen(tmp_str)); > + > +if (!ishttp(text) && isRootHttp) { > +av_strlcpy(tmp_str, root_url, size+1); > +} > +int start = (text[0]==token) ? 1: 0; > +memset(tmp_str_2, 0, strlen(tmp_str_2)); > +av_strlcat(tmp_str, text+start, MAX_URL_SIZE); > +xmlFree(text); > +xmlNodeSetContent(baseurl_nodes[i], tmp_str); > +updated = 1; > +} > +} > + > +end: > +av_free(path); > +av_free(tmp_str); > +av_free(tmp_str_2); > +return updated; > + > +} > static int parse_manifest_representation(AVFormatContext *s, const char *url, > xmlNodePtr node, > xmlNodePtr adaptionset_node, > @@ -698,6 +785,12 @@ static int parse_manifest_representation(AVFormatContext > *s, const char *url, > baseurl_nodes[2] = adaptionset_baseurl_node; > baseurl_nodes[3] = representation_baseurl_node; > > +ret = resolve_content_path(s, url, baseurl_nodes, 4); > + > +if (ret == AVERROR(ENOMEM) || ret == 0) { > +goto end; > +} > + > if (representation_segmenttemplate_node || fragment_template_node) { > fragment_timeline_node = NULL; > fragment_templates_tab[0] = representation_segmenttemplate_node; > @@ -993,6 +1086,9 @@ static int parse_manifest(AVFormatContext *s, const char > *url, AVIOContext *in) > } > > mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); > +if (!mpd_baseurl_node) { > +mpd_baseurl_node = xmlNewNode(node, "BaseURL"); > +} > > // at now we can handle only one period, with the longest duration > node = xmlFirstElementChild(node); > @@ -1315,6 +1411,7 @@ static int read_from_url(struct representation *pls, > struct fragment
[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) - Add function 'resolve_content_path' to propagate the baseURL from upper level nodes. * if no baseURL is availa
--- libavformat/dashdec.c | 111 -- 1 file changed, 98 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 3798649..6e35e91 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) return av_gettime() / 100; } +static char * ishttp(char *url) { +char *proto_name = avio_find_protocol_name(url); +return av_strstart(proto_name, "http", NULL); +} + static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char *datetime) { struct tm timeinfo; @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); +av_freep(pb); +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); + if (ret >= 0) { // update cookies on http response with setcookies. char *new_cookies = NULL; @@ -639,6 +646,86 @@ static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representat return 0; } +static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { + +int i; +char *text; +char *tmp_str = av_mallocz(MAX_URL_SIZE); +char *tmp_str_2= av_mallocz(MAX_URL_SIZE); + +char *path = av_mallocz(MAX_URL_SIZE); +int nameSize = 0; +int updated = 0; + +if (!tmp_str || !tmp_str_2 || !path) { +updated = AVERROR(ENOMEM); +goto end; +} + +av_strlcpy(tmp_str, url, strlen(url)+1); +char *mpdName = strtok (tmp_str," /"); + +while ((mpdName =strtok (NULL, "/"))) { +nameSize = strlen(mpdName); +} + +av_strlcpy (path, url, strlen(url)-nameSize+1); + +int rootId = 0; +xmlNodePtr *node = NULL; +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) { +if (!(node = baseurl_nodes[rootId])) { +continue; +} +if (ishttp(xmlNodeGetContent(node))) { +break; +} +} + +node = baseurl_nodes[rootId]; +char *baseurl = xmlNodeGetContent(node); +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl; + +if (node) { +xmlNodeSetContent(node, root_url); +} + +int size = strlen(root_url); +char *isRootHttp = ishttp(root_url); + +char token ='/'; +if (root_url[size] == token) { +av_strlcat(root_url, "/", size+2); +size+=2; +} + +for (i = 0; i < n_baseurl_nodes; ++i) { +if (i == rootId) { +continue; +} +text = xmlNodeGetContent(baseurl_nodes[i]); +if (text) { +memset(tmp_str, 0, strlen(tmp_str)); + +if (!ishttp(text) && isRootHttp) { +av_strlcpy(tmp_str, root_url, size+1); +} +int start = (text[0]==token) ? 1: 0; +memset(tmp_str_2, 0, strlen(tmp_str_2)); +av_strlcat(tmp_str, text+start, MAX_URL_SIZE); +xmlFree(text); +xmlNodeSetContent(baseurl_nodes[i], tmp_str); +updated = 1; +} +} + +end: +av_free(path); +av_free(tmp_str); +av_free(tmp_str_2); +return updated; + +} static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr node, xmlNodePtr adaptionset_node, @@ -698,6 +785,12 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; +ret = resolve_content_path(s, url, baseurl_nodes, 4); + +if (ret == AVERROR(ENOMEM) || ret == 0) { +goto end; +} + if (representation_segmenttemplate_node || fragment_template_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; @@ -993,6 +1086,9 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) } mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); +if (!mpd_baseurl_node) { +mpd_baseurl_node = xmlNewNode(node, "BaseURL"); +} // at now we can handle only one period, with the longest duration node = xmlFirstElementChild(node); @@ -1315,6 +1411,7 @@ static int read_from_url(struct representation *pls, struct fragment *seg, } else { ret = avio_read(pls->input, buf, buf_size); } + if (ret > 0) pls->cur_seg_offset += ret; @@ -1343,18 +1440,6 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen goto cleanup; } -/* Seek to the requested position. If this
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
From: ffmpeg-devel on behalf of Steven Liu Sent: December 4, 2017 4:52 AM To: FFmpeg development discussions and patches Subject: Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault) 2017-12-04 12:28 GMT+08:00 Colin NG : > --- > libavformat/dashdec.c | 112 > -- > 1 file changed, 99 insertions(+), 13 deletions(-) > > diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c > index 3798649..d04bec0 100644 > --- a/libavformat/dashdec.c > +++ b/libavformat/dashdec.c > @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) > return av_gettime() / 100; > } > > +static char * ishttp(char *url) { > +char *proto_name = avio_find_protocol_name(url); > +return av_strstart(proto_name, "http", NULL); > +} > + > static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char > *datetime) > { > struct tm timeinfo; > @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, > const char *url, > else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) > return AVERROR_INVALIDDATA; > > -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); > +av_freep(pb); > +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); > + > if (ret >= 0) { > // update cookies on http response with setcookies. > char *new_cookies = NULL; > @@ -639,6 +646,87 @@ static int > parse_manifest_segmenttimeline(AVFormatContext *s, struct representat > return 0; > } > > +static int resolve_content_path(AVFormatContext *s, const char *url, > xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { > + > +int i; > +char *text; > +char *tmp_str = av_mallocz(MAX_URL_SIZE); > +char *tmp_str_2= av_mallocz(MAX_URL_SIZE); > + > +char *path = av_mallocz(MAX_URL_SIZE); > +int nameSize = 0; > +int updated = 0; > + > +if (!tmp_str || !tmp_str_2 || !path) { > +updated = AVERROR(ENOMEM); > +goto end; > +} > + > +av_strlcpy(tmp_str, url, strlen(url)+1); > +char *mpdName = strtok (tmp_str," /"); > + > +while ((mpdName =strtok (NULL, "/"))) { What dose this do? The above instruction will split the url (i.e. url of the mpd file) elements with "/" separator in between. > +nameSize = strlen(mpdName); > +} > + > +av_strlcpy (path, url, strlen(url)-nameSize+1); > + > +int rootId = 0; > +xmlNodePtr *node = NULL; > +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) { > +if (!(node = baseurl_nodes[rootId])) { > +continue; > +} > +if (ishttp(xmlNodeGetContent(node))) { > +break; > +} > +} > + > +node = baseurl_nodes[rootId]; > +char *baseurl = xmlNodeGetContent(node); > +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl; > + > +if (node) { > +xmlNodeSetContent(node, root_url); > +} > + > +int size = strlen(root_url); > +char *isRootHttp= ishttp(root_url); > + > +char token ='/'; > +//if (root_url[size-1]==token) { > +if (av_strncasecmp(&root_url[size-1],&token, 1) != 0) { If this only compare 1 char, why don't use root_url[size-1] == token ? > +av_strlcat(root_url, "/", size+2); > +size+=2; > +} > + > +for (i = 0; i < n_baseurl_nodes; ++i) { > +if (i==rootId) { > +continue; > +} > +text = xmlNodeGetContent(baseurl_nodes[i]); > +if (text) { > +memset(tmp_str, 0, strlen(tmp_str)); > + > +if (!ishttp(text) && isRootHttp) { > +av_strlcpy(tmp_str, root_url, size+1); > +} > +int start = (text[0]==token) ? 1: 0; > +memset(tmp_str_2, 0, strlen(tmp_str_2)); > +av_strlcat(tmp_str, text+start, MAX_URL_SIZE); > +xmlFree(text); > +xmlNodeSetContent(baseurl_nodes[i], tmp_str); > +updated = 1; > +} > +} > + > +end: > +av_free(path); > +av_free(tmp_str); > +av_free(tmp_str_2); > +return updated; > + > +} > static int parse_manifest_representation(AVFormatContext *s, const char *url, > xmlNodePtr node, > xmlNodePtr adaptionset_node, > @@ -698,6 +786,12 @@ static int parse_manifest_r
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
On 12/4/2017 4:28 AM, Colin NG wrote: > --- > libavformat/dashdec.c | 112 > -- > 1 file changed, 99 insertions(+), 13 deletions(-) Please describe what is actually being changed, and why, in the commit message. It is both hard to review with no description, and incredibly annoying to git blame later, without a proper commit message. For example, a bunch of these changes seem pretty disparate, hence my 'Why?' after several. > +static char * ishttp(char *url) { > +char *proto_name = avio_find_protocol_name(url); > +return av_strstart(proto_name, "http", NULL); > +} Is the URL guaranteed to have a known, and enabled (in avforma) protocol? If not, then this can crash, because avio_find_procotol_name will return NULL. > -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); > +av_freep(pb); > +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); Why? > +static int resolve_content_path(AVFormatContext *s, const char *url, > xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { > + > +int i; > +char *text; > +char *tmp_str = av_mallocz(MAX_URL_SIZE); > +char *tmp_str_2= av_mallocz(MAX_URL_SIZE); > + > +char *path = av_mallocz(MAX_URL_SIZE); If the size is known (and not massive), why are these heap allocations? > +int nameSize = 0; > +int updated = 0; > + > +if (!tmp_str || !tmp_str_2 || !path) { > +updated = AVERROR(ENOMEM); > +goto end; > +} > + > +av_strlcpy(tmp_str, url, strlen(url)+1); > +char *mpdName = strtok (tmp_str," /"); Don't mix declarations and code. > + > +while ((mpdName =strtok (NULL, "/"))) { > +nameSize = strlen(mpdName); > +} > + > +av_strlcpy (path, url, strlen(url)-nameSize+1); > + > +int rootId = 0; > +xmlNodePtr *node = NULL; Ditto. > +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) { > +if (!(node = baseurl_nodes[rootId])) { > +continue; > +} > +if (ishttp(xmlNodeGetContent(node))) { > +break; > +} > +} > + > +node = baseurl_nodes[rootId]; > +char *baseurl = xmlNodeGetContent(node); > +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl; Ditto. Also should all of these calls to the XML lib have checks? My gut says 'yes'. > + > +if (node) { > +xmlNodeSetContent(node, root_url); > +} > + > +int size = strlen(root_url); > +char *isRootHttp= ishttp(root_url); > + > +char token ='/'; Ditto. > +//if (root_url[size-1]==token) { > +if (av_strncasecmp(&root_url[size-1],&token, 1) != 0) { > +av_strlcat(root_url, "/", size+2); > +size+=2; > +} > + > +for (i = 0; i < n_baseurl_nodes; ++i) { > +if (i==rootId) { > +continue; > +} > +text = xmlNodeGetContent(baseurl_nodes[i]); > +if (text) { > +memset(tmp_str, 0, strlen(tmp_str)); > + > +if (!ishttp(text) && isRootHttp) { > +av_strlcpy(tmp_str, root_url, size+1); > +} > +int start = (text[0]==token) ? 1: 0; Mixed code and variable declarations. Also, redundant ternary operation. > +memset(tmp_str_2, 0, strlen(tmp_str_2)); > +av_strlcat(tmp_str, text+start, MAX_URL_SIZE); > +xmlFree(text); > +xmlNodeSetContent(baseurl_nodes[i], tmp_str); > +updated = 1; What's with the odd 0/1 return values, which are not even checked anywhere? > +} > +} > + > +end: > +av_free(path); > +av_free(tmp_str); > +av_free(tmp_str_2); > +return updated; > + > +} > static int parse_manifest_representation(AVFormatContext *s, const char *url, > xmlNodePtr node, > xmlNodePtr adaptionset_node, > @@ -698,6 +786,12 @@ static int parse_manifest_representation(AVFormatContext > *s, const char *url, > baseurl_nodes[2] = adaptionset_baseurl_node; > baseurl_nodes[3] = representation_baseurl_node; > > +ret = resolve_content_path(s, url, baseurl_nodes, 4); > + > +if (ret == AVERROR(ENOMEM)) { > +goto end; > +} This kind of check seems very wrong. Check for ret < 0. > mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); > +if (!mpd_baseurl_node) { > +mpd_baseurl_node = xmlNewNode(node, "BaseURL"); > +} Why? Also missing check for xmlNewNode ret value? > > // at now we can handle only one period, with the longest duration > node = xmlFirstElementChild(node); > @@ -1315,6 +1412,7 @@ static int read_from_url(struct representation *pls, > struct fragment *seg, > } else { > ret = avio_read(pls->input, buf, buf_size); > } > + > if (ret > 0) Stray change. > -/* Seek to the requested position. If this was a HTTP request, the of
Re: [FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
2017-12-04 12:28 GMT+08:00 Colin NG : > --- > libavformat/dashdec.c | 112 > -- > 1 file changed, 99 insertions(+), 13 deletions(-) > > diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c > index 3798649..d04bec0 100644 > --- a/libavformat/dashdec.c > +++ b/libavformat/dashdec.c > @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) > return av_gettime() / 100; > } > > +static char * ishttp(char *url) { > +char *proto_name = avio_find_protocol_name(url); > +return av_strstart(proto_name, "http", NULL); > +} > + > static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char > *datetime) > { > struct tm timeinfo; > @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, > const char *url, > else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) > return AVERROR_INVALIDDATA; > > -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); > +av_freep(pb); > +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); > + > if (ret >= 0) { > // update cookies on http response with setcookies. > char *new_cookies = NULL; > @@ -639,6 +646,87 @@ static int > parse_manifest_segmenttimeline(AVFormatContext *s, struct representat > return 0; > } > > +static int resolve_content_path(AVFormatContext *s, const char *url, > xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { > + > +int i; > +char *text; > +char *tmp_str = av_mallocz(MAX_URL_SIZE); > +char *tmp_str_2= av_mallocz(MAX_URL_SIZE); > + > +char *path = av_mallocz(MAX_URL_SIZE); > +int nameSize = 0; > +int updated = 0; > + > +if (!tmp_str || !tmp_str_2 || !path) { > +updated = AVERROR(ENOMEM); > +goto end; > +} > + > +av_strlcpy(tmp_str, url, strlen(url)+1); > +char *mpdName = strtok (tmp_str," /"); > + > +while ((mpdName =strtok (NULL, "/"))) { What dose this do? > +nameSize = strlen(mpdName); > +} > + > +av_strlcpy (path, url, strlen(url)-nameSize+1); > + > +int rootId = 0; > +xmlNodePtr *node = NULL; > +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) { > +if (!(node = baseurl_nodes[rootId])) { > +continue; > +} > +if (ishttp(xmlNodeGetContent(node))) { > +break; > +} > +} > + > +node = baseurl_nodes[rootId]; > +char *baseurl = xmlNodeGetContent(node); > +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl; > + > +if (node) { > +xmlNodeSetContent(node, root_url); > +} > + > +int size = strlen(root_url); > +char *isRootHttp= ishttp(root_url); > + > +char token ='/'; > +//if (root_url[size-1]==token) { > +if (av_strncasecmp(&root_url[size-1],&token, 1) != 0) { If this only compare 1 char, why don't use root_url[size-1] == token ? > +av_strlcat(root_url, "/", size+2); > +size+=2; > +} > + > +for (i = 0; i < n_baseurl_nodes; ++i) { > +if (i==rootId) { > +continue; > +} > +text = xmlNodeGetContent(baseurl_nodes[i]); > +if (text) { > +memset(tmp_str, 0, strlen(tmp_str)); > + > +if (!ishttp(text) && isRootHttp) { > +av_strlcpy(tmp_str, root_url, size+1); > +} > +int start = (text[0]==token) ? 1: 0; > +memset(tmp_str_2, 0, strlen(tmp_str_2)); > +av_strlcat(tmp_str, text+start, MAX_URL_SIZE); > +xmlFree(text); > +xmlNodeSetContent(baseurl_nodes[i], tmp_str); > +updated = 1; > +} > +} > + > +end: > +av_free(path); > +av_free(tmp_str); > +av_free(tmp_str_2); > +return updated; > + > +} > static int parse_manifest_representation(AVFormatContext *s, const char *url, > xmlNodePtr node, > xmlNodePtr adaptionset_node, > @@ -698,6 +786,12 @@ static int parse_manifest_representation(AVFormatContext > *s, const char *url, > baseurl_nodes[2] = adaptionset_baseurl_node; > baseurl_nodes[3] = representation_baseurl_node; > > +ret = resolve_content_path(s, url, baseurl_nodes, 4); > + > +if (ret == AVERROR(ENOMEM)) { What about ret < 0 ? > +goto end; > +} > + > if (representation_segmenttemplate_node || fragment_template_node) { > fragment_timeline_node = NULL; > fragment_templates_tab[0] = representation_segmenttemplate_node; > @@ -993,6 +1087,9 @@ static int parse_manifest(AVFormatContext *s, const char > *url, AVIOContext *in) > } > > mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); > +if (!mpd_baseurl_node) { > +mpd_baseurl_node = xmlNewNode(node, "BaseURL"); > +} > > // at now we can handle only one period, with
[FFmpeg-devel] [PATCH] libavformat/dashdec: Fix for ticket 6658 (Dash demuxer segfault)
--- libavformat/dashdec.c | 112 -- 1 file changed, 99 insertions(+), 13 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 3798649..d04bec0 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -148,6 +148,11 @@ static uint64_t get_current_time_in_sec(void) return av_gettime() / 100; } +static char * ishttp(char *url) { +char *proto_name = avio_find_protocol_name(url); +return av_strstart(proto_name, "http", NULL); +} + static uint64_t get_utc_date_time_insec(AVFormatContext *s, const char *datetime) { struct tm timeinfo; @@ -392,7 +397,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; -ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp); +av_freep(pb); +ret = avio_open2(pb, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp); + if (ret >= 0) { // update cookies on http response with setcookies. char *new_cookies = NULL; @@ -639,6 +646,87 @@ static int parse_manifest_segmenttimeline(AVFormatContext *s, struct representat return 0; } +static int resolve_content_path(AVFormatContext *s, const char *url, xmlNodePtr *baseurl_nodes, int n_baseurl_nodes) { + +int i; +char *text; +char *tmp_str = av_mallocz(MAX_URL_SIZE); +char *tmp_str_2= av_mallocz(MAX_URL_SIZE); + +char *path = av_mallocz(MAX_URL_SIZE); +int nameSize = 0; +int updated = 0; + +if (!tmp_str || !tmp_str_2 || !path) { +updated = AVERROR(ENOMEM); +goto end; +} + +av_strlcpy(tmp_str, url, strlen(url)+1); +char *mpdName = strtok (tmp_str," /"); + +while ((mpdName =strtok (NULL, "/"))) { +nameSize = strlen(mpdName); +} + +av_strlcpy (path, url, strlen(url)-nameSize+1); + +int rootId = 0; +xmlNodePtr *node = NULL; +for (rootId = n_baseurl_nodes-1; rootId >0; rootId--) { +if (!(node = baseurl_nodes[rootId])) { +continue; +} +if (ishttp(xmlNodeGetContent(node))) { +break; +} +} + +node = baseurl_nodes[rootId]; +char *baseurl = xmlNodeGetContent(node); +char *root_url = (!av_strcasecmp(baseurl, ""))? path: baseurl; + +if (node) { +xmlNodeSetContent(node, root_url); +} + +int size = strlen(root_url); +char *isRootHttp= ishttp(root_url); + +char token ='/'; +//if (root_url[size-1]==token) { +if (av_strncasecmp(&root_url[size-1],&token, 1) != 0) { +av_strlcat(root_url, "/", size+2); +size+=2; +} + +for (i = 0; i < n_baseurl_nodes; ++i) { +if (i==rootId) { +continue; +} +text = xmlNodeGetContent(baseurl_nodes[i]); +if (text) { +memset(tmp_str, 0, strlen(tmp_str)); + +if (!ishttp(text) && isRootHttp) { +av_strlcpy(tmp_str, root_url, size+1); +} +int start = (text[0]==token) ? 1: 0; +memset(tmp_str_2, 0, strlen(tmp_str_2)); +av_strlcat(tmp_str, text+start, MAX_URL_SIZE); +xmlFree(text); +xmlNodeSetContent(baseurl_nodes[i], tmp_str); +updated = 1; +} +} + +end: +av_free(path); +av_free(tmp_str); +av_free(tmp_str_2); +return updated; + +} static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr node, xmlNodePtr adaptionset_node, @@ -698,6 +786,12 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, baseurl_nodes[2] = adaptionset_baseurl_node; baseurl_nodes[3] = representation_baseurl_node; +ret = resolve_content_path(s, url, baseurl_nodes, 4); + +if (ret == AVERROR(ENOMEM)) { +goto end; +} + if (representation_segmenttemplate_node || fragment_template_node) { fragment_timeline_node = NULL; fragment_templates_tab[0] = representation_segmenttemplate_node; @@ -993,6 +1087,9 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) } mpd_baseurl_node = find_child_node_by_name(node, "BaseURL"); +if (!mpd_baseurl_node) { +mpd_baseurl_node = xmlNewNode(node, "BaseURL"); +} // at now we can handle only one period, with the longest duration node = xmlFirstElementChild(node); @@ -1315,6 +1412,7 @@ static int read_from_url(struct representation *pls, struct fragment *seg, } else { ret = avio_read(pls->input, buf, buf_size); } + if (ret > 0) pls->cur_seg_offset += ret; @@ -1343,18 +1441,6 @@ static int open_input(DASHContext *c, struct representation *pls, struct fragmen goto cleanup; }