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 = [

Roundup Issue Tracker: http://roundup-tracker.org/