Mercurial > pidgin.yaz
changeset 27328:e28b627be482
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
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 02 Jul 2009 07:33:17 +0000 |
parents | a051f77d86a8 |
children | b0f0579f5f22 |
files | libpurple/util.c |
diffstat | 1 files changed, 32 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- 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