[libsoup] soup_multipart_new_from_message: fix to work with binary attachments



commit 3d33dfd16166e302bb77ba98559a6acdf456d8a5
Author: Dan Winship <danw gnome org>
Date:   Sat Nov 21 10:29:00 2009 -0500

    soup_multipart_new_from_message: fix to work with binary attachments
    
    Previously we were using strstr() to find the multipart boundary, so
    it would fail if the body contained '\0' bytes. Update
    tests/forms-test to test this case.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=601640

 libsoup/soup-multipart.c |   41 ++++++++++++++++++++++++++---------------
 tests/forms-test.c       |   20 +++++++++++++-------
 2 files changed, 39 insertions(+), 22 deletions(-)
---
diff --git a/libsoup/soup-multipart.c b/libsoup/soup-multipart.c
index 67f0e9c..dd0287c 100644
--- a/libsoup/soup-multipart.c
+++ b/libsoup/soup-multipart.c
@@ -98,19 +98,27 @@ soup_multipart_new (const char *mime_type)
 }
 
 static const char *
-find_boundary (const char *start, const char *boundary, int boundary_len)
+find_boundary (const char *start, const char *end,
+	       const char *boundary, int boundary_len)
 {
-	const char *b, *end;
-
-	end = start + 2;
-	while ((b = strstr (end, boundary))) {
-		end = b + boundary_len;
-		if (b[-1] == '-' && b[-2] == '-' &&
-		    (b == start + 2 || (b[-3] == '\n' && b[-4] == '\r'))) {
-			if ((end[0] == '-' && end[1] == '-') ||
-			    (end[0] == '\r' && end[1] == '\n'))
-				return b - 2;
-		}
+	const char *b;
+
+	for (b = memchr (start, '-', end - start);
+	     b && b + boundary_len + 4 < end;
+	     b = memchr (b + 2, '-', end - (b + 2))) {
+		/* Check for "--boundary" */
+		if (b[1] != '-' ||
+		    memcmp (b + 2, boundary, boundary_len) != 0)
+			continue;
+
+		/* Check that it's at start of line */
+		if (!(b == start || (b[-1] == '\n' && b[-2] == '\r')))
+			continue;
+
+		/* Check for "--" or "\r\n" after boundary */
+		if ((b[boundary_len + 2] == '-' && b[boundary_len + 3] == '-') ||
+		    (b[boundary_len + 2] == '\r' && b[boundary_len + 3] == '\n'))
+			return b;
 	}
 	return NULL;
 }
@@ -136,7 +144,7 @@ soup_multipart_new_from_message (SoupMessageHeaders *headers,
 	GHashTable *params;
 	int boundary_len;
 	SoupBuffer *flattened;
-	const char *start, *split, *end;
+	const char *start, *split, *end, *body_end;
 	SoupMessageHeaders *part_headers;
 	SoupBuffer *part_body;
 
@@ -155,11 +163,13 @@ soup_multipart_new_from_message (SoupMessageHeaders *headers,
 	g_hash_table_destroy (params);
 
 	flattened = soup_message_body_flatten (body);
+	body_end = flattened->data + flattened->length;
 	boundary = multipart->boundary;
 	boundary_len = strlen (boundary);
 
 	/* skip preamble */
-	start = find_boundary (flattened->data, boundary, boundary_len);
+	start = find_boundary (flattened->data, body_end,
+			       boundary, boundary_len);
 	if (!start) {
 		soup_multipart_free (multipart);
 		soup_buffer_free (flattened);
@@ -167,7 +177,8 @@ soup_multipart_new_from_message (SoupMessageHeaders *headers,
 	}
 
 	while (start[2 + boundary_len] != '-') {
-		end = find_boundary (start + 2 + boundary_len, boundary, boundary_len);
+		end = find_boundary (start + 2 + boundary_len, body_end,
+				     boundary, boundary_len);
 		if (!end) {
 			soup_multipart_free (multipart);
 			soup_buffer_free (flattened);
diff --git a/tests/forms-test.c b/tests/forms-test.c
index e48c9c9..8a7443c 100644
--- a/tests/forms-test.c
+++ b/tests/forms-test.c
@@ -158,8 +158,13 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5)
 	g_free (file_arg);
 }
 
+#define MD5_TEST_FILE SRCDIR "/resources/home.gif"
+#define MD5_TEST_FILE_BASENAME "home.gif"
+#define MD5_TEST_FILE_MIME_TYPE "image/gif"
+
 static void
-do_md5_test_libsoup (const char *uri, const char *contents, const char *md5)
+do_md5_test_libsoup (const char *uri, const char *contents,
+		     gsize length, const char *md5)
 {
 	SoupMultipart *multipart;
 	SoupBuffer *buffer;
@@ -169,9 +174,10 @@ do_md5_test_libsoup (const char *uri, const char *contents, const char *md5)
 	debug_printf (1, "  via libsoup: ");
 
 	multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
-	buffer = soup_buffer_new (SOUP_MEMORY_COPY, contents, strlen (contents));
+	buffer = soup_buffer_new (SOUP_MEMORY_COPY, contents, length);
 	soup_multipart_append_form_file (multipart, "file",
-					 "index.txt", "text/plain",
+					 MD5_TEST_FILE_BASENAME,
+					 MD5_TEST_FILE_MIME_TYPE,
 					 buffer);
 	soup_buffer_free (buffer);
 	soup_multipart_append_form_string (multipart, "fmt", "text");
@@ -206,8 +212,8 @@ do_md5_tests (const char *uri)
 
 	debug_printf (1, "\nMD5 tests (POST, multipart/form-data)\n");
 
-	if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) {
-		debug_printf (1, "  ERROR: Could not read " SRCDIR "/index.txt: %s\n", error->message);
+	if (!g_file_get_contents (MD5_TEST_FILE, &contents, &length, &error)) {
+		debug_printf (1, "  ERROR: Could not read " MD5_TEST_FILE ": %s\n", error->message);
 		g_error_free (error);
 		errors++;
 		return;
@@ -215,8 +221,8 @@ do_md5_tests (const char *uri)
 
 	md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, contents, length);
 
-	do_md5_test_curl (uri, SRCDIR "/index.txt", md5);
-	do_md5_test_libsoup (uri, contents, md5);
+	do_md5_test_curl (uri, MD5_TEST_FILE, md5);
+	do_md5_test_libsoup (uri, contents, length, md5);
 
 	g_free (contents);
 	g_free (md5);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]