File libsoup2-CVE-2026-2443.patch of Package libsoup2

diff -urp libsoup-3.6.5.orig/libsoup/soup-message-headers.c libsoup-3.6.5/libsoup/soup-message-headers.c
--- libsoup-3.6.5.orig/libsoup/soup-message-headers.c	2026-02-14 04:14:09.575357979 -0600
+++ libsoup-3.6.5/libsoup/soup-message-headers.c	2026-02-14 04:17:20.278921604 -0600
@@ -1176,10 +1176,16 @@ sort_ranges (gconstpointer a, gconstpoin
 }
 
 /* like soup_message_headers_get_ranges(), except it returns:
- *   SOUP_STATUS_OK if there is no Range or it should be ignored.
- *   SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range.
- *   SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable
- *     is %TRUE and the request is not satisfiable given @total_length.
+ *  - SOUP_STATUS_OK if there is no Range or it should be ignored due to being
+ *    entirely invalid.
+ *  - SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range.
+ *  - SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable
+ *     is %TRUE, the Range is valid, but no part of the request is satisfiable
+ *     given @total_length.
+ *
+ * @ranges and @length are only set if SOUP_STATUS_PARTIAL_CONTENT is returned.
+ *
+ * See https://httpwg.org/specs/rfc9110.html#field.range
  */
 guint
 soup_message_headers_get_ranges_internal (SoupMessageHeaders  *hdrs,
@@ -1193,22 +1199,28 @@ soup_message_headers_get_ranges_internal
 	GArray *array;
 	char *spec, *end;
 	guint status = SOUP_STATUS_OK;
+	gboolean is_all_valid = TRUE;
 
 	if (!range || strncmp (range, "bytes", 5) != 0)
-		return status;
+		return SOUP_STATUS_OK;  /* invalid header or unknown range unit */
 
 	range += 5;
 	while (g_ascii_isspace (*range))
 		range++;
 	if (*range++ != '=')
-		return status;
+		return SOUP_STATUS_OK;  /* invalid header */
 	while (g_ascii_isspace (*range))
 		range++;
 
 	range_list = soup_header_parse_list (range);
 	if (!range_list)
-		return status;
+		return SOUP_STATUS_OK;  /* invalid list */
 
+	/* Loop through the ranges and modify the status accordingly. Default to
+	 * status 200 (OK, ignoring the ranges). Switch to status 206 (Partial
+	 * Content) if there is at least one partially valid range. Switch to
+	 * status 416 (Range Not Satisfiable) if there are no partially valid
+	 * ranges at all. */
 	array = g_array_new (FALSE, FALSE, sizeof (SoupRange));
 	for (r = range_list; r; r = r->next) {
 		SoupRange cur;
@@ -1221,30 +1233,44 @@ soup_message_headers_get_ranges_internal
 			cur.start = g_ascii_strtoull (spec, &end, 10);
 			if (*end == '-')
 				end++;
-			if (*end) {
+			if (*end)
 				cur.end = g_ascii_strtoull (end, &end, 10);
-				if (cur.end < cur.start) {
-					status = SOUP_STATUS_OK;
-					break;
-				}
-			} else
+			else
 				cur.end = total_length - 1;
 		}
+
 		if (*end) {
-			status = SOUP_STATUS_OK;
-			break;
-		} else if (check_satisfiable && cur.start >= total_length) {
-			if (status == SOUP_STATUS_OK)
-				status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE;
+			/* Junk after the range */
+			is_all_valid = FALSE;
+			continue;
+		}
+
+		if (cur.end < cur.start) {
+			is_all_valid = FALSE;
 			continue;
 		}
 
+		g_assert (cur.start >= 0);
+		if (cur.end >= total_length)
+			cur.end = total_length - 1;
+
+		if (cur.start >= total_length) {
+			/* Range is valid, but unsatisfiable */
+			continue;
+		}
+
+		/* We have at least one (at least partially) satisfiable range */
 		g_array_append_val (array, cur);
 		status = SOUP_STATUS_PARTIAL_CONTENT;
 	}
 	soup_header_free_list (range_list);
 
 	if (status != SOUP_STATUS_PARTIAL_CONTENT) {
+		g_assert (status == SOUP_STATUS_OK);
+
+		if (is_all_valid && check_satisfiable)
+			status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE;
+
 		g_array_free (array, TRUE);
 		return status;
 	}
openSUSE Build Service is sponsored by