From 3d33dfd16166e302bb77ba98559a6acdf456d8a5 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 21 Nov 2009 10:29:00 -0500 Subject: [PATCH] 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); -- 2.7.4