On Fri, Apr 13, 2018 at 5:14 PM, <rshaf...@tunein.com> wrote: > From: Richard Shaffer <rshaf...@tunein.com> > > The HLSContext struct contains fields which duplicate the data stored in > the > avio_opts field. This change removes those fields in favor of avio_opts, > and > updates the code accordingly. > --- > The original patch caused the buffer pointed to by new_cookies in open_url > to be > leaked. The only thing that buffer is used for is to store the value until > it > can be passed to av_dict_set. To fix the leak, v2 of the patch simply calls > av_dict_set with the AV_DICT_DONT_STRDUP_VAL flag, so that the dictionary > takes > ownership of the memory instead of copying it again. > > libavformat/hls.c | 74 +++++++----------------------- > ------------------------- > 1 file changed, 9 insertions(+), 65 deletions(-) > > diff --git a/libavformat/hls.c b/libavformat/hls.c > index 1257cd101c..d6158c0ada 100644 > --- a/libavformat/hls.c > +++ b/libavformat/hls.c > @@ -202,11 +202,6 @@ typedef struct HLSContext { > int64_t first_timestamp; > int64_t cur_timestamp; > AVIOInterruptCB *interrupt_callback; > - char *referer; ///< holds HTTP referer set as > an AVOption to the HTTP protocol context > - char *user_agent; ///< holds HTTP user agent set > as an AVOption to the HTTP protocol context > - char *cookies; ///< holds HTTP cookie values > set in either the initial response or as an AVOption to the HTTP protocol > context > - char *headers; ///< holds HTTP headers set as > an AVOption to the HTTP protocol context > - char *http_proxy; ///< holds the address of the > HTTP proxy server > AVDictionary *avio_opts; > int strict_std_compliance; > char *allowed_extensions; > @@ -267,10 +262,6 @@ static void free_playlist_list(HLSContext *c) > av_free(pls); > } > av_freep(&c->playlists); > - av_freep(&c->cookies); > - av_freep(&c->user_agent); > - av_freep(&c->headers); > - av_freep(&c->http_proxy); > c->n_playlists = 0; > } > > @@ -593,14 +584,6 @@ static int ensure_playlist(HLSContext *c, struct > playlist **pls, const char *url > return 0; > } > > -static void update_options(char **dest, const char *name, void *src) > -{ > - av_freep(dest); > - av_opt_get(src, name, AV_OPT_SEARCH_CHILDREN, (uint8_t**)dest); > - if (*dest && !strlen(*dest)) > - av_freep(dest); > -} > - > static int open_url_keepalive(AVFormatContext *s, AVIOContext **pb, > const char *url) > { > @@ -684,12 +667,8 @@ static int open_url(AVFormatContext *s, AVIOContext > **pb, const char *url, > if (!(s->flags & AVFMT_FLAG_CUSTOM_IO)) > av_opt_get(*pb, "cookies", AV_OPT_SEARCH_CHILDREN, > (uint8_t**)&new_cookies); > > - if (new_cookies) { > - av_free(c->cookies); > - c->cookies = new_cookies; > - } > - > - av_dict_set(&opts, "cookies", c->cookies, 0); > + if (new_cookies) > + av_dict_set(&opts, "cookies", new_cookies, > AV_DICT_DONT_STRDUP_VAL); > } > > av_dict_free(&tmp); > @@ -736,14 +715,7 @@ static int parse_playlist(HLSContext *c, const char > *url, > > if (!in) { > AVDictionary *opts = NULL; > - /* Some HLS servers don't like being sent the range header */ > - av_dict_set(&opts, "seekable", "0", 0); > - > - // broker prior HTTP options that should be consistent across > requests > - av_dict_set(&opts, "user_agent", c->user_agent, 0); > - av_dict_set(&opts, "cookies", c->cookies, 0); > - av_dict_set(&opts, "headers", c->headers, 0); > - av_dict_set(&opts, "http_proxy", c->http_proxy, 0); > + av_dict_copy(&opts, c->avio_opts, 0); > > if (c->http_persistent) > av_dict_set(&opts, "multiple_requests", "1", 0); > @@ -1169,14 +1141,6 @@ static int open_input(HLSContext *c, struct > playlist *pls, struct segment *seg, > int ret; > int is_http = 0; > > - // broker prior HTTP options that should be consistent across requests > - av_dict_set(&opts, "user_agent", c->user_agent, 0); > - av_dict_set(&opts, "referer", c->referer, 0); > - av_dict_set(&opts, "cookies", c->cookies, 0); > - av_dict_set(&opts, "headers", c->headers, 0); > - av_dict_set(&opts, "http_proxy", c->http_proxy, 0); > - av_dict_set(&opts, "seekable", "0", 0); > - > if (c->http_persistent) > av_dict_set(&opts, "multiple_requests", "1", 0); > > @@ -1193,7 +1157,6 @@ static int open_input(HLSContext *c, struct playlist > *pls, struct segment *seg, > if (seg->key_type == KEY_NONE) { > ret = open_url(pls->parent, in, seg->url, c->avio_opts, opts, > &is_http); > } else if (seg->key_type == KEY_AES_128) { > - AVDictionary *opts2 = NULL; > char iv[33], key[33], url[MAX_URL_SIZE]; > if (strcmp(seg->key, pls->key_url)) { > AVIOContext *pb = NULL; > @@ -1218,14 +1181,10 @@ static int open_input(HLSContext *c, struct > playlist *pls, struct segment *seg, > else > snprintf(url, sizeof(url), "crypto:%s", seg->url); > > - av_dict_copy(&opts2, c->avio_opts, 0); > - av_dict_set(&opts2, "key", key, 0); > - av_dict_set(&opts2, "iv", iv, 0); > - > - ret = open_url(pls->parent, in, url, opts2, opts, &is_http); > - > - av_dict_free(&opts2); > + av_dict_set(&opts, "key", key, 0); > + av_dict_set(&opts, "iv", iv, 0); > > + ret = open_url(pls->parent, in, url, c->avio_opts, opts, > &is_http); > if (ret < 0) { > goto cleanup; > } > @@ -1781,7 +1740,6 @@ static int hls_close(AVFormatContext *s) > > static int hls_read_header(AVFormatContext *s) > { > - void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb; > HLSContext *c = s->priv_data; > int ret = 0, i; > int highest_cur_seq_no = 0; > @@ -1794,29 +1752,15 @@ static int hls_read_header(AVFormatContext *s) > c->first_timestamp = AV_NOPTS_VALUE; > c->cur_timestamp = AV_NOPTS_VALUE; > > - if (u) { > - // get the previous user agent & set back to null if string size > is zero > - update_options(&c->user_agent, "user_agent", u); > - > - // get the previous cookies & set back to null if string size is > zero > - update_options(&c->cookies, "cookies", u); > - > - // get the previous headers & set back to null if string size is > zero > - update_options(&c->headers, "headers", u); > - > - // get the previous http proxt & set back to null if string size > is zero > - update_options(&c->http_proxy, "http_proxy", u); > - } > - > - if ((ret = parse_playlist(c, s->url, NULL, s->pb)) < 0) > - goto fail; > - > if ((ret = save_avio_options(s)) < 0) > goto fail; > > /* Some HLS servers don't like being sent the range header */ > av_dict_set(&c->avio_opts, "seekable", "0", 0); > > + if ((ret = parse_playlist(c, s->url, NULL, s->pb)) < 0) > + goto fail; > + > if (c->n_variants == 0) { > av_log(NULL, AV_LOG_WARNING, "Empty playlist\n"); > ret = AVERROR_EOF; > -- > 2.15.1 (Apple Git-101) > > Just wanted to send a reminder about this patch. The original version was sent about a week ago. If anyone has time to review and either comment or merge, that would be really great.
-Richard _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel