|
3 | 3 | import logging |
4 | 4 | import sys |
5 | 5 | import time |
6 | | -import typing |
7 | 6 | from http.cookies import ( |
8 | 7 | CookieError, |
9 | 8 | Morsel, |
10 | 9 | SimpleCookie, |
11 | 10 | _unquote as simplecookie_unquote, |
12 | 11 | ) |
13 | | -from unittest.mock import patch |
14 | 12 |
|
15 | 13 | import pytest |
16 | 14 |
|
@@ -1139,8 +1137,18 @@ def test_parse_set_cookie_headers_uses_unquote_with_octal( |
1139 | 1137 | @pytest.mark.parametrize( |
1140 | 1138 | ("header", "expected_name", "expected_coded"), |
1141 | 1139 | [ |
1142 | | - (r'name="\012newline\012"', "name", r'"\012newline\012"'), |
1143 | | - (r'tab="\011separated\011values"', "tab", r'"\011separated\011values"'), |
| 1140 | + pytest.param( |
| 1141 | + r'name="\012newline\012"', |
| 1142 | + "name", |
| 1143 | + r'"\012newline\012"', |
| 1144 | + id="newline-octal-012", |
| 1145 | + ), |
| 1146 | + pytest.param( |
| 1147 | + r'tab="\011separated\011values"', |
| 1148 | + "tab", |
| 1149 | + r'"\011separated\011values"', |
| 1150 | + id="tab-octal-011", |
| 1151 | + ), |
1144 | 1152 | ], |
1145 | 1153 | ) |
1146 | 1154 | def test_parse_set_cookie_headers_ctl_chars_from_octal( |
@@ -1183,8 +1191,7 @@ def test_parse_set_cookie_headers_literal_ctl_chars_preserves_others() -> None: |
1183 | 1191 | result = parse_set_cookie_headers(['bad="a\x07b"; good=value', "another=cookie"]) |
1184 | 1192 | # "good" is an attribute of "bad" (same header), so it's not a separate cookie. |
1185 | 1193 | # "another" is in a separate header and must always be preserved. |
1186 | | - names = [name for name, _ in result] |
1187 | | - assert "another" in names |
| 1194 | + assert any(name == "another" for name, _ in result) |
1188 | 1195 |
|
1189 | 1196 |
|
1190 | 1197 | # Tests for parse_cookie_header (RFC 6265 compliant Cookie header parser) |
@@ -1660,8 +1667,7 @@ def test_parse_cookie_header_literal_ctl_chars() -> None: |
1660 | 1667 | result = parse_cookie_header('name="a\x07b"; good=cookie') |
1661 | 1668 | # On CPython with CVE-2026-3644 patch the bad cookie is skipped; |
1662 | 1669 | # on older builds it may be accepted. Either way, no crash. |
1663 | | - names = [name for name, _ in result] |
1664 | | - assert "good" in names |
| 1670 | + assert any(name == "good" for name, _ in result) |
1665 | 1671 |
|
1666 | 1672 |
|
1667 | 1673 | @pytest.mark.parametrize( |
@@ -1855,23 +1861,24 @@ def test_unquote_compatibility_with_simplecookie(test_value: str) -> None: |
1855 | 1861 |
|
1856 | 1862 |
|
1857 | 1863 | @pytest.fixture |
1858 | | -def mock_strict_morsel() -> typing.Iterator[None]: |
| 1864 | +def mock_strict_morsel( |
| 1865 | + monkeypatch: pytest.MonkeyPatch, |
| 1866 | +) -> None: |
1859 | 1867 | original_setstate = Morsel.__setstate__ # type: ignore[attr-defined] |
1860 | 1868 |
|
1861 | 1869 | def _mock_setstate(self: Morsel[str], state: dict[str, str]) -> None: |
1862 | 1870 | if any(ord(c) < 32 for c in state.get("value", "")): |
1863 | 1871 | raise CookieError() |
1864 | 1872 | original_setstate(self, state) |
1865 | 1873 |
|
1866 | | - with patch( |
| 1874 | + monkeypatch.setattr( |
1867 | 1875 | "aiohttp._cookie_helpers.Morsel.__setstate__", |
1868 | | - autospec=True, |
1869 | | - side_effect=_mock_setstate, |
1870 | | - ): |
1871 | | - yield |
| 1876 | + _mock_setstate, |
| 1877 | + ) |
1872 | 1878 |
|
1873 | 1879 |
|
1874 | | -def test_cookie_helpers_cve_fallback(mock_strict_morsel: None) -> None: |
| 1880 | +@pytest.mark.usefixtures("mock_strict_morsel") |
| 1881 | +def test_cookie_helpers_cve_fallback() -> None: |
1875 | 1882 | m: Morsel[str] = Morsel() |
1876 | 1883 | assert helpers._safe_set_morsel_state(m, "k", "v\n", "v\\012") is True |
1877 | 1884 | assert m.value == "v\\012" |
|
0 commit comments