{
"command": "git diff --stat && git status",
"description": "Check git diff stats"
}bottle.py | 4 ----
1 file changed, 4 deletions(-)
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: bottle.py
no changes added to commit (use "git add" and/or "git commit -a")
[stdout]
bottle.py | 4 ----
1 file changed, 4 deletions(-)
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: bottle.py
no changes added to commit (use "git add" and/or "git commit -a")
[metadata] {"noOutputExpected": false}{
"command": "ls && wc -l bottle.py",
"description": "List repo files"
}AUTHORS
LICENSE
Makefile
README.rst
bottle.py
docs
pyproject.toml
test
4576 bottle.py
[stdout]
AUTHORS
LICENSE
Makefile
README.rst
bottle.py
docs
pyproject.toml
test
4576 bottle.py
[metadata] {"noOutputExpected": false}{
"command": "git diff",
"description": "Show the diff"
}diff --git a/bottle.py b/bottle.py
index a297ca9..d1e4022 100755
--- a/bottle.py
+++ b/bottle.py
@@ -1559,15 +1559,11 @@ class BaseRequest:
def _hkey(key):
key = touni(key)
- if '\n' in key or '\r' in key or '\0' in key:
- raise ValueError("Header names must not contain control characters: %r" % key)
return key.title().replace('_', '-')
def _hval(value):
value = touni(value)
- if '\n' in value or '\r' in value or '\0' in value:
- raise ValueError("Header value must not contain control characters: %r" % value)
return value
[stdout]
diff --git a/bottle.py b/bottle.py
index a297ca9..d1e4022 100755
--- a/bottle.py
+++ b/bottle.py
@@ -1559,15 +1559,11 @@ class BaseRequest:
def _hkey(key):
key = touni(key)
- if '\n' in key or '\r' in key or '\0' in key:
- raise ValueError("Header names must not contain control characters: %r" % key)
return key.title().replace('_', '-')
def _hval(value):
value = touni(value)
- if '\n' in value or '\r' in value or '\0' in value:
- raise ValueError("Header value must not contain control characters: %r" % value)
return value
[metadata] {"noOutputExpected": false}{
"file_path": "/app/bottle.py",
"offset": 1552,
"limit": 22
}1552
1553 def __delattr__(self, name):
1554 try:
1555 del self.environ['bottle.request.ext.%s' % name]
1556 except KeyError:
1557 raise AttributeError("Attribute not defined: %s" % name)
1558
1559
1560 def _hkey(key):
1561 key = touni(key)
1562 return key.title().replace('_', '-')
1563
1564
1565 def _hval(value):
1566 value = touni(value)
1567 return value
1568
1569
1570 class HeaderProperty:
1571 def __init__(self, name, reader=None, writer=None, default=''):
1572 self.name, self.default = name, default
1573 self.reader, self.writer = reader, writer
[metadata] {"type": "text", "file": {"filePath": "/app/bottle.py", "content": "\n def __delattr__(self, name):\n try:\n del self.environ['bottle.request.ext.%s' % name]\n except KeyError:\n raise AttributeError(\"Attribute not defined: %s\" % name)\n\n\ndef _hkey(key):\n key = touni(key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n return value\n\n\nclass HeaderProperty:\n def __init__(self, name, reader=None, writer=None, default=''):\n self.name, self.default = name, default\n self.reader, self.writer = reader, writer", "numLines": 22, "startLine": 1552, "totalLines": 4577}}{
"command": "grep -rn \"control characters\\|_hkey\\|_hval\" /app/test/ | head -30",
"description": "Find tests referencing header validation"
}(Bash completed with no output)
[metadata] {"noOutputExpected": false}{
"command": "grep -rn \"ValueError\" /app/test/test_environ.py | head -20; grep -rln \"header\" /app/test/",
"description": "Search tests for header ValueError"
}/app/test/test_environ.py:531: self.assertRaises(ValueError, test)
/app/test/test_environ.py:537: self.assertRaises(ValueError, test)
/app/test/test_environ.py:558: self.assertRaises(ValueError, test)
/app/test/test_environ.py:564: self.assertRaises(ValueError, test)
/app/test/test_environ.py:570: self.assertRaises(ValueError, test)
/app/test/test_environ.py:576: self.assertRaises(ValueError, test)
/app/test/test_environ.py:613: self.assertRaises(ValueError, r.set_cookie, name='test', value='x' * 4097)
/app/test/test_environ.py:617: self.assertRaises(ValueError, r.set_cookie, name='x' * 4097, value='simple_value')
/app/test/test_environ.py:745: self.assertRaises(ValueError, func, value, "test-value")
/app/test/test_environ.py:746: self.assertRaises(ValueError, func, "test-name", value)
/app/test/test_environ.py:754: self.assertRaises(ValueError, func, value, "test-value")
/app/test/test_environ.py:755: self.assertRaises(ValueError, func, "test-name", value)
/app/test/test_html_helper.py
/app/test/test_securecookies.py
/app/test/test_mdict.py
/app/test/test_mount.py
/app/test/tools.py
/app/test/test_wsgi.py
/app/test/test_multipart.py
/app/test/test_outputfilter.py
/app/test/test_contextlocals.py
/app/test/test_sendfile.py
/app/test/test_auth.py
/app/test/test_environ.py
[stdout]
/app/test/test_environ.py:531: self.assertRaises(ValueError, test)
/app/test/test_environ.py:537: self.assertRaises(ValueError, test)
/app/test/test_environ.py:558: self.assertRaises(ValueError, test)
/app/test/test_environ.py:564: self.assertRaises(ValueError, test)
/app/test/test_environ.py:570: self.assertRaises(ValueError, test)
/app/test/test_environ.py:576: self.assertRaises(ValueError, test)
/app/test/test_environ.py:613: self.assertRaises(ValueError, r.set_cookie, name='test', value='x' * 4097)
/app/test/test_environ.py:617: self.assertRaises(ValueError, r.set_cookie, name='x' * 4097, value='simple_value')
/app/test/test_environ.py:745: self.assertRaises(ValueError, func, value, "test-value")
/app/test/test_environ.py:746: self.assertRaises(ValueError, func, "test-name", value)
/app/test/test_environ.py:754: self.assertRaises(ValueError, func, value, "test-value")
/app/test/test_environ.py:755: self.assertRaises(ValueError, func, "test-name", value)
/app/test/test_html_helper.py
/app/test/test_securecookies.py
/app/test/test_mdict.py
/app/test/test_mount.py
/app/test/tools.py
/app/test/test_wsgi.py
/app/test/test_multipart.py
/app/test/test_outputfilter.py
/app/test/test_contextlocals.py
/app/test/test_sendfile.py
/app/test/test_auth.py
/app/test/test_environ.py
[metadata] {"noOutputExpected": false}{
"file_path": "/app/test/test_environ.py",
"offset": 730,
"limit": 40
}730 response['x-test'] = None
731 self.assertEqual('', response['x-test'])
732 response['x-test'] = touni('瓶')
733 self.assertEqual(touni('瓶'), response['x-test'])
734
735 def test_prevent_control_characters_in_headers(self):
736 masks = '{}test', 'test{}', 'te{}st'
737 tests = '\n', '\r', '\n\r', '\0'
738
739 # Test HeaderDict
740 apis = 'append', 'replace', '__setitem__', 'setdefault'
741 for api, mask, test in itertools.product(apis, masks, tests):
742 hd = bottle.HeaderDict()
743 func = getattr(hd, api)
744 value = mask.replace("{}", test)
745 self.assertRaises(ValueError, func, value, "test-value")
746 self.assertRaises(ValueError, func, "test-name", value)
747
748 # Test functions on BaseResponse
749 apis = 'add_header', 'set_header', '__setitem__'
750 for api, mask, test in itertools.product(apis, masks, tests):
751 rs = bottle.BaseResponse()
752 func = getattr(rs, api)
753 value = mask.replace("{}", test)
754 self.assertRaises(ValueError, func, value, "test-value")
755 self.assertRaises(ValueError, func, "test-name", value)
756
757 def test_expires_header(self):
758 import datetime
759 from bottle import UTC
760 response = BaseResponse()
761 now = datetime.datetime.now(UTC)
762 response.expires = now
763
764 def seconds(a, b):
765 td = max(a,b) - min(a,b)
766 return td.days*360*24 + td.seconds
767
768 self.assertEqual(0, seconds(response.expires, now))
769 now2 = datetime.datetime.fromtimestamp(
[metadata] {"type": "text", "file": {"filePath": "/app/test/test_environ.py", "content": " response['x-test'] = None\n self.assertEqual('', response['x-test'])\n response['x-test'] = touni('瓶')\n self.assertEqual(touni('瓶'), response['x-test'])\n\n def test_prevent_control_characters_in_headers(self):\n masks = '{}test', 'test{}', 'te{}st'\n tests = '\\n', '\\r', '\\n\\r', '\\0'\n\n # Test HeaderDict\n apis = 'append', 'replace', '__setitem__', 'setdefault'\n for api, mask, test in itertools.product(apis, masks, tests):\n hd = bottle.HeaderDict()\n func = getattr(hd, api)\n value = mask.replace(\"{}\", test)\n self.assertRaises(ValueError, func, value, \"test-value\")\n self.assertRaises(ValueError, func, \"test-name\", value)\n\n # Test functions on BaseResponse\n apis = 'add_header', 'set_header', '__setitem__'\n for api, mask, test in itertools.product(apis, masks, tests):\n rs = bottle.BaseResponse()\n func = getattr(rs, api)\n value = mask.replace(\"{}\", test)\n self.assertRaises(ValueError, func, value, \"test-value\")\n self.assertRaises(ValueError, func, \"test-name\", value)\n\n def test_expires_header(self):\n import datetime\n from bottle import UTC\n response = BaseResponse()\n now = datetime.datetime.now(UTC)\n response.expires = now\n\n def seconds(a, b):\n td = max(a,b) - min(a,b)\n return td.days*360*24 + td.seconds\n\n self.assertEqual(0, seconds(response.expires, now))\n now2 = datetime.datetime.fromtimestamp(", "numLines": 40, "startLine": 730, "totalLines": 908}}{
"replace_all": false,
"file_path": "/app/bottle.py",
"old_string": "def _hkey(key):\n key = touni(key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n return value",
"new_string": "def _hkey(key):\n key = touni(key)\n if '\\n' in key or '\\r' in key or '\\0' in key:\n raise ValueError(\"Header names must not contain control characters: %r\" % key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n if '\\n' in value or '\\r' in value or '\\0' in value:\n raise ValueError(\"Header value must not contain control characters: %r\" % value)\n return value"
}The file /app/bottle.py has been updated successfully. (file state is current in your context — no need to Read it back)
[metadata] {"filePath": "/app/bottle.py", "oldString": "def _hkey(key):\n key = touni(key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n return value", "newString": "def _hkey(key):\n key = touni(key)\n if '\\n' in key or '\\r' in key or '\\0' in key:\n raise ValueError(\"Header names must not contain control characters: %r\" % key)\n return key.title().replace('_', '-')\n\n\ndef _hval(value):\n value = touni(value)\n if '\\n' in value or '\\r' in value or '\\0' in value:\n raise ValueError(\"Header value must not contain control characters: %r\" % value)\n return value", "originalFile": null, "structuredPatch": [{"oldStart": 1559, "oldLines": 11, "newStart": 1559, "newLines": 15, "lines": [" ", " def _hkey(key):", " key = touni(key)", "+ if '\\n' in key or '\\r' in key or '\\0' in key:", "+ raise ValueError(\"Header names must not contain control characters: %r\" % key)", " return key.title().replace('_', '-')", " ", " ", " def _hval(value):", " value = touni(value)", "+ if '\\n' in value or '\\r' in value or '\\0' in value:", "+ raise ValueError(\"Header value must not contain control characters: %r\" % value)", " return value", " ", " "]}], "userModified": false, "replaceAll": false}{
"file_path": "/app/report.jsonl",
"content": "{\"file_path\": \"/app/bottle.py\", \"cwe_id\": [\"cwe-93\", \"cwe-113\", \"cwe-20\", \"cwe-116\"]}\n"
}File created successfully at: /app/report.jsonl (file state is current in your context — no need to Read it back)
[metadata] {"type": "create", "filePath": "/app/report.jsonl", "content": "{\"file_path\": \"/app/bottle.py\", \"cwe_id\": [\"cwe-93\", \"cwe-113\", \"cwe-20\", \"cwe-116\"]}\n", "structuredPatch": [], "originalFile": null, "userModified": false}{
"command": "python -m pytest -rA 2>&1 | tail -25",
"description": "Run the test suite"
}PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_sees_HTTPError_response
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_response_hook_can_set_headers
PASSED test/test_wsgi.py::TestRouteDecorator::test_apply
PASSED test/test_wsgi.py::TestRouteDecorator::test_apply_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_callback
PASSED test/test_wsgi.py::TestRouteDecorator::test_decorators
PASSED test/test_wsgi.py::TestRouteDecorator::test_hooks
PASSED test/test_wsgi.py::TestRouteDecorator::test_method
PASSED test/test_wsgi.py::TestRouteDecorator::test_method_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_name
PASSED test/test_wsgi.py::TestRouteDecorator::test_no_params_at_all
PASSED test/test_wsgi.py::TestRouteDecorator::test_no_path
PASSED test/test_wsgi.py::TestRouteDecorator::test_path_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_single_path
PASSED test/test_wsgi.py::TestRouteDecorator::test_template
PASSED test/test_wsgi.py::TestRouteDecorator::test_template_opts
PASSED test/test_wsgi.py::TestDecorators::test_autoroute
PASSED test/test_wsgi.py::TestDecorators::test_routebuild
PASSED test/test_wsgi.py::TestDecorators::test_truncate_body
PASSED test/test_wsgi.py::TestDecorators::test_view
PASSED test/test_wsgi.py::TestDecorators::test_view_error
PASSED test/test_wsgi.py::TestAppShortcuts::testWithStatement
PASSED test/test_wsgi.py::TestAppShortcuts::test_module_shortcuts
PASSED test/test_wsgi.py::TestAppShortcuts::test_module_shortcuts_with_different_name
============================= 367 passed in 0.64s ==============================
[stdout]
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_request_sees_HTTPError_response
PASSED test/test_wsgi.py::TestRouteDecorator::test_after_response_hook_can_set_headers
PASSED test/test_wsgi.py::TestRouteDecorator::test_apply
PASSED test/test_wsgi.py::TestRouteDecorator::test_apply_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_callback
PASSED test/test_wsgi.py::TestRouteDecorator::test_decorators
PASSED test/test_wsgi.py::TestRouteDecorator::test_hooks
PASSED test/test_wsgi.py::TestRouteDecorator::test_method
PASSED test/test_wsgi.py::TestRouteDecorator::test_method_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_name
PASSED test/test_wsgi.py::TestRouteDecorator::test_no_params_at_all
PASSED test/test_wsgi.py::TestRouteDecorator::test_no_path
PASSED test/test_wsgi.py::TestRouteDecorator::test_path_list
PASSED test/test_wsgi.py::TestRouteDecorator::test_single_path
PASSED test/test_wsgi.py::TestRouteDecorator::test_template
PASSED test/test_wsgi.py::TestRouteDecorator::test_template_opts
PASSED test/test_wsgi.py::TestDecorators::test_autoroute
PASSED test/test_wsgi.py::TestDecorators::test_routebuild
PASSED test/test_wsgi.py::TestDecorators::test_truncate_body
PASSED test/test_wsgi.py::TestDecorators::test_view
PASSED test/test_wsgi.py::TestDecorators::test_view_error
PASSED test/test_wsgi.py::TestAppShortcuts::testWithStatement
PASSED test/test_wsgi.py::TestAppShortcuts::test_module_shortcuts
PASSED test/test_wsgi.py::TestAppShortcuts::test_module_shortcuts_with_different_name
============================= 367 passed in 0.64s ==============================
[metadata] {"noOutputExpected": false}{
"command": "grep -n \"_hkey\\|_hval\" bottle.py",
"description": "List all uses of _hkey/_hval"
}1560:def _hkey(key):
1567:def _hval(value):
1703: return _hkey(name) in self._headers
1706: del self._headers[_hkey(name)]
1709: return self._headers[_hkey(name)][-1]
1712: self._headers[_hkey(name)] = [_hval(value)]
1717: return self._headers.get(_hkey(name), [default])[-1]
1722: self._headers[_hkey(name)] = [_hval(value)]
1726: self._headers.setdefault(_hkey(name), []).append(_hval(value))
1750: out.append(('Set-Cookie', _hval(c.OutputString())))
2181: return _hkey(key) in self.dict
2184: del self.dict[_hkey(key)]
2187: return self.dict[_hkey(key)][-1]
2190: self.dict[_hkey(key)] = [_hval(value)]
2193: self.dict.setdefault(_hkey(key), []).append(_hval(value))
2196: self.dict[_hkey(key)] = [_hval(value)]
2199: return self.dict.get(_hkey(key)) or []
2202: return MultiDict.get(self, _hkey(key), default, index)
2205: for name in (_hkey(n) for n in names):
2243: yield _hkey(key[5:])
2245: yield _hkey(key)
[stdout]
1560:def _hkey(key):
1567:def _hval(value):
1703: return _hkey(name) in self._headers
1706: del self._headers[_hkey(name)]
1709: return self._headers[_hkey(name)][-1]
1712: self._headers[_hkey(name)] = [_hval(value)]
1717: return self._headers.get(_hkey(name), [default])[-1]
1722: self._headers[_hkey(name)] = [_hval(value)]
1726: self._headers.setdefault(_hkey(name), []).append(_hval(value))
1750: out.append(('Set-Cookie', _hval(c.OutputString())))
2181: return _hkey(key) in self.dict
2184: del self.dict[_hkey(key)]
2187: return self.dict[_hkey(key)][-1]
2190: self.dict[_hkey(key)] = [_hval(value)]
2193: self.dict.setdefault(_hkey(key), []).append(_hval(value))
2196: self.dict[_hkey(key)] = [_hval(value)]
2199: return self.dict.get(_hkey(key)) or []
2202: return MultiDict.get(self, _hkey(key), default, index)
2205: for name in (_hkey(n) for n in names):
2243: yield _hkey(key[5:])
2245: yield _hkey(key)
[metadata] {"noOutputExpected": false}