Submitted By: Douglas R. Reno Date: 2025-05-19 Initial Package Version: 2.74.3 Upstream Status: Not Applied (migrate to 3.0) Origin: Debian (https://sources.debian.org/patches/libsoup2.4/2.74.3-10.1/) Description: Applies all of Debian's backports for the recent libsoup security issues. These issues allow for remote code execution, remotely exploitable denial of service, HTTP Request Smuggling, and for users to remotely crash some HTTP servers. The vulnerabilities include CVE-2024-52530, CVE-2024-52531, CVE-2024-52532, CVE-2025-2784, CVE-2025-32050, CVE-2025-32052, CVE-2025-32053, CVE-2025-32906, CVE-2025-32909, CVE-2025-32910, CVE-2025-32911, CVE-2025-32912, CVE-2025-32914, and CVE-2025-46420. The patch has been tested with gst-plugins-good, gst-plugins-bad, libgdata, and Abiword - but note that this package as well as Abiword and libgdata have been archived from LFS because it is unmaintained and applications should have already moved to libsoup3. diff -Naurp libsoup-2.74.3.orig/libsoup/soup-auth-digest.c libsoup-2.74.3/libsoup/soup-auth-digest.c --- libsoup-2.74.3.orig/libsoup/soup-auth-digest.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/libsoup/soup-auth-digest.c 2025-05-19 15:43:32.015104117 -0500 @@ -66,6 +66,7 @@ soup_auth_digest_finalize (GObject *obje g_free (priv->nonce); g_free (priv->domain); g_free (priv->cnonce); + g_free (priv->opaque); memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); @@ -133,6 +134,19 @@ soup_auth_digest_get_qop (SoupAuthDigest } static gboolean +validate_params (SoupAuthDigest *auth_digest) +{ + SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); + + if (priv->qop || priv->algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS) { + if (!priv->nonce) + return FALSE; + } + + return TRUE; +} + +static gboolean soup_auth_digest_update (SoupAuth *auth, SoupMessage *msg, GHashTable *auth_params) { @@ -142,6 +156,9 @@ soup_auth_digest_update (SoupAuth *auth, guint qop_options; gboolean ok = TRUE; + if (!soup_auth_get_realm (auth) || !g_hash_table_lookup (auth_params, "nonce")) + return FALSE; + g_free (priv->domain); g_free (priv->nonce); g_free (priv->opaque); @@ -166,16 +183,21 @@ soup_auth_digest_update (SoupAuth *auth, if (priv->algorithm == -1) ok = FALSE; - stale = g_hash_table_lookup (auth_params, "stale"); - if (stale && !g_ascii_strcasecmp (stale, "TRUE") && *priv->hex_urp) - recompute_hex_a1 (priv); - else { - g_free (priv->user); - priv->user = NULL; - g_free (priv->cnonce); - priv->cnonce = NULL; - memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); - memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); + if (!validate_params (auth_digest)) + ok = FALSE; + + if (ok) { + stale = g_hash_table_lookup (auth_params, "stale"); + if (stale && !g_ascii_strcasecmp (stale, "TRUE") && *priv->hex_urp) + recompute_hex_a1 (priv); + else { + g_free (priv->user); + priv->user = NULL; + g_free (priv->cnonce); + priv->cnonce = NULL; + memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); + memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); + } } return ok; @@ -266,6 +288,8 @@ soup_auth_digest_compute_hex_a1 (const c /* In MD5-sess, A1 is hex_urp:nonce:cnonce */ + g_assert (nonce && cnonce); + checksum = g_checksum_new (G_CHECKSUM_MD5); g_checksum_update (checksum, (guchar *)hex_urp, strlen (hex_urp)); g_checksum_update (checksum, (guchar *)":", 1); @@ -356,6 +380,8 @@ soup_auth_digest_compute_response (const if (qop) { char tmp[9]; + g_assert (cnonce); + g_snprintf (tmp, 9, "%.8x", nc); g_checksum_update (checksum, (guchar *)tmp, strlen (tmp)); g_checksum_update (checksum, (guchar *)":", 1); @@ -419,6 +445,8 @@ soup_auth_digest_get_authorization (Soup g_return_val_if_fail (uri != NULL, NULL); url = soup_uri_to_string (uri, TRUE); + g_assert (priv->nonce); + g_assert (!priv->qop || priv->cnonce); soup_auth_digest_compute_response (msg->method, url, priv->hex_a1, priv->qop, priv->nonce, priv->cnonce, priv->nc, diff -Naurp libsoup-2.74.3.orig/libsoup/soup-content-sniffer.c libsoup-2.74.3/libsoup/soup-content-sniffer.c --- libsoup-2.74.3.orig/libsoup/soup-content-sniffer.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/libsoup/soup-content-sniffer.c 2025-05-19 15:42:59.261346630 -0500 @@ -227,9 +227,14 @@ sniff_mp4 (SoupContentSniffer *sniffer, { const char *resource = (const char *)buffer->data; guint resource_length = MIN (512, buffer->length); - guint32 box_size = *((guint32*)resource); + guint32 box_size; guint i; + if (resource_length < sizeof (guint32)) + return FALSE; + + box_size = *((guint32*)resource); + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ box_size = ((box_size >> 24) | ((box_size << 8) & 0x00FF0000) | @@ -504,7 +509,7 @@ sniff_unknown (SoupContentSniffer *sniff guint index_pattern = 0; gboolean skip_row = FALSE; - while ((index_stream < resource_length) && + while ((index_stream < resource_length - 1) && (index_pattern <= type_row->pattern_length)) { /* Skip insignificant white space ("WS" in the spec) */ if (type_row->pattern[index_pattern] == ' ') { @@ -612,15 +617,18 @@ sniff_text_or_binary (SoupContentSniffer } static gboolean -skip_insignificant_space (const char *resource, int *pos, int resource_length) +skip_insignificant_space (const char *resource, gsize *pos, gsize resource_length) { + if (*pos >= resource_length) + return TRUE; + while ((resource[*pos] == '\x09') || (resource[*pos] == '\x20') || (resource[*pos] == '\x0A') || (resource[*pos] == '\x0D')) { *pos = *pos + 1; - if (*pos > resource_length) + if (*pos >= resource_length) return TRUE; } @@ -632,7 +640,7 @@ sniff_feed_or_html (SoupContentSniffer * { const char *resource = (const char *)buffer->data; int resource_length = MIN (512, buffer->length); - int pos = 0; + gsize pos = 0; if (resource_length < 3) goto text_html; @@ -642,9 +650,6 @@ sniff_feed_or_html (SoupContentSniffer * pos = 3; look_for_tag: - if (pos > resource_length) - goto text_html; - if (skip_insignificant_space (resource, &pos, resource_length)) goto text_html; @@ -682,7 +687,7 @@ sniff_feed_or_html (SoupContentSniffer * do { pos++; - if (pos > resource_length) + if ((pos + 1) > resource_length) goto text_html; } while (resource[pos] != '>'); diff -Naurp libsoup-2.74.3.orig/libsoup/soup-headers.c libsoup-2.74.3/libsoup/soup-headers.c --- libsoup-2.74.3.orig/libsoup/soup-headers.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/libsoup/soup-headers.c 2025-05-19 15:43:46.154999461 -0500 @@ -50,13 +50,14 @@ soup_headers_parse (const char *str, int * ignorable trailing whitespace. */ + /* No '\0's are allowed */ + if (memchr (str, '\0', len)) + return FALSE; + /* Skip over the Request-Line / Status-Line */ headers_start = memchr (str, '\n', len); if (!headers_start) return FALSE; - /* No '\0's in the Request-Line / Status-Line */ - if (memchr (str, '\0', headers_start - str)) - return FALSE; /* We work on a copy of the headers, which we can write '\0's * into, so that we don't have to individually g_strndup and @@ -68,14 +69,6 @@ soup_headers_parse (const char *str, int headers_copy[copy_len] = '\0'; value_end = headers_copy; - /* There shouldn't be any '\0's in the headers already, but - * this is the web we're talking about. - */ - while ((p = memchr (headers_copy, '\0', copy_len))) { - memmove (p, p + 1, copy_len - (p - headers_copy)); - copy_len--; - } - while (*(value_end + 1)) { name = value_end + 1; name_end = strchr (name, ':'); @@ -192,7 +185,7 @@ soup_headers_parse_request (const char /* RFC 2616 4.1 "servers SHOULD ignore any empty line(s) * received where a Request-Line is expected." */ - while ((*str == '\r' || *str == '\n') && len > 0) { + while (len > 0 && (*str == '\r' || *str == '\n')) { str++; len--; } @@ -231,7 +224,7 @@ soup_headers_parse_request (const char !g_ascii_isdigit (version[5])) return SOUP_STATUS_BAD_REQUEST; major_version = strtoul (version + 5, &p, 10); - if (*p != '.' || !g_ascii_isdigit (p[1])) + if (p + 1 >= str + len || *p != '.' || !g_ascii_isdigit (p[1])) return SOUP_STATUS_BAD_REQUEST; minor_version = strtoul (p + 1, &p, 10); version_end = p; @@ -376,7 +369,7 @@ soup_headers_parse_response (const char * after a response, which we then see prepended to the next * response on that connection. */ - while ((*str == '\r' || *str == '\n') && len > 0) { + while (len > 0 && (*str == '\r' || *str == '\n')) { str++; len--; } @@ -535,7 +528,7 @@ soup_header_parse_quality_list (const ch GSList *unsorted; QualityItem *array; GSList *sorted, *iter; - char *item, *semi; + char *semi; const char *param, *equal, *value; double qval; int n; @@ -548,9 +541,8 @@ soup_header_parse_quality_list (const ch unsorted = soup_header_parse_list (header); array = g_new0 (QualityItem, g_slist_length (unsorted)); for (iter = unsorted, n = 0; iter; iter = iter->next) { - item = iter->data; qval = 1.0; - for (semi = strchr (item, ';'); semi; semi = strchr (semi + 1, ';')) { + for (semi = strchr (iter->data, ';'); semi; semi = strchr (semi + 1, ';')) { param = skip_lws (semi + 1); if (*param != 'q') continue; @@ -582,15 +574,15 @@ soup_header_parse_quality_list (const ch if (qval == 0.0) { if (unacceptable) { *unacceptable = g_slist_prepend (*unacceptable, - item); + g_steal_pointer (&iter->data)); } } else { - array[n].item = item; + array[n].item = g_steal_pointer (&iter->data); array[n].qval = qval; n++; } } - g_slist_free (unsorted); + g_slist_free_full (unsorted, g_free); qsort (array, n, sizeof (QualityItem), sort_by_qval); sorted = NULL; @@ -650,8 +642,9 @@ soup_header_contains (const char *header } static void -decode_quoted_string (char *quoted_string) +decode_quoted_string_inplace (GString *quoted_gstring) { + char *quoted_string = quoted_gstring->str; char *src, *dst; src = quoted_string + 1; @@ -665,10 +658,11 @@ decode_quoted_string (char *quoted_strin } static gboolean -decode_rfc5987 (char *encoded_string) +decode_rfc5987_inplace (GString *encoded_gstring) { char *q, *decoded; gboolean iso_8859_1 = FALSE; + const char *encoded_string = encoded_gstring->str; q = strchr (encoded_string, '\''); if (!q) @@ -697,14 +691,7 @@ decode_rfc5987 (char *encoded_string) decoded = utf8; } - /* If encoded_string was UTF-8, then each 3-character %-escape - * will be converted to a single byte, and so decoded is - * shorter than encoded_string. If encoded_string was - * iso-8859-1, then each 3-character %-escape will be - * converted into at most 2 bytes in UTF-8, and so it's still - * shorter. - */ - strcpy (encoded_string, decoded); + g_string_assign (encoded_gstring, decoded); g_free (decoded); return TRUE; } @@ -714,15 +701,17 @@ parse_param_list (const char *header, ch { GHashTable *params; GSList *list, *iter; - char *item, *eq, *name_end, *value; - gboolean override, duplicated; params = g_hash_table_new_full (soup_str_case_hash, soup_str_case_equal, - g_free, NULL); + g_free, g_free); list = parse_list (header, delim); for (iter = list; iter; iter = iter->next) { + char *item, *eq, *name_end; + gboolean override, duplicated; + GString *parsed_value = NULL; + item = iter->data; override = FALSE; @@ -737,19 +726,19 @@ parse_param_list (const char *header, ch *name_end = '\0'; - value = (char *)skip_lws (eq + 1); + parsed_value = g_string_new ((char *)skip_lws (eq + 1)); if (name_end[-1] == '*' && name_end > item + 1) { name_end[-1] = '\0'; - if (!decode_rfc5987 (value)) { + if (!decode_rfc5987_inplace (parsed_value)) { + g_string_free (parsed_value, TRUE); g_free (item); continue; } override = TRUE; - } else if (*value == '"') - decode_quoted_string (value); - } else - value = NULL; + } else if (parsed_value->str[0] == '"') + decode_quoted_string_inplace (parsed_value); + } duplicated = g_hash_table_lookup_extended (params, item, NULL, NULL); @@ -757,11 +746,16 @@ parse_param_list (const char *header, ch soup_header_free_param_list (params); params = NULL; g_slist_foreach (iter, (GFunc)g_free, NULL); + if (parsed_value) + g_string_free (parsed_value, TRUE); break; - } else if (override || !duplicated) - g_hash_table_replace (params, item, value); - else + } else if (override || !duplicated) { + g_hash_table_replace (params, item, parsed_value ? g_string_free (parsed_value, FALSE) : NULL); + } else { + if (parsed_value) + g_string_free (parsed_value, TRUE); g_free (item); + } } g_slist_free (list); @@ -910,7 +904,7 @@ append_param_quoted (GString *string, const char *name, const char *value) { - int len; + gsize len; g_string_append (string, name); g_string_append (string, "=\""); diff -Naurp libsoup-2.74.3.orig/libsoup/soup-message-headers.c libsoup-2.74.3/libsoup/soup-message-headers.c --- libsoup-2.74.3.orig/libsoup/soup-message-headers.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/libsoup/soup-message-headers.c 2025-05-19 15:43:23.110170038 -0500 @@ -1454,10 +1454,15 @@ soup_message_headers_get_content_disposi */ if (params && g_hash_table_lookup_extended (*params, "filename", &orig_key, &orig_value)) { - char *filename = strrchr (orig_value, '/'); + if (orig_value) { + char *filename = strrchr (orig_value, '/'); - if (filename) - g_hash_table_insert (*params, g_strdup (orig_key), filename + 1); + if (filename) + g_hash_table_insert (*params, g_strdup (orig_key), g_strdup (filename + 1)); + } else { + /* filename with no value isn't valid. */ + g_hash_table_remove (*params, "filename"); + } } return TRUE; } diff -Naurp libsoup-2.74.3.orig/libsoup/soup-multipart.c libsoup-2.74.3/libsoup/soup-multipart.c --- libsoup-2.74.3.orig/libsoup/soup-multipart.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/libsoup/soup-multipart.c 2025-05-19 15:43:36.231072910 -0500 @@ -181,7 +181,7 @@ soup_multipart_new_from_message (SoupMes return NULL; } - split = strstr (start, "\r\n\r\n"); + split = g_strstr_len (start, body_end - start, "\r\n\r\n"); if (!split || split > end) { soup_multipart_free (multipart); soup_buffer_free (flattened); diff -Naurp libsoup-2.74.3.orig/libsoup/soup-websocket-connection.c libsoup-2.74.3/libsoup/soup-websocket-connection.c --- libsoup-2.74.3.orig/libsoup/soup-websocket-connection.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/libsoup/soup-websocket-connection.c 2025-05-19 15:41:57.436804738 -0500 @@ -1140,9 +1140,9 @@ soup_websocket_connection_read (SoupWebs } pv->incoming->len = len + count; - } while (count > 0); - process_incoming (self); + process_incoming (self); + } while (count > 0 && !pv->close_sent && !pv->io_closing); if (end) { if (!pv->close_sent || !pv->close_received) { diff -Naurp libsoup-2.74.3.orig/meson.build libsoup-2.74.3/meson.build --- libsoup-2.74.3.orig/meson.build 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/meson.build 2025-05-19 15:41:47.012882026 -0500 @@ -125,6 +125,9 @@ endif cdata = configuration_data() +cdata.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_2_70') +cdata.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_70') + brotlidec_dep = dependency('libbrotlidec', required : get_option('brotli')) if brotlidec_dep.found() cdata.set('WITH_BROTLI', true) diff -Naurp libsoup-2.74.3.orig/tests/auth-test.c libsoup-2.74.3/tests/auth-test.c --- libsoup-2.74.3.orig/tests/auth-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/auth-test.c 2025-05-19 15:43:28.386130980 -0500 @@ -1549,6 +1549,68 @@ do_cancel_after_retry_test (void) soup_test_session_abort_unref (session); } +//from upstream commit 9af7d0fc751f7afcd8b03bc827a4d3af0c4556f8 +static gboolean +on_digest_authenticate (SoupMessage *msg, + SoupAuth *auth, + gboolean retrying, + gpointer user_data) +{ + g_assert_false (retrying); + soup_auth_authenticate (auth, "user", "good"); + return TRUE; +} + +static void +on_request_read_for_missing_params (SoupServer *server, + SoupMessage *msg, + SoupClientContext *client, + gpointer user_data) +{ + const char *auth_header = user_data; + soup_message_headers_replace (msg->response_headers, "WWW-Authenticate", auth_header); +} + +static void +do_missing_params_test (gconstpointer auth_header) +{ + SoupSession *session; + SoupMessage *msg; + SoupServer *server; + SoupAuthDomain *digest_auth_domain; + gint status; + SoupURI *uri; + + server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + uri = soup_test_server_get_uri (server, "http", NULL); + + digest_auth_domain = soup_auth_domain_digest_new ( + "realm", "auth-test", + "auth-callback", server_digest_auth_callback, + NULL); + soup_auth_domain_add_path (digest_auth_domain, "/"); + soup_server_add_auth_domain (server, digest_auth_domain); + g_object_unref (digest_auth_domain); + + g_signal_connect (server, "request-read", + G_CALLBACK (on_request_read_for_missing_params), + (gpointer)auth_header); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + msg = soup_message_new_from_uri ("GET", uri); + g_signal_connect (session, "authenticate", + G_CALLBACK (on_digest_authenticate), + NULL); + + status = soup_session_send_message (session, msg); + + g_assert_cmpint (status, ==, SOUP_STATUS_UNAUTHORIZED); + soup_uri_free (uri); + soup_test_server_quit_unref (server); +} + int main (int argc, char **argv) { @@ -1576,6 +1638,10 @@ main (int argc, char **argv) g_test_add_func ("/auth/async-message-do-not-use-auth-cache", do_async_message_do_not_use_auth_cache_test); g_test_add_func ("/auth/authorization-header-request", do_message_has_authorization_header_test); g_test_add_func ("/auth/cancel-after-retry", do_cancel_after_retry_test); + g_test_add_data_func ("/auth/missing-params/realm", "Digest qop=\"auth\"", do_missing_params_test); + g_test_add_data_func ("/auth/missing-params/nonce", "Digest realm=\"auth-test\", qop=\"auth,auth-int\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"", do_missing_params_test); + g_test_add_data_func ("/auth/missing-params/nonce-md5-sess", "Digest realm=\"auth-test\", qop=\"auth,auth-int\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\" algorithm=\"MD5-sess\"", do_missing_params_test); + g_test_add_data_func ("/auth/missing-params/nonce-and-qop", "Digest realm=\"auth-test\"", do_missing_params_test); ret = g_test_run (); diff -Naurp libsoup-2.74.3.orig/tests/header-parsing-test.c libsoup-2.74.3/tests/header-parsing-test.c --- libsoup-2.74.3.orig/tests/header-parsing-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/header-parsing-test.c 2025-05-19 15:43:23.111170031 -0500 @@ -6,6 +6,15 @@ typedef struct { const char *name, *value; } Header; +/* These are not C strings to ensure going one byte over is not safe. */ +static char unterminated_http_version[] = { + 'G','E','T',' ','/',' ','H','T','T','P','/','1', '0', '0', '.' +}; + +static char only_newlines[] = { + '\n', '\n', '\n', '\n' +}; + static struct RequestTest { const char *description; const char *bugref; @@ -358,24 +367,6 @@ static struct RequestTest { } }, - { "NUL in header name", "760832", - "GET / HTTP/1.1\r\nHost\x00: example.com\r\n", 36, - SOUP_STATUS_OK, - "GET", "/", SOUP_HTTP_1_1, - { { "Host", "example.com" }, - { NULL } - } - }, - - { "NUL in header value", "760832", - "GET / HTTP/1.1\r\nHost: example\x00" "com\r\n", 35, - SOUP_STATUS_OK, - "GET", "/", SOUP_HTTP_1_1, - { { "Host", "examplecom" }, - { NULL } - } - }, - /************************/ /*** INVALID REQUESTS ***/ /************************/ @@ -401,6 +392,13 @@ static struct RequestTest { { { NULL } } }, + { "Long HTTP version terminating at missing minor version", "https://gitlab.gnome.org/GNOME/libsoup/-/issues/404", + unterminated_http_version, sizeof (unterminated_http_version), + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + { "Non-HTTP request", NULL, "GET / SOUP/1.1\r\nHost: example.com\r\n", -1, SOUP_STATUS_BAD_REQUEST, @@ -448,6 +446,28 @@ static struct RequestTest { SOUP_STATUS_EXPECTATION_FAILED, NULL, NULL, -1, { { NULL } } + }, + + // https://gitlab.gnome.org/GNOME/libsoup/-/issues/377 + { "NUL in header name", NULL, + "GET / HTTP/1.1\r\nHost\x00: example.com\r\n", 36, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "NUL in header value", NULL, + "HTTP/1.1 200 OK\r\nFoo: b\x00" "ar\r\n", 28, + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } + }, + + { "Only newlines", NULL, + only_newlines, sizeof (only_newlines), + SOUP_STATUS_BAD_REQUEST, + NULL, NULL, -1, + { { NULL } } } }; static const int num_reqtests = G_N_ELEMENTS (reqtests); @@ -620,22 +640,6 @@ static struct ResponseTest { { NULL } } }, - { "NUL in header name", "760832", - "HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28, - SOUP_HTTP_1_1, SOUP_STATUS_OK, "OK", - { { "Foo", "bar" }, - { NULL } - } - }, - - { "NUL in header value", "760832", - "HTTP/1.1 200 OK\r\nFoo: b\x00" "ar\r\n", 28, - SOUP_HTTP_1_1, SOUP_STATUS_OK, "OK", - { { "Foo", "bar" }, - { NULL } - } - }, - /********************************/ /*** VALID CONTINUE RESPONSES ***/ /********************************/ @@ -768,6 +772,19 @@ static struct ResponseTest { { { NULL } } }, + + // https://gitlab.gnome.org/GNOME/libsoup/-/issues/377 + { "NUL in header name", NULL, + "HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28, + -1, 0, NULL, + { { NULL } } + }, + + { "NUL in header value", "760832", + "HTTP/1.1 200 OK\r\nFoo: b\x00" "ar\r\n", 28, + -1, 0, NULL, + { { NULL } } + }, }; static const int num_resptests = G_N_ELEMENTS (resptests); @@ -1034,6 +1051,7 @@ do_param_list_tests (void) #define RFC5987_TEST_HEADER_FALLBACK "attachment; filename*=Unknown''t%FF%FF%FFst.txt; filename=\"test.txt\"" #define RFC5987_TEST_HEADER_NO_TYPE "filename=\"test.txt\"" #define RFC5987_TEST_HEADER_NO_TYPE_2 "filename=\"test.txt\"; foo=bar" +#define RFC5987_TEST_HEADER_EMPTY_FILENAME ";filename" static void do_content_disposition_tests (void) @@ -1135,6 +1153,20 @@ do_content_disposition_tests (void) g_assert_cmpstr (parameter2, ==, "bar"); g_hash_table_destroy (params); + /* Empty filename */ + soup_message_headers_clear (hdrs); + soup_message_headers_append (hdrs, "Content-Disposition", + RFC5987_TEST_HEADER_EMPTY_FILENAME); + if (!soup_message_headers_get_content_disposition (hdrs, + &disposition, + ¶ms)) { + soup_test_assert (FALSE, "empty filename decoding FAILED"); + return; + } + g_free (disposition); + g_assert_false (g_hash_table_contains (params, "filename")); + g_hash_table_destroy (params); + soup_message_headers_free (hdrs); /* Ensure that soup-multipart always quotes filename */ diff -Naurp libsoup-2.74.3.orig/tests/hsts-db-test.c libsoup-2.74.3/tests/hsts-db-test.c --- libsoup-2.74.3.orig/tests/hsts-db-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/hsts-db-test.c 2025-05-19 15:41:47.012882026 -0500 @@ -1,8 +1,9 @@ +#include "test-utils.h" + #include #include #include -#include "test-utils.h" #define DB_FILE "hsts-db.sqlite" diff -Naurp libsoup-2.74.3.orig/tests/multipart-test.c libsoup-2.74.3/tests/multipart-test.c --- libsoup-2.74.3.orig/tests/multipart-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/multipart-test.c 2025-05-19 15:43:52.789950360 -0500 @@ -479,6 +479,65 @@ test_multipart (gconstpointer data) g_main_loop_unref (loop); } +static void +test_multipart_bounds_good (void) +{ + #define TEXT "line1\r\nline2" + SoupMultipart *multipart; + SoupMessageHeaders *headers, *set_headers = NULL; + SoupMessageBody *body = NULL; + SoupBuffer *set_bytes = NULL; + const char *raw_data = "--123\r\nContent-Type: text/plain;\r\n\r\n" TEXT "\r\n--123--\r\n"; + gboolean success; + + headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + soup_message_headers_append (headers, "Content-Type", "multipart/mixed; boundary=\"123\""); + + body = soup_message_body_new (); + soup_message_body_append (body, SOUP_MEMORY_COPY, + raw_data, strlen (raw_data)); + + multipart = soup_multipart_new_from_message (headers, body); + + g_assert_nonnull (multipart); + g_assert_cmpint (soup_multipart_get_length (multipart), ==, 1); + success = soup_multipart_get_part (multipart, 0, &set_headers, &set_bytes); + g_assert_true (success); + g_assert_nonnull (set_headers); + g_assert_nonnull (set_bytes); + g_assert_cmpint (strlen (TEXT), ==, set_bytes->length); + g_assert_cmpstr ("text/plain", ==, soup_message_headers_get_content_type (set_headers, NULL)); + g_assert_cmpmem (TEXT, strlen (TEXT), set_bytes->data, set_bytes->length); + + soup_message_headers_free (headers); + + soup_multipart_free (multipart); + + #undef TEXT +} + +static void +test_multipart_bounds_bad (void) +{ + SoupMultipart *multipart; + SoupMessageHeaders *headers; + SoupMessageBody *body = NULL; + const char *raw_data = "--123\r\nContent-Type: text/plain;\r\nline1\r\nline2\r\n--123--\r\n"; + + headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + soup_message_headers_append (headers, "Content-Type", "multipart/mixed; boundary=\"123\""); + + body = soup_message_body_new (); + soup_message_body_append (body, SOUP_MEMORY_COPY, + raw_data, strlen (raw_data)); + + /* it did read out of raw_data/bytes bounds */ + multipart = soup_multipart_new_from_message (headers, body); + g_assert_null (multipart); + + soup_message_headers_free (headers); +} + int main (int argc, char **argv) { @@ -508,6 +567,8 @@ main (int argc, char **argv) g_test_add_data_func ("/multipart/sync", GINT_TO_POINTER (SYNC_MULTIPART), test_multipart); g_test_add_data_func ("/multipart/async", GINT_TO_POINTER (ASYNC_MULTIPART), test_multipart); g_test_add_data_func ("/multipart/async-small-reads", GINT_TO_POINTER (ASYNC_MULTIPART_SMALL_READS), test_multipart); + g_test_add_func ("/multipart/bounds-good", test_multipart_bounds_good); + g_test_add_func ("/multipart/bounds-bad", test_multipart_bounds_bad); ret = g_test_run (); diff -Naurp libsoup-2.74.3.orig/tests/pull-api-test.c libsoup-2.74.3/tests/pull-api-test.c --- libsoup-2.74.3.orig/tests/pull-api-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/pull-api-test.c 2025-05-19 15:41:07.621174231 -0500 @@ -511,11 +511,13 @@ main (int argc, char **argv) int ret; test_init (argc, argv, NULL); - apache_init (); base_uri = "http://127.0.0.1:47524/"; + #ifdef HAVE_APACHE - get_correct_response (base_uri); + if (apache_init ()) { + get_correct_response (base_uri); + } #endif g_test_add_data_func ("/pull-api/async/fast", base_uri, do_fast_async_test); @@ -525,7 +527,9 @@ main (int argc, char **argv) ret = g_test_run (); #ifdef HAVE_APACHE - soup_buffer_free (correct_response); + if (correct_response != NULL) { + soup_buffer_free (correct_response); + } #endif test_cleanup (); diff -Naurp libsoup-2.74.3.orig/tests/sniffing-test.c libsoup-2.74.3/tests/sniffing-test.c --- libsoup-2.74.3.orig/tests/sniffing-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/sniffing-test.c 2025-05-19 15:42:17.631655045 -0500 @@ -436,6 +436,52 @@ test_disabled (gconstpointer data) soup_uri_free (uri); } +static const gsize MARKUP_LENGTH = strlen (""); + +static void +do_skip_whitespace_test (void) +{ + SoupContentSniffer *sniffer = soup_content_sniffer_new (); + SoupMessage *msg = soup_message_new (SOUP_METHOD_GET, "http://example.org"); + const char *test_cases[] = { + "", + "response_headers, "text/html", NULL); + + for (guint i = 0; i < G_N_ELEMENTS (test_cases); i++) { + const char *trailing_data = test_cases[i]; + gsize leading_zeros = 512 - MARKUP_LENGTH - strlen (trailing_data); + gsize testsize = MARKUP_LENGTH + leading_zeros + strlen (trailing_data); + guint8 *data = g_malloc0 (testsize); + guint8 *p = data; + char *content_type; + GBytes *buffer; + + // Format of $trailing_data + memcpy (p, "", strlen ("-->")); + p += strlen ("-->"); + if (strlen (trailing_data)) + memcpy (p, trailing_data, strlen (trailing_data)); + // Purposefully not NUL terminated. + + buffer = g_bytes_new_take (g_steal_pointer (&data), testsize); + content_type = soup_content_sniffer_sniff (sniffer, msg, (SoupBuffer *) buffer, NULL); + + g_free (content_type); + g_bytes_unref (buffer); + } + + g_object_unref (msg); + g_object_unref (sniffer); +} + int main (int argc, char **argv) { @@ -610,6 +656,8 @@ main (int argc, char **argv) "/text_or_binary/home.gif", test_disabled); + g_test_add_func ("/sniffing/whitespace", do_skip_whitespace_test); + ret = g_test_run (); soup_uri_free (base_uri); diff -Naurp libsoup-2.74.3.orig/tests/ssl-test.c libsoup-2.74.3/tests/ssl-test.c --- libsoup-2.74.3.orig/tests/ssl-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/ssl-test.c 2025-05-19 15:40:21.519516502 -0500 @@ -370,6 +370,11 @@ do_tls_interaction_test (void) SOUP_TEST_SKIP_IF_NO_TLS; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable? https://gitlab.gnome.org/GNOME/libsoup/issues/120"); + return; + } + service = g_threaded_socket_service_new (1); address = g_inet_socket_address_new_from_string ("127.0.0.1", 0); g_socket_listener_add_address (G_SOCKET_LISTENER (service), address, diff -Naurp libsoup-2.74.3.orig/tests/test-cert.pem libsoup-2.74.3/tests/test-cert.pem --- libsoup-2.74.3.orig/tests/test-cert.pem 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/test-cert.pem 2025-05-19 15:42:41.278479831 -0500 @@ -1,6 +1,6 @@ -----BEGIN CERTIFICATE----- MIIC2zCCAcOgAwIBAgIJALRbg2WnuAAqMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV -BAMMCTEyNy4wLjAuMTAeFw0xNzA2MjAxNDI3MzBaFw0yNzA2MTgxNDI3MzBaMBQx +BAMMCTEyNy4wLjAuMTAeFw0yMTAyMTgwODA3MzBaFw00OTEyMzEwODA3MzRaMBQx EjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAKs4fuRuW77nORhOT9kbbU6BsjKW3GEsMc+ZSmXjINQWpfkES2hV+DQyzhm5 qh4OLi1vYtXoSbdQNDCbA8ybZJqR8m9F3ed8vobdSSQGxWpPdXTgz27x+TpiAc9P @@ -8,11 +8,11 @@ w83UuPvlu/0AxHJBFXVAg+id0yFu3wmGWYJHoAtv BKTRCkGsRSmPpJyGbU2Q96fjxnVfV9oYvQXeugUcSx/pTUCM/kDgD9QZCxG2rflX NWcqDFY3uO6ZR68Qwi/KouOa8rzrgAcwhFUI6Wz0Zwi1rzRtWK5WqC24aBUYz/tK hl8i88UDXSMh7spChdYDBGLhZyUCAwEAAaMwMC4wLAYDVR0RBCUwI4IJbG9jYWxo -b3N0hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQBj -+U8tebwg5/pof5Rht6TMHqeg6Fcr4OJkL2ph2g+T/AMTS7kEGeFIKJN5AZ+S/qIY -cdoDKHwc8+bCK/mG6DPmJ4z/2Eamb85YhplOLVrLRwfxRebTK9CtnjcjnflAiU9H -7vPVwXIvkwebhBSQNKTdkBlPXKaTNWXuygeFG2OVQkPf/KAxSdtg2R+owv/s802Z -HISk26wY9oFIQz6AiXWdrY1QqNOltZ7rlU5iofAH7X+9ryZlxPWj/gHg2YQRvvLl -dq6nCF+ED0ke7h0lg5nU0beKEygwli8DlLVbu0JK0PkARFp5t7wUtzC9DCjzvfOc -gxR44PyZX7/2oaTDm4PS +b3N0hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQAz +/qYTUuBGHgp7T1cfaJPnhx6U1SMfdJRtFoWOXDx+MNCK9GYkdMEabzRGUP5uNHO+ +PiZP/bMIHlpsbRA5AyyVf9Xv8JCujvYh24qYcBbwgZrfvNTm0D52P9JJm0SalTXS +kwwTj00DWGVfVzJR+wiwYGHRIlyXbHqQSRzv6+z9f/xY5gXw/KpCNYTuOJcXW7w6 +JfMrUnc9pphRUpcLkuuzOMKuB0dtWRc0mZIr7PZHt+0gitNZWA0bDYI3JI9tlK17 +nxBUSpGtJwDgH//b8ek/P0P9a5VzQbBC6lXtQUMdxg7ovfAI//IS8ekBoRKI0Wde +r2IpM9hKSBU3c2gGXcJC -----END CERTIFICATE----- diff -Naurp libsoup-2.74.3.orig/tests/test-utils.c libsoup-2.74.3/tests/test-utils.c --- libsoup-2.74.3.orig/tests/test-utils.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/test-utils.c 2025-05-19 15:41:23.331057670 -0500 @@ -147,11 +147,25 @@ have_curl(void) { #ifdef HAVE_APACHE +gboolean +check_apache (void) +{ + if (g_getenv ("SOUP_TESTS_ALREADY_RUNNING_APACHE")) + return TRUE; + + if (!apache_running) { + g_test_skip ("Failed to start apache"); + return FALSE; + } + + return TRUE; +} + static gboolean apache_cmd (const char *cmd) { GPtrArray *argv; - char *cwd, *pid_file; + char *cwd, *pid_file, *error_log; #ifdef HAVE_APACHE_2_4 char *default_runtime_dir; #endif @@ -170,6 +184,7 @@ apache_cmd (const char *cmd) default_runtime_dir = g_strdup_printf ("DefaultRuntimeDir %s", cwd); #endif pid_file = g_strdup_printf ("PidFile %s/httpd.pid", cwd); + error_log = g_strdup_printf ("ErrorLog %s/error.log", cwd); argv = g_ptr_array_new (); g_ptr_array_add (argv, APACHE_HTTPD); @@ -183,6 +198,8 @@ apache_cmd (const char *cmd) g_ptr_array_add (argv, default_runtime_dir); #endif g_ptr_array_add (argv, "-c"); + g_ptr_array_add (argv, error_log); + g_ptr_array_add (argv, "-c"); g_ptr_array_add (argv, pid_file); g_ptr_array_add (argv, "-k"); @@ -208,6 +225,7 @@ apache_cmd (const char *cmd) g_free (cwd); g_free (pid_file); + g_free (error_log); #ifdef HAVE_APACHE_2_4 g_free (default_runtime_dir); #endif @@ -217,21 +235,25 @@ apache_cmd (const char *cmd) return ok; } -void +gboolean apache_init (void) { /* Set this environment variable if you are already running a * suitably-configured Apache server */ if (g_getenv ("SOUP_TESTS_ALREADY_RUNNING_APACHE")) - return; + return TRUE; server_root = soup_test_build_filename_abs (G_TEST_BUILT, "", NULL); if (!apache_cmd ("start")) { g_printerr ("Could not start apache\n"); - exit (1); + apache_running = FALSE; + } + else { + apache_running = TRUE; } - apache_running = TRUE; + + return apache_running; } void @@ -255,6 +277,11 @@ apache_cleanup (void) g_usleep (100); } + if (g_file_get_contents ("error.log", &contents, NULL, NULL)) { + g_test_message ("error.log contents:\n%s", contents); + g_free (contents); + } + g_clear_pointer (&server_root, g_free); } diff -Naurp libsoup-2.74.3.orig/tests/test-utils.h libsoup-2.74.3/tests/test-utils.h --- libsoup-2.74.3.orig/tests/test-utils.h 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/test-utils.h 2025-05-19 15:41:07.621174231 -0500 @@ -29,11 +29,17 @@ void debug_printf (int level, const char } G_STMT_END #ifdef HAVE_APACHE -void apache_init (void); +gboolean apache_init (void); void apache_cleanup (void); -#define SOUP_TEST_SKIP_IF_NO_APACHE +gboolean check_apache (void); +#define SOUP_TEST_SKIP_IF_NO_APACHE \ + G_STMT_START { \ + if (!check_apache ()) { \ + return; \ + } \ + } G_STMT_END #else -#define apache_init() +#define apache_init() FALSE #define apache_cleanup() #define SOUP_TEST_SKIP_IF_NO_APACHE \ G_STMT_START { \ diff -Naurp libsoup-2.74.3.orig/tests/websocket-test.c libsoup-2.74.3/tests/websocket-test.c --- libsoup-2.74.3.orig/tests/websocket-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/websocket-test.c 2025-05-19 15:42:06.547737197 -0500 @@ -1300,8 +1300,9 @@ test_receive_invalid_encode_length_16 (T GError *error = NULL; InvalidEncodeLengthTest context = { test, NULL }; guint i; + guint error_id; - g_signal_connect (test->client, "error", G_CALLBACK (on_error_copy), &error); + error_id = g_signal_connect (test->client, "error", G_CALLBACK (on_error_copy), &error); g_signal_connect (test->client, "message", G_CALLBACK (on_binary_message), &received); /* We use 126(~) as payload length with 125 extended length */ @@ -1314,6 +1315,7 @@ test_receive_invalid_encode_length_16 (T WAIT_UNTIL (error != NULL || received != NULL); g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR); g_clear_error (&error); + g_signal_handler_disconnect (test->client, error_id); g_assert_null (received); g_thread_join (thread); @@ -1331,8 +1333,9 @@ test_receive_invalid_encode_length_64 (T GError *error = NULL; InvalidEncodeLengthTest context = { test, NULL }; guint i; + guint error_id; - g_signal_connect (test->client, "error", G_CALLBACK (on_error_copy), &error); + error_id = g_signal_connect (test->client, "error", G_CALLBACK (on_error_copy), &error); g_signal_connect (test->client, "message", G_CALLBACK (on_binary_message), &received); /* We use 127(\x7f) as payload length with 65535 extended length */ @@ -1345,6 +1348,7 @@ test_receive_invalid_encode_length_64 (T WAIT_UNTIL (error != NULL || received != NULL); g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR); g_clear_error (&error); + g_signal_handler_disconnect (test->client, error_id); g_assert_null (received); g_thread_join (thread); diff -Naurp libsoup-2.74.3.orig/tests/xmlrpc-old-test.c libsoup-2.74.3/tests/xmlrpc-old-test.c --- libsoup-2.74.3.orig/tests/xmlrpc-old-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/xmlrpc-old-test.c 2025-05-19 15:41:29.451012271 -0500 @@ -15,7 +15,12 @@ static const char *uri = NULL; static gboolean server_test = FALSE; #ifdef HAVE_PHP_XMLRPC -#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER +#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \ + G_STMT_START { \ + if (uri == default_uri) { \ + SOUP_TEST_SKIP_IF_NO_APACHE; \ + } \ + } G_STMT_END #else #define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \ G_STMT_START { \ @@ -23,6 +28,9 @@ static gboolean server_test = FALSE; g_test_skip ("php-xmlrpc is not available"); \ return; \ } \ + if (uri == default_uri) { \ + SOUP_TEST_SKIP_IF_NO_APACHE; \ + } \ } G_STMT_END #endif @@ -104,6 +112,11 @@ test_sum (void) GValue retval; gboolean ok; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "sum (array of double -> double): "); @@ -140,6 +153,11 @@ test_countBools (void) gboolean val, ok; GHashTable *result; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "countBools (array of boolean -> struct of ints): "); @@ -185,6 +203,11 @@ test_md5sum (void) GValue retval; gboolean ok; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "md5sum (base64 -> base64)\n"); @@ -221,6 +244,11 @@ test_dateChange (void) GValue retval; gboolean ok; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "dateChange (date, struct of ints -> time)\n"); @@ -323,6 +351,11 @@ test_echo (void) GValue retval; int i; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "echo (array of string -> array of string):\n"); @@ -370,6 +403,11 @@ test_ping (gconstpointer include_params) g_test_bug ("671661"); + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "ping (void (%s) -> string)\n", @@ -439,6 +477,11 @@ do_bad_xmlrpc (const char *body) static void test_fault_malformed (void) { + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; do_bad_xmlrpc (""); @@ -447,6 +490,11 @@ test_fault_malformed (void) static void test_fault_method (void) { + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; do_bad_xmlrpc ("no_such_method1"); @@ -455,6 +503,11 @@ test_fault_method (void) static void test_fault_args (void) { + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; do_bad_xmlrpc ("sum1"); diff -Naurp libsoup-2.74.3.orig/tests/xmlrpc-test.c libsoup-2.74.3/tests/xmlrpc-test.c --- libsoup-2.74.3.orig/tests/xmlrpc-test.c 2022-10-11 13:27:22.000000000 -0500 +++ libsoup-2.74.3/tests/xmlrpc-test.c 2025-05-19 15:41:29.451012271 -0500 @@ -12,7 +12,12 @@ static const char *uri = NULL; static gboolean server_test = FALSE; #ifdef HAVE_PHP_XMLRPC -#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER +#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \ + G_STMT_START { \ + if (uri == default_uri) { \ + SOUP_TEST_SKIP_IF_NO_APACHE; \ + } \ + } G_STMT_END #else #define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \ G_STMT_START { \ @@ -20,6 +25,9 @@ static gboolean server_test = FALSE; g_test_skip ("php-xmlrpc is not available"); \ return; \ } \ + if (uri == default_uri) { \ + SOUP_TEST_SKIP_IF_NO_APACHE; \ + } \ } G_STMT_END #endif @@ -79,6 +87,11 @@ test_sum (void) GVariant *retval; gboolean ok; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "sum (array of double -> double): "); @@ -115,6 +128,11 @@ test_countBools (void) int ret_trues, ret_falses; gboolean val, ok; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "countBools (array of boolean -> struct of ints): "); @@ -158,6 +176,11 @@ test_md5sum (void) GVariant *retval; gboolean ok; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "md5sum (base64 -> base64)\n"); @@ -197,6 +220,11 @@ test_dateChange (void) gboolean ok; GError *error = NULL; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "dateChange (date, struct of ints -> time)\n"); @@ -304,6 +332,11 @@ test_echo (void) GVariant *retval; char *str; + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "echo (array of string -> array of string):\n"); @@ -341,6 +374,11 @@ test_ping (gconstpointer include_params) g_test_bug ("671661"); + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "ping (void (%s) -> string)\n", @@ -406,6 +444,11 @@ do_bad_xmlrpc (const char *body) static void test_fault_malformed (void) { + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; do_bad_xmlrpc (""); @@ -414,6 +457,11 @@ test_fault_malformed (void) static void test_fault_method (void) { + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; do_bad_xmlrpc ("no_such_method1"); @@ -422,6 +470,11 @@ test_fault_method (void) static void test_fault_args (void) { + if (g_getenv ("DEB_ALLOW_FLAKY_TESTS") == NULL) { + g_test_skip ("Not reliable?"); + return; + } + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; do_bad_xmlrpc ("sum1");