[FFmpeg-devel] [PATCH] Replace old cookies with new cookies of the same name

wm4 nfxjfg at googlemail.com
Sun Aug 17 13:35:06 CEST 2014


On Sun, 17 Aug 2014 13:29:15 +0200
Nicolas George <george at nsup.org> wrote:

> Le decadi 30 thermidor, an CCXXII, Micah Galizia a écrit :
> > When new cookie values (with the same name as an existing cookie) are
> > returned in an HLS stream, the current implementation will append the
> > new cookie to the list of cookies. This causes FFMPEG to send multiple
> > cookie values for the same cookie and in some cases exceed the http
> > header size in some cases.
> > 
> > The patch attached resolves the issue.
> 
> Thanks for the patch. Below are a few technical remarks. But before that, a
> general remark:
> 
> char *cookies;  ///< holds newline (\n) delimited Set-Cookie header field
>                      values (without the "Set-Cookie: " field name)
> 
> Well, this is just awful. This is obviously not your fault, this is existing
> code, but it is no way of building anything: it can do for a quick-and-dirty
> first implementation to get things working, but it makes a very bad ground
> to build upon.
> 
> It seems to me that most of your patch is there to deal with that awful data
> structure. A large part of the existing code too, for that matter.
> 
> IMHO, it would be much better to rework the current code to use a proper
> data structure. A dynarray of structures with name, value, path and domain
> already split seems like the best option.
> 
> I suspect it would even be simpler to do that than making sure your patch is
> correct in its current form.
> 
> Are you interested in that?

AFAIK this cookie string is exposed by AVOption API, and I use it for
setting cookies. And I don't feel like rewriting this code at all.

> 
> > From ad65b070a7b49698e623f08365ec7e751d0bae08 Mon Sep 17 00:00:00 2001
> > From: Micah Galizia <micahgalizia at gmail.com>
> > Date: Sun, 17 Aug 2014 20:50:02 +1000
> > Subject: [PATCH] Replace old cookies with new cookies of the same name
> > 
> > ---
> >  libavformat/http.c | 86 +++++++++++++++++++++++++++++++++++++++++++++---------
> >  1 file changed, 73 insertions(+), 13 deletions(-)
> > 
> > diff --git a/libavformat/http.c b/libavformat/http.c
> > index 7480834..f1b9c34 100644
> > --- a/libavformat/http.c
> > +++ b/libavformat/http.c
> > @@ -444,6 +444,77 @@ static int parse_icy(HTTPContext *s, const char *tag, const char *p)
> >      return 0;
> >  }
> >  
> > +static int update_cookies(URLContext *h, char **cookies, char *new_cookie) {
> > +
> > +    int prefix, offset, suffix, new_cookie_len = strlen(new_cookie);
> > +    char *name, *cookie, *next;
> > +
> > +    // if the existing cookies are empty then just set it and forget it
> > +    if (!*cookies) {
> > +        if (!(*cookies = av_strdup(new_cookie)))
> > +            return AVERROR(ENOMEM);
> > +        return 0;
> > +    }
> > +
> > +    // get the new cookies name
> > +    if (!(cookie = av_strdup(new_cookie)))
> > +        return AVERROR(ENOMEM);
> > +
> 
> > +    // if the new cookie format isnt valid just return (without error)
> > +    if (!(name = av_strtok(cookie, "=", &next))) {
> > +        av_log(h, AV_LOG_INFO, "Invalid new cookie format.");
> > +        return 0;
> > +    }
> 
> This makes the av_strdup()ed cookie leak.
> 
> > +
> > +    // copy the name and then free the copy of the cookies
> > +    name = av_asprintf("%s=", name);
> > +    av_free(cookie);
> > +
> > +    // find the offset and free the name (we don't need it anymore)
> > +    next = av_stristr(*cookies, name);
> > +    av_free(name);
> 
> I believe this is wrong: av_stristr() will find "n=" in "session=", so
> "Set-Cookie: n=42" will overwrite "session=1729".
> 
> > +
> > +    // if no substring is found, just append
> > +    if (!next) {
> > +        cookie = av_asprintf("%s\n%s", *cookies, new_cookie);
> > +        av_free(*cookies);
> > +        *cookies = cookie;
> > +        return 0;
> > +    }
> > +
> > +    prefix = next - *cookies;
> > +
> > +    // no subsequent newline means this is the last cookie
> 
> > +    if (!(next = av_stristr(next, "\n"))) {
> 
> av_stristr() for searching a single non-alphabetic character seems overkill.
> 
> > +
> > +        // old and new cookie plus null terminate
> 
> > +        if (!(cookie = av_malloc(prefix + new_cookie_len + 1)))
> 
> It needs a check for integer overflow.
> 
> > +            return AVERROR(ENOMEM);
> > +
> > +        strncpy(cookie, *cookies, prefix);
> 
> > +        sprintf(&cookie[prefix], "%s", new_cookie);
> 
> Unbounded string copy. I know the buffer has been allocated large enough,
> but this makes for fragile code.
> 
> > +        av_free(*cookies);
> > +        *cookies = cookie;
> > +        return 0;
> > +    }
> > +
> > +    offset = next - *cookies;
> > +    suffix = strlen(*cookies) - offset;
> > +
> 
> > +    if (!(cookie = av_malloc(prefix + suffix + new_cookie_len + 2)))
> 
> Check for integer overflow, same as above.
> 
> > +        return AVERROR(ENOMEM);
> > +
> > +    // copy in the prefix, new cookie, and suffix if they exist
> > +    if (prefix) strncpy(cookie, *cookies, prefix);
> 
> > +    sprintf(&cookie[prefix], "%s", new_cookie);
> 
> Unbounded string copy, same as above.
> 
> > +    if (suffix) strncpy(&cookie[prefix + new_cookie_len], &((*cookies)[offset]), suffix);
> > +
> > +    av_free(*cookies);
> > +    *cookies = cookie;
> > +
> > +    return 0;
> > +}
> > +
> >  static int process_line(URLContext *h, char *line, int line_count,
> >                          int *new_location)
> >  {
> > @@ -515,19 +586,8 @@ static int process_line(URLContext *h, char *line, int line_count,
> >              av_free(s->mime_type);
> >              s->mime_type = av_strdup(p);
> >          } else if (!av_strcasecmp(tag, "Set-Cookie")) {
> > -            if (!s->cookies) {
> > -                if (!(s->cookies = av_strdup(p)))
> > -                    return AVERROR(ENOMEM);
> > -            } else {
> > -                char *tmp = s->cookies;
> > -                size_t str_size = strlen(tmp) + strlen(p) + 2;
> > -                if (!(s->cookies = av_malloc(str_size))) {
> > -                    s->cookies = tmp;
> > -                    return AVERROR(ENOMEM);
> > -                }
> > -                snprintf(s->cookies, str_size, "%s\n%s", tmp, p);
> > -                av_free(tmp);
> > -            }
> > +            update_cookies(h, &s->cookies, p);
> > +            av_log(h, AV_LOG_VERBOSE, "Cookies set to '%s'\n", s->cookies);
> >          } else if (!av_strcasecmp(tag, "Icy-MetaInt")) {
> >              s->icy_metaint = strtoll(p, NULL, 10);
> >          } else if (!av_strncasecmp(tag, "Icy-", 4)) {
> 
> Regards,
> 



More information about the ffmpeg-devel mailing list