curl-0001 (UNDF-2026-000000040): lib/http_aws_sigv4.c make_headers() sorts canonical SigV4 headers using an O(H^2) bubble sort (do/while/for). Every SigV4 HTTP request pays H^2 comparisons. At H=200: 35,024 vs 794 (44x). Fix: qsort on a temporary pointer array, O(H log H). ffmpeg-0001 (UNDF-2026-000000070): libavfilter/formats.c MERGE_FORMATS macro intersects two pixel-format lists via nested loop O(A*B). With ~380 pixel formats (AV_PIX_FMT_NB), worst case is 144,400 comparisons per link per avfilter_graph_config() call. At A=B=380: 72,390 vs 3,420 (21x). Fix: sort b, bsearch for membership, O((A+B) log B). Unit tests: CurlTest.java, FFmpegTest.java — both PASS.
73 lines
2.3 KiB
Diff
73 lines
2.3 KiB
Diff
# UNDF: UNDF-2026-000000040
|
|
--- a/lib/http_aws_sigv4.c
|
|
+++ b/lib/http_aws_sigv4.c
|
|
@@ -288,6 +288,16 @@ static int compare_header_names(const char *a, const char *b)
|
|
return cmp;
|
|
}
|
|
|
|
+/* qsort-compatible wrapper for compare_header_names */
|
|
+static int compare_header_names_qsort(const void *pa, const void *pb)
|
|
+{
|
|
+ return compare_header_names(*(const char *const *)pa,
|
|
+ *(const char *const *)pb);
|
|
+}
|
|
+
|
|
/* Merge duplicate header definitions by comma delimiting their values
|
|
in the order defined the headers are defined, expecting headers to
|
|
be alpha-sorted and use ':' at this point */
|
|
@@ -383,7 +393,6 @@ static CURLcode make_headers(struct Curl_easy *data,
|
|
struct curl_slist *head = NULL;
|
|
struct curl_slist *tmp_head = NULL;
|
|
CURLcode ret = CURLE_OUT_OF_MEMORY;
|
|
struct curl_slist *l;
|
|
- bool again = TRUE;
|
|
|
|
curl_msnprintf(date_hdr_key, DATE_HDR_KEY_LEN, "X-%.*s-Date",
|
|
(int)plen, provider1);
|
|
@@ -503,18 +513,31 @@ static CURLcode make_headers(struct Curl_easy *data,
|
|
*date_header = NULL;
|
|
}
|
|
|
|
- /* alpha-sort by header name in a case sensitive manner */
|
|
- do {
|
|
- again = FALSE;
|
|
- for(l = head; l; l = l->next) {
|
|
- struct curl_slist *next = l->next;
|
|
-
|
|
- if(next && compare_header_names(l->data, next->data) > 0) {
|
|
- char *tmp = l->data;
|
|
-
|
|
- l->data = next->data;
|
|
- next->data = tmp;
|
|
- again = TRUE;
|
|
- }
|
|
- }
|
|
- } while(again);
|
|
+ /* alpha-sort headers by name in a case sensitive manner.
|
|
+ *
|
|
+ * The original implementation used an O(H^2) bubble sort over the slist.
|
|
+ * With H custom headers (CWE-407), every SigV4 request paid H^2 string
|
|
+ * comparisons. At H=50 that is 2,500 comparisons vs ~280 for qsort.
|
|
+ * Replace with an O(H log H) qsort on a temporary pointer array.
|
|
+ */
|
|
+ {
|
|
+ size_t count = 0;
|
|
+ char **arr;
|
|
+ for(l = head; l; l = l->next)
|
|
+ count++;
|
|
+ if(count > 1) {
|
|
+ arr = malloc(count * sizeof(*arr));
|
|
+ if(!arr)
|
|
+ goto fail;
|
|
+ count = 0;
|
|
+ for(l = head; l; l = l->next)
|
|
+ arr[count++] = l->data;
|
|
+ qsort(arr, count, sizeof(*arr), compare_header_names_qsort);
|
|
+ count = 0;
|
|
+ for(l = head; l; l = l->next)
|
|
+ l->data = arr[count++];
|
|
+ free(arr);
|
|
+ }
|
|
+ }
|
|
|
|
ret = merge_duplicate_headers(head);
|