We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Dangerous example regex for CORS Middleware?
Looking at the docs for CORS Middlware here: https://www.starlette.io/middleware/#corsmiddleware , under the `allow_origin_regex` attribute, the example value is `https://.*\.example\.org`.

However, based on the handler code for this at https://github.com/encode/starlette/blob/ab86530eddfcf56e0f7e5ca56f6ab69c15594a7d/starlette/middleware/cors.py#L90 , it appears `https://www.example.org.hacker.com` would pass as a valid origin, right?

It seems like the example should be `https://.*\.example\.org$`, yes?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `starlette/middleware/cors.py`
Content:
```
1 import functools
2 import re
3 import typing
4 
5 from starlette.datastructures import Headers, MutableHeaders
6 from starlette.responses import PlainTextResponse, Response
7 from starlette.types import ASGIApp, Message, Receive, Scope, Send
8 
9 ALL_METHODS = ("DELETE", "GET", "OPTIONS", "PATCH", "POST", "PUT")
10 
11 
12 class CORSMiddleware:
13     def __init__(
14         self,
15         app: ASGIApp,
16         allow_origins: typing.Sequence[str] = (),
17         allow_methods: typing.Sequence[str] = ("GET",),
18         allow_headers: typing.Sequence[str] = (),
19         allow_credentials: bool = False,
20         allow_origin_regex: str = None,
21         expose_headers: typing.Sequence[str] = (),
22         max_age: int = 600,
23     ) -> None:
24 
25         if "*" in allow_methods:
26             allow_methods = ALL_METHODS
27 
28         compiled_allow_origin_regex = None
29         if allow_origin_regex is not None:
30             compiled_allow_origin_regex = re.compile(allow_origin_regex)
31 
32         simple_headers = {}
33         if "*" in allow_origins:
34             simple_headers["Access-Control-Allow-Origin"] = "*"
35         if allow_credentials:
36             simple_headers["Access-Control-Allow-Credentials"] = "true"
37         if expose_headers:
38             simple_headers["Access-Control-Expose-Headers"] = ", ".join(expose_headers)
39 
40         preflight_headers = {}
41         if "*" in allow_origins:
42             preflight_headers["Access-Control-Allow-Origin"] = "*"
43         else:
44             preflight_headers["Vary"] = "Origin"
45         preflight_headers.update(
46             {
47                 "Access-Control-Allow-Methods": ", ".join(allow_methods),
48                 "Access-Control-Max-Age": str(max_age),
49             }
50         )
51         if allow_headers and "*" not in allow_headers:
52             preflight_headers["Access-Control-Allow-Headers"] = ", ".join(allow_headers)
53         if allow_credentials:
54             preflight_headers["Access-Control-Allow-Credentials"] = "true"
55 
56         self.app = app
57         self.allow_origins = allow_origins
58         self.allow_methods = allow_methods
59         self.allow_headers = [h.lower() for h in allow_headers]
60         self.allow_all_origins = "*" in allow_origins
61         self.allow_all_headers = "*" in allow_headers
62         self.allow_origin_regex = compiled_allow_origin_regex
63         self.simple_headers = simple_headers
64         self.preflight_headers = preflight_headers
65 
66     async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
67         if scope["type"] != "http":  # pragma: no cover
68             await self.app(scope, receive, send)
69             return
70 
71         method = scope["method"]
72         headers = Headers(scope=scope)
73         origin = headers.get("origin")
74 
75         if origin is None:
76             await self.app(scope, receive, send)
77             return
78 
79         if method == "OPTIONS" and "access-control-request-method" in headers:
80             response = self.preflight_response(request_headers=headers)
81             await response(scope, receive, send)
82             return
83 
84         await self.simple_response(scope, receive, send, request_headers=headers)
85 
86     def is_allowed_origin(self, origin: str) -> bool:
87         if self.allow_all_origins:
88             return True
89 
90         if self.allow_origin_regex is not None and self.allow_origin_regex.match(
91             origin
92         ):
93             return True
94 
95         return origin in self.allow_origins
96 
97     def preflight_response(self, request_headers: Headers) -> Response:
98         requested_origin = request_headers["origin"]
99         requested_method = request_headers["access-control-request-method"]
100         requested_headers = request_headers.get("access-control-request-headers")
101 
102         headers = dict(self.preflight_headers)
103         failures = []
104 
105         if self.is_allowed_origin(origin=requested_origin):
106             if not self.allow_all_origins:
107                 # If self.allow_all_origins is True, then the "Access-Control-Allow-Origin"
108                 # header is already set to "*".
109                 # If we only allow specific origins, then we have to mirror back
110                 # the Origin header in the response.
111                 headers["Access-Control-Allow-Origin"] = requested_origin
112         else:
113             failures.append("origin")
114 
115         if requested_method not in self.allow_methods:
116             failures.append("method")
117 
118         # If we allow all headers, then we have to mirror back any requested
119         # headers in the response.
120         if self.allow_all_headers and requested_headers is not None:
121             headers["Access-Control-Allow-Headers"] = requested_headers
122         elif requested_headers is not None:
123             for header in [h.lower() for h in requested_headers.split(",")]:
124                 if header.strip() not in self.allow_headers:
125                     failures.append("headers")
126 
127         # We don't strictly need to use 400 responses here, since its up to
128         # the browser to enforce the CORS policy, but its more informative
129         # if we do.
130         if failures:
131             failure_text = "Disallowed CORS " + ", ".join(failures)
132             return PlainTextResponse(failure_text, status_code=400, headers=headers)
133 
134         return PlainTextResponse("OK", status_code=200, headers=headers)
135 
136     async def simple_response(
137         self, scope: Scope, receive: Receive, send: Send, request_headers: Headers
138     ) -> None:
139         send = functools.partial(self.send, send=send, request_headers=request_headers)
140         await self.app(scope, receive, send)
141 
142     async def send(
143         self, message: Message, send: Send, request_headers: Headers
144     ) -> None:
145         if message["type"] != "http.response.start":
146             await send(message)
147             return
148 
149         message.setdefault("headers", [])
150         headers = MutableHeaders(scope=message)
151         headers.update(self.simple_headers)
152         origin = request_headers["Origin"]
153         has_cookie = "cookie" in request_headers
154 
155         # If request includes any cookie headers, then we must respond
156         # with the specific origin instead of '*'.
157         if self.allow_all_origins and has_cookie:
158             headers["Access-Control-Allow-Origin"] = origin
159 
160         # If we only allow specific origins, then we have to mirror back
161         # the Origin header in the response.
162         elif not self.allow_all_origins and self.is_allowed_origin(origin=origin):
163             headers["Access-Control-Allow-Origin"] = origin
164             headers.add_vary_header("Origin")
165         await send(message)
166
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/starlette/middleware/cors.py b/starlette/middleware/cors.py
--- a/starlette/middleware/cors.py
+++ b/starlette/middleware/cors.py
@@ -87,7 +87,7 @@
         if self.allow_all_origins:
             return True
 
-        if self.allow_origin_regex is not None and self.allow_origin_regex.match(
+        if self.allow_origin_regex is not None and self.allow_origin_regex.fullmatch(
             origin
         ):
             return True

{"golden_diff": "diff --git a/starlette/middleware/cors.py b/starlette/middleware/cors.py\n--- a/starlette/middleware/cors.py\n+++ b/starlette/middleware/cors.py\n@@ -87,7 +87,7 @@\n         if self.allow_all_origins:\n             return True\n \n-        if self.allow_origin_regex is not None and self.allow_origin_regex.match(\n+        if self.allow_origin_regex is not None and self.allow_origin_regex.fullmatch(\n             origin\n         ):\n             return True\n", "issue": "Dangerous example regex for CORS Middleware?\nLooking at the docs for CORS Middlware here: https://www.starlette.io/middleware/#corsmiddleware , under the `allow_origin_regex` attribute, the example value is `https://.*\\.example\\.org`.\r\n\r\nHowever, based on the handler code for this at https://github.com/encode/starlette/blob/ab86530eddfcf56e0f7e5ca56f6ab69c15594a7d/starlette/middleware/cors.py#L90 , it appears `https://www.example.org.hacker.com` would pass as a valid origin, right?\r\n\r\nIt seems like the example should be `https://.*\\.example\\.org$`, yes?\n", "before_files": [{"content": "import functools\nimport re\nimport typing\n\nfrom starlette.datastructures import Headers, MutableHeaders\nfrom starlette.responses import PlainTextResponse, Response\nfrom starlette.types import ASGIApp, Message, Receive, Scope, Send\n\nALL_METHODS = (\"DELETE\", \"GET\", \"OPTIONS\", \"PATCH\", \"POST\", \"PUT\")\n\n\nclass CORSMiddleware:\n    def __init__(\n        self,\n        app: ASGIApp,\n        allow_origins: typing.Sequence[str] = (),\n        allow_methods: typing.Sequence[str] = (\"GET\",),\n        allow_headers: typing.Sequence[str] = (),\n        allow_credentials: bool = False,\n        allow_origin_regex: str = None,\n        expose_headers: typing.Sequence[str] = (),\n        max_age: int = 600,\n    ) -> None:\n\n        if \"*\" in allow_methods:\n            allow_methods = ALL_METHODS\n\n        compiled_allow_origin_regex = None\n        if allow_origin_regex is not None:\n            compiled_allow_origin_regex = re.compile(allow_origin_regex)\n\n        simple_headers = {}\n        if \"*\" in allow_origins:\n            simple_headers[\"Access-Control-Allow-Origin\"] = \"*\"\n        if allow_credentials:\n            simple_headers[\"Access-Control-Allow-Credentials\"] = \"true\"\n        if expose_headers:\n            simple_headers[\"Access-Control-Expose-Headers\"] = \", \".join(expose_headers)\n\n        preflight_headers = {}\n        if \"*\" in allow_origins:\n            preflight_headers[\"Access-Control-Allow-Origin\"] = \"*\"\n        else:\n            preflight_headers[\"Vary\"] = \"Origin\"\n        preflight_headers.update(\n            {\n                \"Access-Control-Allow-Methods\": \", \".join(allow_methods),\n                \"Access-Control-Max-Age\": str(max_age),\n            }\n        )\n        if allow_headers and \"*\" not in allow_headers:\n            preflight_headers[\"Access-Control-Allow-Headers\"] = \", \".join(allow_headers)\n        if allow_credentials:\n            preflight_headers[\"Access-Control-Allow-Credentials\"] = \"true\"\n\n        self.app = app\n        self.allow_origins = allow_origins\n        self.allow_methods = allow_methods\n        self.allow_headers = [h.lower() for h in allow_headers]\n        self.allow_all_origins = \"*\" in allow_origins\n        self.allow_all_headers = \"*\" in allow_headers\n        self.allow_origin_regex = compiled_allow_origin_regex\n        self.simple_headers = simple_headers\n        self.preflight_headers = preflight_headers\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        if scope[\"type\"] != \"http\":  # pragma: no cover\n            await self.app(scope, receive, send)\n            return\n\n        method = scope[\"method\"]\n        headers = Headers(scope=scope)\n        origin = headers.get(\"origin\")\n\n        if origin is None:\n            await self.app(scope, receive, send)\n            return\n\n        if method == \"OPTIONS\" and \"access-control-request-method\" in headers:\n            response = self.preflight_response(request_headers=headers)\n            await response(scope, receive, send)\n            return\n\n        await self.simple_response(scope, receive, send, request_headers=headers)\n\n    def is_allowed_origin(self, origin: str) -> bool:\n        if self.allow_all_origins:\n            return True\n\n        if self.allow_origin_regex is not None and self.allow_origin_regex.match(\n            origin\n        ):\n            return True\n\n        return origin in self.allow_origins\n\n    def preflight_response(self, request_headers: Headers) -> Response:\n        requested_origin = request_headers[\"origin\"]\n        requested_method = request_headers[\"access-control-request-method\"]\n        requested_headers = request_headers.get(\"access-control-request-headers\")\n\n        headers = dict(self.preflight_headers)\n        failures = []\n\n        if self.is_allowed_origin(origin=requested_origin):\n            if not self.allow_all_origins:\n                # If self.allow_all_origins is True, then the \"Access-Control-Allow-Origin\"\n                # header is already set to \"*\".\n                # If we only allow specific origins, then we have to mirror back\n                # the Origin header in the response.\n                headers[\"Access-Control-Allow-Origin\"] = requested_origin\n        else:\n            failures.append(\"origin\")\n\n        if requested_method not in self.allow_methods:\n            failures.append(\"method\")\n\n        # If we allow all headers, then we have to mirror back any requested\n        # headers in the response.\n        if self.allow_all_headers and requested_headers is not None:\n            headers[\"Access-Control-Allow-Headers\"] = requested_headers\n        elif requested_headers is not None:\n            for header in [h.lower() for h in requested_headers.split(\",\")]:\n                if header.strip() not in self.allow_headers:\n                    failures.append(\"headers\")\n\n        # We don't strictly need to use 400 responses here, since its up to\n        # the browser to enforce the CORS policy, but its more informative\n        # if we do.\n        if failures:\n            failure_text = \"Disallowed CORS \" + \", \".join(failures)\n            return PlainTextResponse(failure_text, status_code=400, headers=headers)\n\n        return PlainTextResponse(\"OK\", status_code=200, headers=headers)\n\n    async def simple_response(\n        self, scope: Scope, receive: Receive, send: Send, request_headers: Headers\n    ) -> None:\n        send = functools.partial(self.send, send=send, request_headers=request_headers)\n        await self.app(scope, receive, send)\n\n    async def send(\n        self, message: Message, send: Send, request_headers: Headers\n    ) -> None:\n        if message[\"type\"] != \"http.response.start\":\n            await send(message)\n            return\n\n        message.setdefault(\"headers\", [])\n        headers = MutableHeaders(scope=message)\n        headers.update(self.simple_headers)\n        origin = request_headers[\"Origin\"]\n        has_cookie = \"cookie\" in request_headers\n\n        # If request includes any cookie headers, then we must respond\n        # with the specific origin instead of '*'.\n        if self.allow_all_origins and has_cookie:\n            headers[\"Access-Control-Allow-Origin\"] = origin\n\n        # If we only allow specific origins, then we have to mirror back\n        # the Origin header in the response.\n        elif not self.allow_all_origins and self.is_allowed_origin(origin=origin):\n            headers[\"Access-Control-Allow-Origin\"] = origin\n            headers.add_vary_header(\"Origin\")\n        await send(message)\n", "path": "starlette/middleware/cors.py"}], "after_files": [{"content": "import functools\nimport re\nimport typing\n\nfrom starlette.datastructures import Headers, MutableHeaders\nfrom starlette.responses import PlainTextResponse, Response\nfrom starlette.types import ASGIApp, Message, Receive, Scope, Send\n\nALL_METHODS = (\"DELETE\", \"GET\", \"OPTIONS\", \"PATCH\", \"POST\", \"PUT\")\n\n\nclass CORSMiddleware:\n    def __init__(\n        self,\n        app: ASGIApp,\n        allow_origins: typing.Sequence[str] = (),\n        allow_methods: typing.Sequence[str] = (\"GET\",),\n        allow_headers: typing.Sequence[str] = (),\n        allow_credentials: bool = False,\n        allow_origin_regex: str = None,\n        expose_headers: typing.Sequence[str] = (),\n        max_age: int = 600,\n    ) -> None:\n\n        if \"*\" in allow_methods:\n            allow_methods = ALL_METHODS\n\n        compiled_allow_origin_regex = None\n        if allow_origin_regex is not None:\n            compiled_allow_origin_regex = re.compile(allow_origin_regex)\n\n        simple_headers = {}\n        if \"*\" in allow_origins:\n            simple_headers[\"Access-Control-Allow-Origin\"] = \"*\"\n        if allow_credentials:\n            simple_headers[\"Access-Control-Allow-Credentials\"] = \"true\"\n        if expose_headers:\n            simple_headers[\"Access-Control-Expose-Headers\"] = \", \".join(expose_headers)\n\n        preflight_headers = {}\n        if \"*\" in allow_origins:\n            preflight_headers[\"Access-Control-Allow-Origin\"] = \"*\"\n        else:\n            preflight_headers[\"Vary\"] = \"Origin\"\n        preflight_headers.update(\n            {\n                \"Access-Control-Allow-Methods\": \", \".join(allow_methods),\n                \"Access-Control-Max-Age\": str(max_age),\n            }\n        )\n        if allow_headers and \"*\" not in allow_headers:\n            preflight_headers[\"Access-Control-Allow-Headers\"] = \", \".join(allow_headers)\n        if allow_credentials:\n            preflight_headers[\"Access-Control-Allow-Credentials\"] = \"true\"\n\n        self.app = app\n        self.allow_origins = allow_origins\n        self.allow_methods = allow_methods\n        self.allow_headers = [h.lower() for h in allow_headers]\n        self.allow_all_origins = \"*\" in allow_origins\n        self.allow_all_headers = \"*\" in allow_headers\n        self.allow_origin_regex = compiled_allow_origin_regex\n        self.simple_headers = simple_headers\n        self.preflight_headers = preflight_headers\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        if scope[\"type\"] != \"http\":  # pragma: no cover\n            await self.app(scope, receive, send)\n            return\n\n        method = scope[\"method\"]\n        headers = Headers(scope=scope)\n        origin = headers.get(\"origin\")\n\n        if origin is None:\n            await self.app(scope, receive, send)\n            return\n\n        if method == \"OPTIONS\" and \"access-control-request-method\" in headers:\n            response = self.preflight_response(request_headers=headers)\n            await response(scope, receive, send)\n            return\n\n        await self.simple_response(scope, receive, send, request_headers=headers)\n\n    def is_allowed_origin(self, origin: str) -> bool:\n        if self.allow_all_origins:\n            return True\n\n        if self.allow_origin_regex is not None and self.allow_origin_regex.fullmatch(\n            origin\n        ):\n            return True\n\n        return origin in self.allow_origins\n\n    def preflight_response(self, request_headers: Headers) -> Response:\n        requested_origin = request_headers[\"origin\"]\n        requested_method = request_headers[\"access-control-request-method\"]\n        requested_headers = request_headers.get(\"access-control-request-headers\")\n\n        headers = dict(self.preflight_headers)\n        failures = []\n\n        if self.is_allowed_origin(origin=requested_origin):\n            if not self.allow_all_origins:\n                # If self.allow_all_origins is True, then the \"Access-Control-Allow-Origin\"\n                # header is already set to \"*\".\n                # If we only allow specific origins, then we have to mirror back\n                # the Origin header in the response.\n                headers[\"Access-Control-Allow-Origin\"] = requested_origin\n        else:\n            failures.append(\"origin\")\n\n        if requested_method not in self.allow_methods:\n            failures.append(\"method\")\n\n        # If we allow all headers, then we have to mirror back any requested\n        # headers in the response.\n        if self.allow_all_headers and requested_headers is not None:\n            headers[\"Access-Control-Allow-Headers\"] = requested_headers\n        elif requested_headers is not None:\n            for header in [h.lower() for h in requested_headers.split(\",\")]:\n                if header.strip() not in self.allow_headers:\n                    failures.append(\"headers\")\n\n        # We don't strictly need to use 400 responses here, since its up to\n        # the browser to enforce the CORS policy, but its more informative\n        # if we do.\n        if failures:\n            failure_text = \"Disallowed CORS \" + \", \".join(failures)\n            return PlainTextResponse(failure_text, status_code=400, headers=headers)\n\n        return PlainTextResponse(\"OK\", status_code=200, headers=headers)\n\n    async def simple_response(\n        self, scope: Scope, receive: Receive, send: Send, request_headers: Headers\n    ) -> None:\n        send = functools.partial(self.send, send=send, request_headers=request_headers)\n        await self.app(scope, receive, send)\n\n    async def send(\n        self, message: Message, send: Send, request_headers: Headers\n    ) -> None:\n        if message[\"type\"] != \"http.response.start\":\n            await send(message)\n            return\n\n        message.setdefault(\"headers\", [])\n        headers = MutableHeaders(scope=message)\n        headers.update(self.simple_headers)\n        origin = request_headers[\"Origin\"]\n        has_cookie = \"cookie\" in request_headers\n\n        # If request includes any cookie headers, then we must respond\n        # with the specific origin instead of '*'.\n        if self.allow_all_origins and has_cookie:\n            headers[\"Access-Control-Allow-Origin\"] = origin\n\n        # If we only allow specific origins, then we have to mirror back\n        # the Origin header in the response.\n        elif not self.allow_all_origins and self.is_allowed_origin(origin=origin):\n            headers[\"Access-Control-Allow-Origin\"] = origin\n            headers.add_vary_header(\"Origin\")\n        await send(message)\n", "path": "starlette/middleware/cors.py"}]}