Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions tests/test_benchmarks_cookie_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""codspeed benchmarks for cookie helpers."""

from typing import TYPE_CHECKING

import pytest

from aiohttp._cookie_helpers import _COOKIE_PATTERN

if TYPE_CHECKING:
from pytest_codspeed import BenchmarkFixture
else:
pytest_codspeed = pytest.importorskip("pytest_codspeed")
BenchmarkFixture = pytest_codspeed.BenchmarkFixture


def test_cookie_pattern_redos_payload(benchmark: BenchmarkFixture) -> None:
"""Benchmark ``_COOKIE_PATTERN`` against a ReDoS payload.

A regression that reintroduces catastrophic backtracking shows up here as
a large, deterministic slowdown instead of a flaky wall-clock assertion.
"""
value = "a" + "=" * 21651 + "\x00"
# This payload must not match.
assert _COOKIE_PATTERN.match(value) is None

@benchmark
def _run() -> None:
_COOKIE_PATTERN.match(value)
18 changes: 0 additions & 18 deletions tests/test_cookie_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import logging
import sys
import time
from http.cookies import (
CookieError,
Morsel,
Expand Down Expand Up @@ -637,23 +636,6 @@ def test_cookie_pattern_matches_partitioned_attribute(test_string: str) -> None:
assert match.group("key").lower() == "partitioned"


def test_cookie_pattern_performance() -> None:
"""Test that the cookie pattern doesn't suffer from ReDoS issues."""
COOKIE_PATTERN_TIME_THRESHOLD_SECONDS = 0.08
value = "a" + "=" * 21651 + "\x00"
start = time.perf_counter()
match = helpers._COOKIE_PATTERN.match(value)
elapsed = time.perf_counter() - start

# If this is taking more time, there's probably a performance/ReDoS issue.
assert elapsed < COOKIE_PATTERN_TIME_THRESHOLD_SECONDS, (
f"Pattern took {elapsed * 1000:.1f}ms, "
f"expected <{COOKIE_PATTERN_TIME_THRESHOLD_SECONDS * 1000:.0f}ms - potential ReDoS issue"
)
# This example shouldn't produce a match either.
assert match is None


def test_parse_set_cookie_headers_issue_7993_double_quotes() -> None:
"""
Test that cookies with unmatched opening quotes don't break parsing of subsequent cookies.
Expand Down
Loading