java-topology/defects/nginx/patch/nginx-0001-link-multi-headers-hash.patch

109 lines
3.4 KiB
Diff

# UNDF: UNDF-2026-000000185
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2871,38 +2871,50 @@ ngx_http_link_multi_headers(ngx_http_request_t *r)
{
- ngx_uint_t i, j;
- ngx_list_part_t *part, *ppart;
- ngx_table_elt_t *header, *pheader, **ph;
+ ngx_uint_t i;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *header, **ph;
+ ngx_hash_t name_map;
+ ngx_hash_init_t hash;
+ ngx_hash_key_t *keys;
+ ngx_uint_t nkeys;
if (r->headers_in.multi_linked) {
return NGX_OK;
}
r->headers_in.multi_linked = 1;
part = &r->headers_in.headers.part;
header = part->elts;
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- header[i].next = NULL;
-
- ppart = &r->headers_in.headers.part;
- pheader = ppart->elts;
-
- for (j = 0; /* void */; j++) {
-
- if (j >= ppart->nelts) {
- if (ppart->next == NULL) {
- break;
- }
-
- ppart = ppart->next;
- pheader = ppart->elts;
- j = 0;
- }
-
- if (part == ppart && i == j) {
- break;
- }
-
- if (header[i].key.len == pheader[j].key.len
- && ngx_strncasecmp(header[i].key.data, pheader[j].key.data,
- header[i].key.len)
- == 0)
- {
- ph = &pheader[j].next;
- while (*ph) { ph = &(*ph)->next; }
- *ph = &header[i];
-
- r->headers_in.multi = 1;
-
- break;
- }
- }
- }
+ /*
+ * Build a hash table mapping lowercased header name → first ngx_table_elt_t *.
+ * Single O(H) forward pass: for each header, if the name is already in the
+ * hash, append to that entry's ->next chain. No backward re-scan needed.
+ * Replaces the O(H²) double-traversal that compared every (i,j) pair.
+ */
+ ngx_hash_keys_array_t ha;
+ if (ngx_hash_keys_array_init(&ha, NGX_HASH_SMALL, r->pool) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ for (i = 0; /* void */; i++) {
+ if (i >= part->nelts) {
+ if (part->next == NULL) break;
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ header[i].next = NULL;
+
+ ngx_table_elt_t **existing = ngx_hash_find(&name_map,
+ header[i].lowcase_key ?
+ ngx_hash_key(header[i].lowcase_key, header[i].key.len) :
+ ngx_hash_key_lc(header[i].key.data, header[i].key.len),
+ header[i].key.data,
+ header[i].key.len);
+ if (existing) {
+ ph = &(*existing)->next;
+ while (*ph) { ph = &(*ph)->next; }
+ *ph = &header[i];
+ r->headers_in.multi = 1;
+ } else {
+ ngx_hash_add_key(&ha, &header[i].key, &header[i], NGX_HASH_READONLY_KEY);
+ }
+ }