diff mbox

[FFmpeg-devel] Ignore expired cookies

Message ID 20170325014218.1329-2-micahgalizia@gmail.com
State Superseded
Headers show

Commit Message

Micah Galizia March 25, 2017, 1:42 a.m. UTC
Signed-off-by: Micah Galizia <micahgalizia@gmail.com>
---
 libavformat/http.c | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

Comments

wm4 March 25, 2017, 11:11 a.m. UTC | #1
On Fri, 24 Mar 2017 21:42:18 -0400
Micah Galizia <micahgalizia@gmail.com> wrote:

> Signed-off-by: Micah Galizia <micahgalizia@gmail.com>
> ---
>  libavformat/http.c | 41 +++++++++++++++++++++++++++++++++++++----
>  1 file changed, 37 insertions(+), 4 deletions(-)
> 
> diff --git a/libavformat/http.c b/libavformat/http.c
> index 293a8a7..37bdacf 100644
> --- a/libavformat/http.c
> +++ b/libavformat/http.c
> @@ -29,6 +29,7 @@
>  #include "libavutil/avstring.h"
>  #include "libavutil/opt.h"
>  #include "libavutil/time.h"
> +#include "libavutil/parseutils.h"
>  
>  #include "avformat.h"
>  #include "http.h"
> @@ -48,6 +49,7 @@
>  #define MAX_REDIRECTS 8
>  #define HTTP_SINGLE   1
>  #define HTTP_MUTLI    2
> +#define WHITESPACES " \n\t\r"
>  typedef enum {
>      LOWER_PROTO,
>      READ_HEADERS,
> @@ -877,7 +879,7 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path,
>  
>      *cookies = NULL;
>      while ((cookie = av_strtok(set_cookies, "\n", &next))) {
> -        int domain_offset = 0;
> +        int domain_offset = 0, expired = 0;
>          char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = NULL;
>          set_cookies = NULL;
>  
> @@ -885,7 +887,11 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path,
>          if (parse_cookie(s, cookie, &s->cookie_dict))
>              av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
>  
> -        while ((param = av_strtok(cookie, "; ", &next_param))) {
> +        while ((param = av_strtok(cookie, ";", &next_param))) {
> +
> +            // move past any leading whitespace
> +            param += strspn(param, WHITESPACES);
> +

Not quite sure why this change is even needed, but seems ok.

>              if (cookie) {
>                  // first key-value pair is the actual cookie value
>                  cvalue = av_strdup(param);
> @@ -899,6 +905,33 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path,
>                  int leading_dot = (param[7] == '.');
>                  av_free(cdomain);
>                  cdomain = av_strdup(&param[7+leading_dot]);
> +            } else if (!av_strncasecmp("expires=", param, 8)) {
> +                int i = 0, j = 0;
> +                struct tm tm_buf = {0};
> +                char *expiry = av_strdup(&param[8]);

Unchecked memory allocation that could fail.

> +
> +                // strip off any punctuation or whitespace
> +                for (; i < strlen(expiry); i++) {

A bit ugly stylistically: the i=0 initialization should be in here, and
the strlen should be cached in a variable, instead of recomputing it on
every loop.

> +                    if ((expiry[i] >= '0' && expiry[i] <= '9') ||
> +                        (expiry[i] >= 'A' && expiry[i] <= 'Z') ||
> +                        (expiry[i] >= 'a' && expiry[i] <= 'z')) {
> +                        expiry[j] = expiry[i];
> +                        j++;
> +                    }
> +                }
> +                expiry[j] = '\0';

(To be honest I don't understand why the string is even strduped - you
could just make it with a fixed-sized on-stack buffer. Just discard the
remainder of the string if the buffer is unexpectedly too small - time
strings probably have an upper size bound anyway.)

> +
> +                // move the string beyond the day of week
> +                i = 0;
> +                while ((expiry[i] < '0' || expiry[i] > '9') && (i < j))
> +                    i++;
> +
> +                if (av_small_strptime(&expiry[i], "%d%b%Y%H%M%SGMT", &tm_buf)) {
> +                    if (av_timegm(&tm_buf) < time(NULL))
> +                        expired = 1;

A bit unsure about this time() call. Also nervous about having this in
library code.

> +                }
> +
> +                av_free(expiry);
>              } else {
>                  // ignore unknown attributes
>              }
> @@ -907,9 +940,9 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path,
>              cdomain = av_strdup(domain);
>  
>          // ensure all of the necessary values are valid
> -        if (!cdomain || !cpath || !cvalue) {
> +        if (expired || !cdomain || !cpath || !cvalue ) {
>              av_log(s, AV_LOG_WARNING,
> -                   "Invalid cookie found, no value, path or domain specified\n");
> +                   "Invalid cookie found, expired or no value, path or domain specified\n");
>              goto done_cookie;
>          }
>
Micah Galizia March 25, 2017, 2:30 p.m. UTC | #2
On 2017-03-25 07:11 AM, wm4 wrote:

<snip>

>> -        while ((param = av_strtok(cookie, "; ", &next_param))) {
>> +        while ((param = av_strtok(cookie, ";", &next_param))) {
>> +
>> +            // move past any leading whitespace
>> +            param += strspn(param, WHITESPACES);
>> +
> Not quite sure why this change is even needed, but seems ok.

Its just a little more flexible than expecting a single space and only a space between each delimited field of a cookie.

>>               if (cookie) {
>>                   // first key-value pair is the actual cookie value
>>                   cvalue = av_strdup(param);
>> @@ -899,6 +905,33 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path,
>>                   int leading_dot = (param[7] == '.');
>>                   av_free(cdomain);
>>                   cdomain = av_strdup(&param[7+leading_dot]);
>> +            } else if (!av_strncasecmp("expires=", param, 8)) {
>> +                int i = 0, j = 0;
>> +                struct tm tm_buf = {0};
>> +                char *expiry = av_strdup(&param[8]);
> Unchecked memory allocation that could fail.

Thanks, resolved using the on-stack buffer described below.

>> +
>> +                // strip off any punctuation or whitespace
>> +                for (; i < strlen(expiry); i++) {
> A bit ugly stylistically: the i=0 initialization should be in here, and
> the strlen should be cached in a variable, instead of recomputing it on
> every loop.

Fixed.

>> +                    if ((expiry[i] >= '0' && expiry[i] <= '9') ||
>> +                        (expiry[i] >= 'A' && expiry[i] <= 'Z') ||
>> +                        (expiry[i] >= 'a' && expiry[i] <= 'z')) {
>> +                        expiry[j] = expiry[i];
>> +                        j++;
>> +                    }
>> +                }
>> +                expiry[j] = '\0';
> (To be honest I don't understand why the string is even strduped - you
> could just make it with a fixed-sized on-stack buffer. Just discard the
> remainder of the string if the buffer is unexpectedly too small - time
> strings probably have an upper size bound anyway.)

Changed.

>> +
>> +                // move the string beyond the day of week
>> +                i = 0;
>> +                while ((expiry[i] < '0' || expiry[i] > '9') && (i < j))
>> +                    i++;
>> +
>> +                if (av_small_strptime(&expiry[i], "%d%b%Y%H%M%SGMT", &tm_buf)) {
>> +                    if (av_timegm(&tm_buf) < time(NULL))
>> +                        expired = 1;
> A bit unsure about this time() call. Also nervous about having this in
> library code.

I borrowed some code from parseutils to resolve this.

Thanks for the prompt review.
diff mbox

Patch

diff --git a/libavformat/http.c b/libavformat/http.c
index 293a8a7..37bdacf 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -29,6 +29,7 @@ 
 #include "libavutil/avstring.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/parseutils.h"
 
 #include "avformat.h"
 #include "http.h"
@@ -48,6 +49,7 @@ 
 #define MAX_REDIRECTS 8
 #define HTTP_SINGLE   1
 #define HTTP_MUTLI    2
+#define WHITESPACES " \n\t\r"
 typedef enum {
     LOWER_PROTO,
     READ_HEADERS,
@@ -877,7 +879,7 @@  static int get_cookies(HTTPContext *s, char **cookies, const char *path,
 
     *cookies = NULL;
     while ((cookie = av_strtok(set_cookies, "\n", &next))) {
-        int domain_offset = 0;
+        int domain_offset = 0, expired = 0;
         char *param, *next_param, *cdomain = NULL, *cpath = NULL, *cvalue = NULL;
         set_cookies = NULL;
 
@@ -885,7 +887,11 @@  static int get_cookies(HTTPContext *s, char **cookies, const char *path,
         if (parse_cookie(s, cookie, &s->cookie_dict))
             av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
 
-        while ((param = av_strtok(cookie, "; ", &next_param))) {
+        while ((param = av_strtok(cookie, ";", &next_param))) {
+
+            // move past any leading whitespace
+            param += strspn(param, WHITESPACES);
+
             if (cookie) {
                 // first key-value pair is the actual cookie value
                 cvalue = av_strdup(param);
@@ -899,6 +905,33 @@  static int get_cookies(HTTPContext *s, char **cookies, const char *path,
                 int leading_dot = (param[7] == '.');
                 av_free(cdomain);
                 cdomain = av_strdup(&param[7+leading_dot]);
+            } else if (!av_strncasecmp("expires=", param, 8)) {
+                int i = 0, j = 0;
+                struct tm tm_buf = {0};
+                char *expiry = av_strdup(&param[8]);
+
+                // strip off any punctuation or whitespace
+                for (; i < strlen(expiry); i++) {
+                    if ((expiry[i] >= '0' && expiry[i] <= '9') ||
+                        (expiry[i] >= 'A' && expiry[i] <= 'Z') ||
+                        (expiry[i] >= 'a' && expiry[i] <= 'z')) {
+                        expiry[j] = expiry[i];
+                        j++;
+                    }
+                }
+                expiry[j] = '\0';
+
+                // move the string beyond the day of week
+                i = 0;
+                while ((expiry[i] < '0' || expiry[i] > '9') && (i < j))
+                    i++;
+
+                if (av_small_strptime(&expiry[i], "%d%b%Y%H%M%SGMT", &tm_buf)) {
+                    if (av_timegm(&tm_buf) < time(NULL))
+                        expired = 1;
+                }
+
+                av_free(expiry);
             } else {
                 // ignore unknown attributes
             }
@@ -907,9 +940,9 @@  static int get_cookies(HTTPContext *s, char **cookies, const char *path,
             cdomain = av_strdup(domain);
 
         // ensure all of the necessary values are valid
-        if (!cdomain || !cpath || !cvalue) {
+        if (expired || !cdomain || !cpath || !cvalue ) {
             av_log(s, AV_LOG_WARNING,
-                   "Invalid cookie found, no value, path or domain specified\n");
+                   "Invalid cookie found, expired or no value, path or domain specified\n");
             goto done_cookie;
         }