# HG changeset patch # User Mark Doliner # Date 1246519997 0 # Node ID e28b627be4820b84e6a10d03e410c0875c74abf9 # Parent a051f77d86a8b781ede1d8a8f9ad47f2c20ad2b0 A few changes to our code to handle chunked transfer-encodings (technically required for http 1.1 clients, but I guess it hasn't been a problem until now?) * Most importantly, check that the size of this chunk is less than the size of the data remaining in the buffer. Otherwise malicious servers could cause us to crash * Handle reading chunks that have a semi-colon after them. It seems like maybe this is allowed but almost never used? * Assume len is non-NULL (it always is in our case) * Add some comments diff -r a051f77d86a8 -r e28b627be482 libpurple/util.c --- a/libpurple/util.c Thu Jul 02 07:09:24 2009 +0000 +++ b/libpurple/util.c Thu Jul 02 07:33:17 2009 +0000 @@ -3788,32 +3788,56 @@ process_chunked_data(char *data, gsize *len) { gsize sz; - gsize nlen = 0; + gsize newlen = 0; char *p = data; char *s = data; while (*s) { - if (sscanf(s, "%" G_GSIZE_MODIFIER "x\r\n", &sz) != 1) { - purple_debug_error("util", "Error processing chunked data. Expected data length, found: %s\n", s); + /* Read the size of this chunk */ + if (sscanf(s, "%" G_GSIZE_MODIFIER "x\r\n", &sz) != 1 && + sscanf(s, "%" G_GSIZE_MODIFIER "x;", &sz) != 1) + { + purple_debug_error("util", "Error processing chunked data: " + "Expected data length, found: %s\n", s); break; } - if (sz == 0) + if (sz == 0) { + /* We've reached the last chunk */ + /* + * TODO: The spec allows "footers" to follow the last chunk. + * If there is more data after this line then we should + * treat it like a header. + */ break; + } + + /* Advance to the start of the data */ s = strstr(s, "\r\n") + 2; + + if (s + sz > data + *len) { + purple_debug_error("util", "Error processing chunked data: " + "Chunk size %" G_GSIZE_FORMAT " bytes was longer " + "than the data remaining in the buffer (%" + G_GSIZE_FORMAT " bytes)\n", sz, data + *len - s); + } + + /* Move all data overtop of the chunk length that we read in earlier */ g_memmove(p, s, sz); p += sz; s += sz; - nlen += sz; + newlen += sz; if (*s != '\r' && *(s + 1) != '\n') { - purple_debug_error("util", "Error processing chunked data. Expected \\r\\n, found: %s\n", s); + purple_debug_error("util", "Error processing chunked data: " + "Expected \\r\\n, found: %s\n", s); break; } s += 2; } + + /* NULL terminate the data */ *p = 0; - if (len) - *len = nlen; + *len = newlen; } static void