|
| 1 | +From 0cd5cb7d61ec22b60ce21f84f91a1d8da930eff6 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Kshitiz Godara <kgodara@microsoft.com> |
| 3 | +Date: Sun, 4 May 2025 12:46:20 +0000 |
| 4 | +Subject: [PATCH 1/6] Combined two patches to address CVE-2025-2784 |
| 5 | + |
| 6 | +Upstream references: |
| 7 | +https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/435/diffs |
| 8 | +https://gitlab.gnome.org/GNOME/libsoup/-/commit/c415ad0b6771992e66c70edf373566c6e247089d |
| 9 | +--- |
| 10 | + .../content-sniffer/soup-content-sniffer.c | 10 ++-- |
| 11 | + tests/meson.build | 4 +- |
| 12 | + tests/sniffing-test.c | 48 +++++++++++++++++++ |
| 13 | + 3 files changed, 56 insertions(+), 6 deletions(-) |
| 14 | + |
| 15 | +diff --git a/libsoup/content-sniffer/soup-content-sniffer.c b/libsoup/content-sniffer/soup-content-sniffer.c |
| 16 | +index 2351c3f..150d285 100644 |
| 17 | +--- a/libsoup/content-sniffer/soup-content-sniffer.c |
| 18 | ++++ b/libsoup/content-sniffer/soup-content-sniffer.c |
| 19 | +@@ -638,8 +638,11 @@ sniff_text_or_binary (SoupContentSniffer *sniffer, GBytes *buffer) |
| 20 | + } |
| 21 | + |
| 22 | + static gboolean |
| 23 | +-skip_insignificant_space (const char *resource, int *pos, int resource_length) |
| 24 | ++skip_insignificant_space (const char *resource, gsize *pos, gsize resource_length) |
| 25 | + { |
| 26 | ++ if (*pos >= resource_length) |
| 27 | ++ return TRUE; |
| 28 | ++ |
| 29 | + while ((resource[*pos] == '\x09') || |
| 30 | + (resource[*pos] == '\x20') || |
| 31 | + (resource[*pos] == '\x0A') || |
| 32 | +@@ -659,7 +662,7 @@ sniff_feed_or_html (SoupContentSniffer *sniffer, GBytes *buffer) |
| 33 | + gsize resource_length; |
| 34 | + const char *resource = g_bytes_get_data (buffer, &resource_length); |
| 35 | + resource_length = MIN (512, resource_length); |
| 36 | +- int pos = 0; |
| 37 | ++ gsize pos = 0; |
| 38 | + |
| 39 | + if (resource_length < 3) |
| 40 | + goto text_html; |
| 41 | +@@ -669,9 +672,6 @@ sniff_feed_or_html (SoupContentSniffer *sniffer, GBytes *buffer) |
| 42 | + pos = 3; |
| 43 | + |
| 44 | + look_for_tag: |
| 45 | +- if (pos > resource_length) |
| 46 | +- goto text_html; |
| 47 | +- |
| 48 | + if (skip_insignificant_space (resource, &pos, resource_length)) |
| 49 | + goto text_html; |
| 50 | + |
| 51 | +diff --git a/tests/meson.build b/tests/meson.build |
| 52 | +index 9bf88be..b4112ec 100644 |
| 53 | +--- a/tests/meson.build |
| 54 | ++++ b/tests/meson.build |
| 55 | +@@ -94,7 +94,9 @@ tests = [ |
| 56 | + {'name': 'session'}, |
| 57 | + {'name': 'server-auth'}, |
| 58 | + {'name': 'server'}, |
| 59 | +- {'name': 'sniffing'}, |
| 60 | ++ {'name': 'sniffing', |
| 61 | ++ 'depends': [test_resources], |
| 62 | ++ }, |
| 63 | + {'name': 'ssl', |
| 64 | + 'dependencies': [gnutls_dep], |
| 65 | + 'depends': mock_pkcs11_module, |
| 66 | +diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c |
| 67 | +index 6116719..7857732 100644 |
| 68 | +--- a/tests/sniffing-test.c |
| 69 | ++++ b/tests/sniffing-test.c |
| 70 | +@@ -342,6 +342,52 @@ test_disabled (gconstpointer data) |
| 71 | + g_uri_unref (uri); |
| 72 | + } |
| 73 | + |
| 74 | ++static const gsize MARKUP_LENGTH = strlen ("<!--") + strlen ("-->"); |
| 75 | ++ |
| 76 | ++static void |
| 77 | ++do_skip_whitespace_test (void) |
| 78 | ++{ |
| 79 | ++ SoupContentSniffer *sniffer = soup_content_sniffer_new (); |
| 80 | ++ SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "http://example.org"); |
| 81 | ++ const char *test_cases[] = { |
| 82 | ++ "", |
| 83 | ++ "<rdf:RDF", |
| 84 | ++ "<rdf:RDFxmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"", |
| 85 | ++ "<rdf:RDFxmlns=\"http://purl.org/rss/1.0/\"", |
| 86 | ++ }; |
| 87 | ++ |
| 88 | ++ soup_message_headers_set_content_type (soup_message_get_response_headers (msg), "text/html", NULL); |
| 89 | ++ |
| 90 | ++ for (guint i = 0; i < G_N_ELEMENTS (test_cases); i++) { |
| 91 | ++ const char *trailing_data = test_cases[i]; |
| 92 | ++ gsize leading_zeros = 512 - MARKUP_LENGTH - strlen (trailing_data); |
| 93 | ++ gsize testsize = MARKUP_LENGTH + leading_zeros + strlen (trailing_data); |
| 94 | ++ guint8 *data = g_malloc0 (testsize); |
| 95 | ++ guint8 *p = data; |
| 96 | ++ char *content_type; |
| 97 | ++ GBytes *buffer; |
| 98 | ++ |
| 99 | ++ // Format of <!--[0x00 * $leading_zeros]-->$trailing_data |
| 100 | ++ memcpy (p, "<!--", strlen ("<!--")); |
| 101 | ++ p += strlen ("<!--"); |
| 102 | ++ p += leading_zeros; |
| 103 | ++ memcpy (p, "-->", strlen ("-->")); |
| 104 | ++ p += strlen ("-->"); |
| 105 | ++ if (strlen (trailing_data)) |
| 106 | ++ memcpy (p, trailing_data, strlen (trailing_data)); |
| 107 | ++ // Purposefully not NUL terminated. |
| 108 | ++ |
| 109 | ++ buffer = g_bytes_new_take (g_steal_pointer (&data), testsize); |
| 110 | ++ content_type = soup_content_sniffer_sniff (sniffer, msg, buffer, NULL); |
| 111 | ++ |
| 112 | ++ g_free (content_type); |
| 113 | ++ g_bytes_unref (buffer); |
| 114 | ++ } |
| 115 | ++ |
| 116 | ++ g_object_unref (msg); |
| 117 | ++ g_object_unref (sniffer); |
| 118 | ++} |
| 119 | ++ |
| 120 | + int |
| 121 | + main (int argc, char **argv) |
| 122 | + { |
| 123 | +@@ -517,6 +563,8 @@ main (int argc, char **argv) |
| 124 | + "/text_or_binary/home.gif", |
| 125 | + test_disabled); |
| 126 | + |
| 127 | ++ g_test_add_func ("/sniffing/whitespace", do_skip_whitespace_test); |
| 128 | ++ |
| 129 | + ret = g_test_run (); |
| 130 | + |
| 131 | + g_uri_unref (base_uri); |
| 132 | +-- |
| 133 | +2.45.3 |
| 134 | + |
0 commit comments