| 1693 | } |
| 1694 | |
| 1695 | static apr_status_t req_add_header(apr_table_t *headers, apr_pool_t *pool, |
| 1696 | nghttp2_nv *nv, h2_hd_scratch *scratch, |
| 1697 | int *pwas_added) |
| 1698 | { |
| 1699 | const char *existing; |
| 1700 | |
| 1701 | *pwas_added = 0; |
| 1702 | strip_field_value_ws(nv); |
| 1703 | |
| 1704 | if (h2_req_ignore_header(nv)) { |
| 1705 | return APR_SUCCESS; |
| 1706 | } |
| 1707 | else if (nv->namelen == sizeof("cookie")-1 |
| 1708 | && !ap_cstr_casecmpn("cookie", (const char *)nv->name, nv->namelen)) { |
| 1709 | existing = apr_table_get(headers, "cookie"); |
| 1710 | if (existing) { |
| 1711 | if (!nv->valuelen) |
| 1712 | return APR_SUCCESS; |
| 1713 | /* Cookie header come separately in HTTP/2, but need |
| 1714 | * to be merged by "; " (instead of default ", ") |
| 1715 | */ |
| 1716 | if ((strlen(existing) + nv->valuelen + nv->namelen + 4) |
| 1717 | > scratch->max_len) { |
| 1718 | /* "key: oldval, nval" is too long */ |
| 1719 | return APR_EINVAL; |
| 1720 | } |
| 1721 | apr_table_setn(headers, "Cookie", |
| 1722 | apr_psprintf(pool, "%s; %.*s", existing, |
| 1723 | (int)nv->valuelen, nv->value)); |
| 1724 | /* Treat the merge as an "add" to not escape LimitRequestFields */ |
| 1725 | *pwas_added = 1; |
| 1726 | return APR_SUCCESS; |
| 1727 | } |
| 1728 | } |
| 1729 | else if (nv->namelen == sizeof("host")-1 |
| 1730 | && !ap_cstr_casecmpn("host", (const char *)nv->name, nv->namelen)) { |
| 1731 | if (apr_table_get(headers, "Host")) { |
| 1732 | return APR_SUCCESS; /* ignore duplicate */ |
| 1733 | } |
| 1734 | } |
| 1735 | |
| 1736 | if (((nv->namelen + nv->valuelen + 2) > scratch->max_len)) |
| 1737 | return APR_EINVAL; |
| 1738 | |
| 1739 | /* We need 0-terminated strings to operate on apr_table */ |
| 1740 | AP_DEBUG_ASSERT(nv->namelen < scratch->max_len); |
| 1741 | memcpy(scratch->name, nv->name, nv->namelen); |
| 1742 | scratch->name[nv->namelen] = 0; |
| 1743 | AP_DEBUG_ASSERT(nv->valuelen < scratch->max_len); |
| 1744 | memcpy(scratch->value, nv->value, nv->valuelen); |
| 1745 | scratch->value[nv->valuelen] = 0; |
| 1746 | |
| 1747 | *pwas_added = 1; |
| 1748 | existing = apr_table_get(headers, scratch->name); |
| 1749 | if (existing) { |
| 1750 | if (!nv->valuelen) /* not adding a 0-length value to existing */ |
| 1751 | return APR_SUCCESS; |
| 1752 | if ((strlen(existing) + 2 + nv->valuelen + nv->namelen + 2) |
no test coverage detected