)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5a14b78989b259a7b4f4ad8fdab440a4ddeba2f8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"9b9e7c69_1de5ed8e","updated":"2026-06-03 22:41:34.000000000","message":"I\u0027ve got some questions around `versions` params, but even setting that aside, we ought to test more params -- I can back some of the fix out:\n```\ndiff --git a/swift/common/middleware/s3api/controllers/bucket.py b/swift/common/middleware/s3api/controllers/bucket.py\nindex 2a608ec29..912c74a82 100644\n--- a/swift/common/middleware/s3api/controllers/bucket.py\n+++ b/swift/common/middleware/s3api/controllers/bucket.py\n@@ -128,10 +128,10 @@ class BucketController(Controller):\n             query[\u0027delimiter\u0027] \u003d self._validated_utf8_param(req, \u0027delimiter\u0027)\n         fetch_owner \u003d False\n         if \u0027versions\u0027 in req.params:\n-            query[\u0027versions\u0027] \u003d self._validated_utf8_param(req, \u0027versions\u0027)\n+            query[\u0027versions\u0027] \u003d swob.wsgi_to_str(req.params[\u0027versions\u0027])\n             listing_type \u003d \u0027object-versions\u0027\n-            version_marker \u003d self._validated_utf8_param(\n-                req, \u0027version-id-marker\u0027)\n+            version_marker \u003d swob.wsgi_to_str(req.params.get(\n+                \u0027version-id-marker\u0027))\n             if \u0027key-marker\u0027 in req.params:\n                 query[\u0027marker\u0027] \u003d self._validated_utf8_param(\n                     req, \u0027key-marker\u0027)\n```\nand no tests pop.","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"}],"swift/common/middleware/s3api/controllers/bucket.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5a14b78989b259a7b4f4ad8fdab440a4ddeba2f8","unresolved":true,"context_lines":[{"line_number":128,"context_line":"            query[\u0027delimiter\u0027] \u003d self._validated_utf8_param(req, \u0027delimiter\u0027)"},{"line_number":129,"context_line":"        fetch_owner \u003d False"},{"line_number":130,"context_line":"        if \u0027versions\u0027 in req.params:"},{"line_number":131,"context_line":"            query[\u0027versions\u0027] \u003d self._validated_utf8_param(req, \u0027versions\u0027)"},{"line_number":132,"context_line":"            listing_type \u003d \u0027object-versions\u0027"},{"line_number":133,"context_line":"            version_marker \u003d self._validated_utf8_param("},{"line_number":134,"context_line":"                req, \u0027version-id-marker\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"aa6b90a0_99d2f855","line":131,"updated":"2026-06-03 22:41:34.000000000","message":"Do we actually need to validate this? If so, should we support any value other than `\u0027\u0027`? What does AWS do?","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"c2340ff50cf2019a3103e06a768d7e91683ce001","unresolved":false,"context_lines":[{"line_number":128,"context_line":"            query[\u0027delimiter\u0027] \u003d self._validated_utf8_param(req, \u0027delimiter\u0027)"},{"line_number":129,"context_line":"        fetch_owner \u003d False"},{"line_number":130,"context_line":"        if \u0027versions\u0027 in req.params:"},{"line_number":131,"context_line":"            query[\u0027versions\u0027] \u003d self._validated_utf8_param(req, \u0027versions\u0027)"},{"line_number":132,"context_line":"            listing_type \u003d \u0027object-versions\u0027"},{"line_number":133,"context_line":"            version_marker \u003d self._validated_utf8_param("},{"line_number":134,"context_line":"                req, \u0027version-id-marker\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"6256891e_e1170367","line":131,"in_reply_to":"aa6b90a0_99d2f855","updated":"2026-06-04 18:28:27.000000000","message":"When using the s3 client for AWS\n```bash\naws s3api list-object-versions   --bucket my-bucket --debug\n```\n\nThe request URL is `https://my-bucket.us-east-2.amazonaws.com/?versions\u0026encoding-type\u003durl`\n\nTrying to forcefully give S3 anything else (like versions\u003dtrue or versions\u003d\\x89 or versions\u003d):\n```bash\nHTTP/1.1 403 Forbidden\n```\n\nExample command:\n```bash\ncurl -i \\\n  \u0027https://my-bucket.us-east-2.amazonaws.com/?versions\u0026encoding-type\u003durl\u0027 \\\n  -H \u0027Host: my-bucket.us-east-2.amazonaws.com\u0027 \\\n  -H \u0027X-Amz-Date: 20260604T164111Z\u0027 \\\n  -H \u0027X-Amz-Content-SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\u0027 \\\n  -H \u0027X-Amz-Security-Token: ...\u0027 \\\n  -H \u0027Authorization: ...\u0027 \\\n  -H \u0027User-Agent: aws-cli/2.34.57 md/awscrt#0.32.2 ua/2.1 os/linux#6.17.0-23-generic md/arch#x86_64 lang/python#3.14.5 md/pyimpl#CPython m/n,Z,E,C,b cfg/retry-mode#standard md/installer#exe md/distrib#ubuntu.24 md/prompt#off md/command#s3api.list-object-versions\u0027\n```\n\nSo we would not need to verify anything in the value for `versions` since AWS doesn\u0027t even allow a value to being with.","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5a14b78989b259a7b4f4ad8fdab440a4ddeba2f8","unresolved":true,"context_lines":[{"line_number":149,"context_line":"                           \u0027a key marker.\u0027)"},{"line_number":150,"context_line":"                raise InvalidArgument(\u0027version-id-marker\u0027,"},{"line_number":151,"context_line":"                                      version_marker, err_msg)"},{"line_number":152,"context_line":"        elif int(req.params.get(\u0027list-type\u0027, \u00271\u0027)) \u003d\u003d 2:"},{"line_number":153,"context_line":"            listing_type \u003d \u0027version-2\u0027"},{"line_number":154,"context_line":"            if \u0027start-after\u0027 in req.params:"},{"line_number":155,"context_line":"                query[\u0027marker\u0027] \u003d self._validated_utf8_param("}],"source_content_type":"text/x-python","patch_set":1,"id":"2719e7f9_af73e040","line":152,"range":{"start_line":152,"start_character":13,"end_line":152,"end_character":50},"updated":"2026-06-03 22:41:34.000000000","message":"Off-topic: we should catch the possible `ValueError`","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"c2340ff50cf2019a3103e06a768d7e91683ce001","unresolved":false,"context_lines":[{"line_number":149,"context_line":"                           \u0027a key marker.\u0027)"},{"line_number":150,"context_line":"                raise InvalidArgument(\u0027version-id-marker\u0027,"},{"line_number":151,"context_line":"                                      version_marker, err_msg)"},{"line_number":152,"context_line":"        elif int(req.params.get(\u0027list-type\u0027, \u00271\u0027)) \u003d\u003d 2:"},{"line_number":153,"context_line":"            listing_type \u003d \u0027version-2\u0027"},{"line_number":154,"context_line":"            if \u0027start-after\u0027 in req.params:"},{"line_number":155,"context_line":"                query[\u0027marker\u0027] \u003d self._validated_utf8_param("}],"source_content_type":"text/x-python","patch_set":1,"id":"1c71633b_7cca4751","line":152,"range":{"start_line":152,"start_character":13,"end_line":152,"end_character":50},"in_reply_to":"2719e7f9_af73e040","updated":"2026-06-04 18:28:27.000000000","message":"Acknowledged","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5a14b78989b259a7b4f4ad8fdab440a4ddeba2f8","unresolved":true,"context_lines":[{"line_number":157,"context_line":"            # continuation-token overrides start-after"},{"line_number":158,"context_line":"            if \u0027continuation-token\u0027 in req.params:"},{"line_number":159,"context_line":"                decoded \u003d b64decode("},{"line_number":160,"context_line":"                    req.params[\u0027continuation-token\u0027]).decode(\u0027utf8\u0027)"},{"line_number":161,"context_line":"                query[\u0027marker\u0027] \u003d decoded"},{"line_number":162,"context_line":"            if \u0027fetch-owner\u0027 in req.params:"},{"line_number":163,"context_line":"                fetch_owner \u003d config_true_value(req.params[\u0027fetch-owner\u0027])"}],"source_content_type":"text/x-python","patch_set":1,"id":"53933e53_cdb41a93","line":160,"updated":"2026-06-03 22:41:34.000000000","message":"Off-topic: and here -- it seems like this could fail in so many ways.","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"c2340ff50cf2019a3103e06a768d7e91683ce001","unresolved":false,"context_lines":[{"line_number":157,"context_line":"            # continuation-token overrides start-after"},{"line_number":158,"context_line":"            if \u0027continuation-token\u0027 in req.params:"},{"line_number":159,"context_line":"                decoded \u003d b64decode("},{"line_number":160,"context_line":"                    req.params[\u0027continuation-token\u0027]).decode(\u0027utf8\u0027)"},{"line_number":161,"context_line":"                query[\u0027marker\u0027] \u003d decoded"},{"line_number":162,"context_line":"            if \u0027fetch-owner\u0027 in req.params:"},{"line_number":163,"context_line":"                fetch_owner \u003d config_true_value(req.params[\u0027fetch-owner\u0027])"}],"source_content_type":"text/x-python","patch_set":1,"id":"1fc38804_b4e7c288","line":160,"in_reply_to":"53933e53_cdb41a93","updated":"2026-06-04 18:28:27.000000000","message":"Acknowledged","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"054f28d2c21b8427cf242d2d6098373ac592487d","unresolved":false,"context_lines":[{"line_number":118,"context_line":"            query[\u0027delimiter\u0027] \u003d swob.wsgi_to_str(req.params[\u0027delimiter\u0027])"},{"line_number":119,"context_line":"        fetch_owner \u003d False"},{"line_number":120,"context_line":"        if \u0027versions\u0027 in req.params:"},{"line_number":121,"context_line":"            query[\u0027versions\u0027] \u003d swob.wsgi_to_str(req.params[\u0027versions\u0027])"},{"line_number":122,"context_line":"            listing_type \u003d \u0027object-versions\u0027"},{"line_number":123,"context_line":"            version_marker \u003d swob.wsgi_to_str(req.params.get("},{"line_number":124,"context_line":"                \u0027version-id-marker\u0027))"}],"source_content_type":"text/x-python","patch_set":3,"id":"fea41508_a2107f9f","side":"PARENT","line":121,"updated":"2026-07-10 07:13:31.000000000","message":"This seems to miss the new _validata_utf8_param so what if this triggers. Ie running a request with `versions\u003d\\x98` will still cause a 500. Not sure we expect utf8 there, but still probably worth the guard?","commit_id":"efa02d8ad0baccc7143d9626bf725cf4f8df35d9"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"054f28d2c21b8427cf242d2d6098373ac592487d","unresolved":false,"context_lines":[{"line_number":50,"context_line":"        value \u003d swob.wsgi_to_str(req.params.get(name))"},{"line_number":51,"context_line":"        if value is None:"},{"line_number":52,"context_line":"            return None"},{"line_number":53,"context_line":"        if value and not check_utf8(value):"},{"line_number":54,"context_line":"            raise InvalidArgument(name, swob.wsgi_quote(req.params[name]))"},{"line_number":55,"context_line":"        return value"},{"line_number":56,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"196dda2a_8a532e97","line":53,"updated":"2026-07-10 07:13:31.000000000","message":"check_utf8 also rejects null \u0027\\x00\u0027. So prefix/delimiter/markers with a \\x00 will now get a 400 and not be passed back into swift. It\u0027s probably ok, but something to note. We sometimes use \\x00 if shard range checks and the like.. but that isn\u0027t here in s3api. So might need to think on this.. tho probably ok.","commit_id":"6c3bb1d22a644ca4fc0a3bf0f950edfc494b6705"}],"test/unit/common/middleware/s3api/test_bucket.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5a14b78989b259a7b4f4ad8fdab440a4ddeba2f8","unresolved":true,"context_lines":[{"line_number":859,"context_line":"        self._assert_invalid_utf8_list_param("},{"line_number":860,"context_line":"            \u0027list-type\u003d2\u0026start-after\u003d\\x98\u0027, \u0027start-after\u0027)"},{"line_number":861,"context_line":""},{"line_number":862,"context_line":"    def test_bucket_GET_versions_with_invalid_utf8_queries(self):"},{"line_number":863,"context_line":"        self._assert_invalid_utf8_list_param("},{"line_number":864,"context_line":"            \u0027versions\u0026key-marker\u003d\\x98\u0027, \u0027key-marker\u0027)"},{"line_number":865,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"75c55115_58bde5f2","line":862,"updated":"2026-06-03 22:41:34.000000000","message":"Shouldn\u0027t we be checking `versions` and `version-id-marker` here?\n\nWhat about checking `prefix` or `delimiter` here, too?","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"c2340ff50cf2019a3103e06a768d7e91683ce001","unresolved":false,"context_lines":[{"line_number":859,"context_line":"        self._assert_invalid_utf8_list_param("},{"line_number":860,"context_line":"            \u0027list-type\u003d2\u0026start-after\u003d\\x98\u0027, \u0027start-after\u0027)"},{"line_number":861,"context_line":""},{"line_number":862,"context_line":"    def test_bucket_GET_versions_with_invalid_utf8_queries(self):"},{"line_number":863,"context_line":"        self._assert_invalid_utf8_list_param("},{"line_number":864,"context_line":"            \u0027versions\u0026key-marker\u003d\\x98\u0027, \u0027key-marker\u0027)"},{"line_number":865,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"7202e786_01788096","line":862,"in_reply_to":"75c55115_58bde5f2","updated":"2026-06-04 18:28:27.000000000","message":"Acknowledged","commit_id":"630106db78b1d4b449be4b78779f3b442eee915c"}]}
