Mercurial > p > roundup > code
comparison test/rest_common.py @ 8268:05d8806b25ad
fix: issue2551387 - TypeError: not indexable.
Fix crash due to uninitialized list element on a (Mini)FieldStorage
when unexpected input is posted via wsgi. This doesn't happen when
running roundup-server. It might happen under other front ends.
Moved the code that sets '.list = [] if .list == None' to the main
flow. Added an exception hander that logs the value of self.form if
self.form.list raises an AttributeError. This exception should never
happen if I understand the code correctly (but I probably don't).
Fixed a number of test cases that were broken because I was calling
Client and passing '[]' rather than a cgi.formStorage object.
Added test cases:
create a FileStorage (self.form) with .list = None.
check AttributeError exception and verify logging.
Problem reported and debugged by Christof Meerwald.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sun, 12 Jan 2025 12:34:52 -0500 |
| parents | 8c1e0459b73d |
| children | 1ffa1f42e1da |
comparison
equal
deleted
inserted
replaced
| 8267:7f0c7966d204 | 8268:05d8806b25ad |
|---|---|
| 1 import pytest | 1 import pytest |
| 2 import unittest | 2 import unittest |
| 3 import shutil | 3 import shutil |
| 4 import sys | 4 import sys |
| 5 import errno | 5 import errno |
| 6 import logging | |
| 6 | 7 |
| 7 from time import sleep | 8 from time import sleep |
| 8 from datetime import datetime, timedelta | 9 from datetime import datetime, timedelta |
| 9 from roundup.anypy.cgi_ import cgi | 10 from roundup.anypy.cgi_ import cgi |
| 10 from roundup.anypy.datetime_ import utcnow | 11 from roundup.anypy.datetime_ import utcnow |
| 73 | 74 |
| 74 NEEDS_INSTANCE = 1 | 75 NEEDS_INSTANCE = 1 |
| 75 | 76 |
| 76 | 77 |
| 77 class TestCase(): | 78 class TestCase(): |
| 79 | |
| 80 @pytest.fixture(autouse=True) | |
| 81 def inject_fixtures(self, caplog): | |
| 82 self._caplog = caplog | |
| 78 | 83 |
| 79 backend = None | 84 backend = None |
| 80 url_pfx = 'http://tracker.example/cgi-bin/roundup.cgi/bugs/rest/data/' | 85 url_pfx = 'http://tracker.example/cgi-bin/roundup.cgi/bugs/rest/data/' |
| 81 | 86 |
| 82 def setUp(self): | 87 def setUp(self): |
| 289 'HTTP_HOST': 'localhost', | 294 'HTTP_HOST': 'localhost', |
| 290 'TRACKER_NAME': 'rounduptest', | 295 'TRACKER_NAME': 'rounduptest', |
| 291 'HTTP_ORIGIN': 'http://tracker.example' | 296 'HTTP_ORIGIN': 'http://tracker.example' |
| 292 } | 297 } |
| 293 self.dummy_client = client.Client(self.instance, MockNull(), | 298 self.dummy_client = client.Client(self.instance, MockNull(), |
| 294 self.client_env, [], None) | 299 self.client_env, |
| 300 cgi.FieldStorage(), None) | |
| 295 self.dummy_client.request.headers.get = self.get_header | 301 self.dummy_client.request.headers.get = self.get_header |
| 296 self.dummy_client.db = self.db | 302 self.dummy_client.db = self.db |
| 297 | 303 |
| 298 self.empty_form = cgi.FieldStorage() | 304 self.empty_form = cgi.FieldStorage() |
| 299 # under python2 invoking: | 305 # under python2 invoking: |
| 2292 self.server.client.additional_headers['X-Content-Type-Options']) | 2298 self.server.client.additional_headers['X-Content-Type-Options']) |
| 2293 else: | 2299 else: |
| 2294 self.assertNotIn("X-Content-Type-Options", | 2300 self.assertNotIn("X-Content-Type-Options", |
| 2295 self.server.client.additional_headers) | 2301 self.server.client.additional_headers) |
| 2296 | 2302 |
| 2303 def testBadFormAttributeErrorException(self): | |
| 2304 env = { | |
| 2305 'PATH_INFO': 'rest/data/user', | |
| 2306 'HTTP_HOST': 'localhost', | |
| 2307 'TRACKER_NAME': 'rounduptest', | |
| 2308 "REQUEST_METHOD": "GET" | |
| 2309 } | |
| 2310 | |
| 2311 | |
| 2312 with self._caplog.at_level(logging.ERROR, logger="roundup"): | |
| 2313 with self.assertRaises(AttributeError) as exc: | |
| 2314 self.dummy_client = client.Client( | |
| 2315 self.instance, MockNull(), env, [], None) | |
| 2316 | |
| 2317 self.assertEqual(exc.exception.args[0], | |
| 2318 "'list' object has no attribute 'list'") | |
| 2319 | |
| 2320 # log should look like (with string not broken into parts): | |
| 2321 # [('roundup', 40, | |
| 2322 # 'Invalid self.form found (please report to the ' | |
| 2323 # 'roundup-users mailing list): []')] | |
| 2324 log = self._caplog.record_tuples[:] | |
| 2325 self.assertIn("Invalid self.form found", log[0][2]) | |
| 2326 | |
| 2297 def testDispatchBadAccept(self): | 2327 def testDispatchBadAccept(self): |
| 2298 # simulate: /rest/data/issue expect failure unknown accept settings | 2328 # simulate: /rest/data/issue expect failure unknown accept settings |
| 2299 body=b'{ "title": "Joe Doe has problems", \ | 2329 body=b'{ "title": "Joe Doe has problems", \ |
| 2300 "nosy": [ "1", "3" ], \ | 2330 "nosy": [ "1", "3" ], \ |
| 2301 "assignedto": "2", \ | 2331 "assignedto": "2", \ |
| 4506 'PATH_INFO': 'rest/data/user', | 4536 'PATH_INFO': 'rest/data/user', |
| 4507 'HTTP_HOST': 'localhost', | 4537 'HTTP_HOST': 'localhost', |
| 4508 'TRACKER_NAME': 'rounduptest', | 4538 'TRACKER_NAME': 'rounduptest', |
| 4509 "REQUEST_METHOD": "GET" | 4539 "REQUEST_METHOD": "GET" |
| 4510 } | 4540 } |
| 4541 | |
| 4511 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4542 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4512 [], None) | 4543 cgi.FieldStorage(), None) |
| 4513 self.dummy_client.db = self.db | 4544 self.dummy_client.db = self.db |
| 4514 self.dummy_client.request.headers.get = self.get_header | 4545 self.dummy_client.request.headers.get = self.get_header |
| 4515 self.empty_form = cgi.FieldStorage() | 4546 self.empty_form = cgi.FieldStorage() |
| 4516 self.terse_form = cgi.FieldStorage() | 4547 self.terse_form = cgi.FieldStorage() |
| 4517 self.terse_form.list = [ | 4548 self.terse_form.list = [ |
| 4518 cgi.MiniFieldStorage('@verbose', '0'), | 4549 cgi.MiniFieldStorage('@verbose', '0'), |
| 4519 ] | 4550 ] |
| 4520 self.dummy_client.form = cgi.FieldStorage() | |
| 4521 self.dummy_client.form.list = [ | 4551 self.dummy_client.form.list = [ |
| 4522 cgi.MiniFieldStorage('@fields', 'username,address'), | 4552 cgi.MiniFieldStorage('@fields', 'username,address'), |
| 4523 ] | 4553 ] |
| 4524 # accumulate json output for further analysis | 4554 # accumulate json output for further analysis |
| 4525 self.dummy_client.write = wh | 4555 self.dummy_client.write = wh |
| 4573 self.db.config['WEB_JWT_SECRET'] = "%s, %s, " % ( | 4603 self.db.config['WEB_JWT_SECRET'] = "%s, %s, " % ( |
| 4574 self.new_secret, self.old_secret | 4604 self.new_secret, self.old_secret |
| 4575 ) | 4605 ) |
| 4576 | 4606 |
| 4577 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4607 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4578 [], None) | 4608 cgi.FieldStorage(), None) |
| 4579 self.dummy_client.db = self.db | 4609 self.dummy_client.db = self.db |
| 4580 self.dummy_client.request.headers.get = self.get_header | 4610 self.dummy_client.request.headers.get = self.get_header |
| 4581 self.empty_form = cgi.FieldStorage() | 4611 self.empty_form = cgi.FieldStorage() |
| 4582 self.terse_form = cgi.FieldStorage() | 4612 self.terse_form = cgi.FieldStorage() |
| 4583 self.terse_form.list = [ | 4613 self.terse_form.list = [ |
| 4643 'TRACKER_NAME': 'rounduptest', | 4673 'TRACKER_NAME': 'rounduptest', |
| 4644 "REQUEST_METHOD": "GET" | 4674 "REQUEST_METHOD": "GET" |
| 4645 } | 4675 } |
| 4646 | 4676 |
| 4647 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4677 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4648 [], None) | 4678 cgi.FieldStorage(), None) |
| 4649 self.dummy_client.db = self.db | 4679 self.dummy_client.db = self.db |
| 4650 self.dummy_client.request.headers.get = self.get_header | 4680 self.dummy_client.request.headers.get = self.get_header |
| 4651 self.empty_form = cgi.FieldStorage() | 4681 self.empty_form = cgi.FieldStorage() |
| 4652 self.terse_form = cgi.FieldStorage() | 4682 self.terse_form = cgi.FieldStorage() |
| 4653 self.terse_form.list = [ | 4683 self.terse_form.list = [ |
| 4708 'HTTP_HOST': 'localhost', | 4738 'HTTP_HOST': 'localhost', |
| 4709 'TRACKER_NAME': 'rounduptest', | 4739 'TRACKER_NAME': 'rounduptest', |
| 4710 "REQUEST_METHOD": "GET" | 4740 "REQUEST_METHOD": "GET" |
| 4711 } | 4741 } |
| 4712 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4742 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4713 [], None) | 4743 cgi.FieldStorage(), None) |
| 4714 self.dummy_client.db = self.db | 4744 self.dummy_client.db = self.db |
| 4715 self.dummy_client.request.headers.get = self.get_header | 4745 self.dummy_client.request.headers.get = self.get_header |
| 4716 self.empty_form = cgi.FieldStorage() | 4746 self.empty_form = cgi.FieldStorage() |
| 4717 self.terse_form = cgi.FieldStorage() | 4747 self.terse_form = cgi.FieldStorage() |
| 4718 self.terse_form.list = [ | 4748 self.terse_form.list = [ |
| 4779 'HTTP_HOST': 'localhost', | 4809 'HTTP_HOST': 'localhost', |
| 4780 'TRACKER_NAME': 'rounduptest', | 4810 'TRACKER_NAME': 'rounduptest', |
| 4781 "REQUEST_METHOD": "GET" | 4811 "REQUEST_METHOD": "GET" |
| 4782 } | 4812 } |
| 4783 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4813 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4784 [], None) | 4814 cgi.FieldStorage(), None) |
| 4785 self.dummy_client.db = self.db | 4815 self.dummy_client.db = self.db |
| 4786 self.dummy_client.request.headers.get = self.get_header | 4816 self.dummy_client.request.headers.get = self.get_header |
| 4787 self.empty_form = cgi.FieldStorage() | 4817 self.empty_form = cgi.FieldStorage() |
| 4788 self.terse_form = cgi.FieldStorage() | 4818 self.terse_form = cgi.FieldStorage() |
| 4789 self.terse_form.list = [ | 4819 self.terse_form.list = [ |
| 4847 'HTTP_HOST': 'localhost', | 4877 'HTTP_HOST': 'localhost', |
| 4848 'TRACKER_NAME': 'rounduptest', | 4878 'TRACKER_NAME': 'rounduptest', |
| 4849 "REQUEST_METHOD": "GET" | 4879 "REQUEST_METHOD": "GET" |
| 4850 } | 4880 } |
| 4851 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4881 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4852 [], None) | 4882 cgi.FieldStorage(), None) |
| 4853 self.dummy_client.db = self.db | 4883 self.dummy_client.db = self.db |
| 4854 self.dummy_client.request.headers.get = self.get_header | 4884 self.dummy_client.request.headers.get = self.get_header |
| 4855 self.empty_form = cgi.FieldStorage() | 4885 self.empty_form = cgi.FieldStorage() |
| 4856 self.terse_form = cgi.FieldStorage() | 4886 self.terse_form = cgi.FieldStorage() |
| 4857 self.terse_form.list = [ | 4887 self.terse_form.list = [ |
| 4889 'HTTP_HOST': 'localhost', | 4919 'HTTP_HOST': 'localhost', |
| 4890 'TRACKER_NAME': 'rounduptest', | 4920 'TRACKER_NAME': 'rounduptest', |
| 4891 "REQUEST_METHOD": "GET" | 4921 "REQUEST_METHOD": "GET" |
| 4892 } | 4922 } |
| 4893 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4923 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4894 [], None) | 4924 cgi.FieldStorage(), None) |
| 4895 self.dummy_client.db = self.db | 4925 self.dummy_client.db = self.db |
| 4896 self.dummy_client.request.headers.get = self.get_header | 4926 self.dummy_client.request.headers.get = self.get_header |
| 4897 self.empty_form = cgi.FieldStorage() | 4927 self.empty_form = cgi.FieldStorage() |
| 4898 self.terse_form = cgi.FieldStorage() | 4928 self.terse_form = cgi.FieldStorage() |
| 4899 self.terse_form.list = [ | 4929 self.terse_form.list = [ |
| 4928 'HTTP_HOST': 'localhost', | 4958 'HTTP_HOST': 'localhost', |
| 4929 'TRACKER_NAME': 'rounduptest', | 4959 'TRACKER_NAME': 'rounduptest', |
| 4930 "REQUEST_METHOD": "GET" | 4960 "REQUEST_METHOD": "GET" |
| 4931 } | 4961 } |
| 4932 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4962 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4933 [], None) | 4963 cgi.FieldStorage(), None) |
| 4934 self.dummy_client.db = self.db | 4964 self.dummy_client.db = self.db |
| 4935 self.dummy_client.request.headers.get = self.get_header | 4965 self.dummy_client.request.headers.get = self.get_header |
| 4936 self.empty_form = cgi.FieldStorage() | 4966 self.empty_form = cgi.FieldStorage() |
| 4937 self.terse_form = cgi.FieldStorage() | 4967 self.terse_form = cgi.FieldStorage() |
| 4938 self.terse_form.list = [ | 4968 self.terse_form.list = [ |
| 4964 'HTTP_HOST': 'localhost', | 4994 'HTTP_HOST': 'localhost', |
| 4965 'TRACKER_NAME': 'rounduptest', | 4995 'TRACKER_NAME': 'rounduptest', |
| 4966 "REQUEST_METHOD": "GET" | 4996 "REQUEST_METHOD": "GET" |
| 4967 } | 4997 } |
| 4968 self.dummy_client = client.Client(self.instance, MockNull(), env, | 4998 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 4969 [], None) | 4999 cgi.FieldStorage(), None) |
| 4970 self.dummy_client.db = self.db | 5000 self.dummy_client.db = self.db |
| 4971 self.dummy_client.request.headers.get = self.get_header | 5001 self.dummy_client.request.headers.get = self.get_header |
| 4972 self.empty_form = cgi.FieldStorage() | 5002 self.empty_form = cgi.FieldStorage() |
| 4973 self.terse_form = cgi.FieldStorage() | 5003 self.terse_form = cgi.FieldStorage() |
| 4974 self.terse_form.list = [ | 5004 self.terse_form.list = [ |
| 5001 'HTTP_HOST': 'localhost', | 5031 'HTTP_HOST': 'localhost', |
| 5002 'TRACKER_NAME': 'rounduptest', | 5032 'TRACKER_NAME': 'rounduptest', |
| 5003 "REQUEST_METHOD": "GET" | 5033 "REQUEST_METHOD": "GET" |
| 5004 } | 5034 } |
| 5005 self.dummy_client = client.Client(self.instance, MockNull(), env, | 5035 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 5006 [], None) | 5036 cgi.FieldStorage(), None) |
| 5007 self.dummy_client.db = self.db | 5037 self.dummy_client.db = self.db |
| 5008 self.dummy_client.request.headers.get = self.get_header | 5038 self.dummy_client.request.headers.get = self.get_header |
| 5009 self.empty_form = cgi.FieldStorage() | 5039 self.empty_form = cgi.FieldStorage() |
| 5010 self.terse_form = cgi.FieldStorage() | 5040 self.terse_form = cgi.FieldStorage() |
| 5011 self.terse_form.list = [ | 5041 self.terse_form.list = [ |
| 5037 'HTTP_HOST': 'localhost', | 5067 'HTTP_HOST': 'localhost', |
| 5038 'TRACKER_NAME': 'rounduptest', | 5068 'TRACKER_NAME': 'rounduptest', |
| 5039 "REQUEST_METHOD": "GET" | 5069 "REQUEST_METHOD": "GET" |
| 5040 } | 5070 } |
| 5041 self.dummy_client = client.Client(self.instance, MockNull(), env, | 5071 self.dummy_client = client.Client(self.instance, MockNull(), env, |
| 5042 [], None) | 5072 cgi.FieldStorage(), None) |
| 5043 self.dummy_client.db = self.db | 5073 self.dummy_client.db = self.db |
| 5044 self.dummy_client.request.headers.get = self.get_header | 5074 self.dummy_client.request.headers.get = self.get_header |
| 5045 self.empty_form = cgi.FieldStorage() | 5075 self.empty_form = cgi.FieldStorage() |
| 5046 self.terse_form = cgi.FieldStorage() | 5076 self.terse_form = cgi.FieldStorage() |
| 5047 self.terse_form.list = [ | 5077 self.terse_form.list = [ |
