pidgin: 150db837: A few changes to our code to handle chun...

markdoliner at pidgin.im markdoliner at pidgin.im
Thu Jul 2 03:35:27 EDT 2009


-----------------------------------------------------------------
Revision: 150db837b012d157fec1d94919808a3125b7d1a4
Ancestor: bbca51d4ecb2cb1f3eb8ebf0de5f8c8ad6d0893e
Author: markdoliner at pidgin.im
Date: 2009-07-02T07:33:17
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/150db837b012d157fec1d94919808a3125b7d1a4

Modified files:
        libpurple/util.c

ChangeLog: 

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

-------------- next part --------------
============================================================
--- libpurple/util.c	1a552bb60cb8f950190972e5245f16443fce7cc8
+++ libpurple/util.c	10ff4dd275fe591ee44e41da047659cd7fbe5cf6
@@ -3788,32 +3788,56 @@ process_chunked_data(char *data, gsize *
 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


More information about the Commits mailing list