Skip to content

Commit db83482

Browse files
committed
Fix unquote IndexError on empty string input
unquote() in _utils.py accesses value[0] and value[-1] without checking string length first. This raises IndexError when called with an empty string, which can occur when parsing Digest auth WWW-Authenticate headers containing parameters with empty unquoted values (e.g. realm= instead of realm=""). Added a len(value) >= 2 guard and comprehensive test coverage for empty strings, single characters, quoted values, and unquoted values. Note: encode#3771 addresses the same issue. This PR adds the regression tests that are missing there. Happy to close in favor of that PR if tests are added. Powered by codepo8 — tribal knowledge extraction identified this as a guard-level issue: "Check string length before accessing index 0 in unquote() utilities because empty string inputs cause an IndexError."
1 parent b5addb6 commit db83482

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

httpx/_utils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ def to_bytes_or_str(value: str, match_type_of: typing.AnyStr) -> typing.AnyStr:
8989

9090

9191
def unquote(value: str) -> str:
92-
return value[1:-1] if value[0] == value[-1] == '"' else value
92+
if len(value) >= 2 and value[0] == value[-1] == '"':
93+
return value[1:-1]
94+
return value
9395

9496

9597
def peek_filelike_length(stream: typing.Any) -> int | None:

tests/test_utils.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pytest
77

88
import httpx
9-
from httpx._utils import URLPattern, get_environment_proxies
9+
from httpx._utils import URLPattern, get_environment_proxies, unquote
1010

1111

1212
@pytest.mark.parametrize(
@@ -148,3 +148,19 @@ def test_pattern_priority():
148148
URLPattern("http://"),
149149
URLPattern("all://"),
150150
]
151+
152+
153+
@pytest.mark.parametrize(
154+
["value", "expected"],
155+
[
156+
('""', ""),
157+
('"hello"', "hello"),
158+
('"hello world"', "hello world"),
159+
("hello", "hello"),
160+
("", ""),
161+
('"', '"'),
162+
("noquotes", "noquotes"),
163+
],
164+
)
165+
def test_unquote(value, expected):
166+
assert unquote(value) == expected

0 commit comments

Comments
 (0)