Repository: aio-libs/aiohttp

Issue:
HTTP method and version REs are prefix matched
### Describe the bug

The HTTP parser only validates that methods and versions have a valid prefix, instead of validating the entire method and version. For example, the following is incorrectly accepted by the parser:
```
GET\xff / HTTP/1.1\xff\r\n
\r\n
```

### To Reproduce

1. Start an AIOHTTP server.
2. Send it the request above.
3. Observe that it responds normally.

### Expected behavior

The request should be rejected.

### Logs/tracebacks

```python-traceback
N/A
```


### Python Version

```console
$ python --version
Python 3.11.6
```


### aiohttp Version

```console
$ python -m pip show aiohttp
Name: aiohttp
Version: 4.0.0a2.dev0
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author:
Author-email:
License: Apache 2
Location: /app/aiohttp/env/lib/python3.11/site-packages
Requires: aiosignal, frozenlist, multidict, yarl
Required-by:
```


### multidict Version

```console
$ python -m pip show multidict
Name: multidict
Version: 6.0.4
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /app/aiohttp/env/lib/python3.11/site-packages
Requires:
Required-by: aiohttp, yarl
```


### yarl Version

```console
$ python -m pip show yarl
Name: yarl
Version: 1.9.2
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl/
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache-2.0
Location: /app/aiohttp/env/lib/python3.11/site-packages
Requires: idna, multidict
Required-by: aiohttp
```


### OS

Alpine Linux 3.18.0

### Related component

Client

### Additional context

This bug is caused by (what I assume to be) mistaken use of `re.Pattern.match` instead of `re.Pattern.fullmatch` in `aiohttp/parse_http.py`.

### Code of Conduct

- [X] I agree to follow the aio-libs Code of Conduct


Discussion:

Resolving patch:
diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py
--- a/aiohttp/http_parser.py
+++ b/aiohttp/http_parser.py
@@ -549,11 +549,11 @@ def parse_message(self, lines: List[bytes]) -> RawRequestMessage:
             )
 
         # method
-        if not METHRE.match(method):
+        if not METHRE.fullmatch(method):
             raise BadStatusLine(method)
 
         # version
-        match = VERSRE.match(version)
+        match = VERSRE.fullmatch(version)
         if match is None:
             raise BadStatusLine(line)
         version_o = HttpVersion(int(match.group(1)), int(match.group(2)))
@@ -652,7 +652,7 @@ def parse_message(self, lines: List[bytes]) -> RawResponseMessage:
             )
 
         # version
-        match = VERSRE.match(version)
+        match = VERSRE.fullmatch(version)
         if match is None:
             raise BadStatusLine(line)
         version_o = HttpVersion(int(match.group(1)), int(match.group(2)))


Test patch:
diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py
--- a/tests/test_http_parser.py
+++ b/tests/test_http_parser.py
@@ -727,7 +727,7 @@ def test_http_request_parser_two_slashes(parser: Any) -> None:
 
 def test_http_request_parser_bad_method(parser: Any) -> None:
     with pytest.raises(http_exceptions.BadStatusLine):
-        parser.feed_data(b'=":<G>(e),[T];?" /get HTTP/1.1\r\n\r\n')
+        parser.feed_data(b'G=":<>(e),[T];?" /get HTTP/1.1\r\n\r\n')
 
 
 def test_http_request_parser_bad_version(parser: Any) -> None:
@@ -737,7 +737,7 @@ def test_http_request_parser_bad_version(parser: Any) -> None:
 
 def test_http_request_parser_bad_version_number(parser: Any) -> None:
     with pytest.raises(http_exceptions.BadHttpMessage):
-        parser.feed_data(b"GET /test HTTP/12.3\r\n\r\n")
+        parser.feed_data(b"GET /test HTTP/1.32\r\n\r\n")
 
 
 @pytest.mark.parametrize("size", [40965, 8191])