1481: Review Board 500 error if testing done is over 65535 characters (or a bit smaller)
- Fixed
- Review Board
lon***@gmai***** (Google Code) (Is this you? Claim this profile.) | |
Aug. 29, 2011 | |
1648 |
What version are you running? 1.5.0.1 What's the URL of the page containing the problem? private, but can be reproduced easily, by submitting a new request see: http://demo.reviewboard.org/r/3217/ (or http://demo.reviewboard.org/r/3217/diff as the above reports a 500) What steps will reproduce the problem? 1. Create a new review request, publish it. 2. Update the review request, filling the testing done field with over 67000 characters (for instance: "".join(map(str,range(1,16000))) ) 3. Save 4. Review Board reports a 500 error. Traceback (most recent call last): File "/opt/software/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/core/handlers/base.py", line 92, in get_response response = callback(request, *callback_args, **callback_kwargs) File "/opt/software/lib/python2.5/site-packages/ReviewBoard-1.0.5.1-py2.5.egg/reviewboard/accounts/decorators.py", line 25, in _check return login_required(view_func)(*args, **kwargs) File "/opt/software/lib/python2.5/site-packages/Djblets-0.5.5-py2.5.egg/djblets/auth/util.py", line 46, in _checklogin return view_func(request, *args, **kwargs) File "/opt/software/lib/python2.5/site-packages/ReviewBoard-1.0.5.1-py2.5.egg/reviewboard/reviews/views.py", line 188, in review_detail for changedesc in changedescs: File "/opt/software/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/db/models/query.py", line 106, in _result_iter self._fill_cache() File "/opt/software/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/db/models/query.py", line 692, in _fill_cache self._result_cache.append(self._iter.next()) File "/opt/software/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/db/models/query.py", line 251, in iterator obj = self.model(*row[index_start:aggregate_start]) File "/opt/software/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/db/models/base.py", line 324, in __init__ signals.post_init.send(sender=self.__class__, instance=self) File "/opt/software/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/dispatch/dispatcher.py", line 166, in send response = receiver(signal=self, sender=sender, **named) File "/opt/software/lib/python2.5/site-packages/Djblets-0.5.5-py2.5.egg/djblets/util/fields.py", line 174, in post_init value = self.loads(value) File "/opt/software/lib/python2.5/site-packages/Djblets-0.5.5-py2.5.egg/djblets/util/fields.py", line 206, in loads val = eval(val) File "<string>", line 1 {"testing_done": {"new": ["12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814.... 5264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532 ^ SyntaxError: EOL while scanning single-quoted string What is the expected output? What do you see instead? The review should be published. A 500 error is displayed instead. What operating system are you using? What browser? Linux for the server. Firefox/windows for the browser. Please provide any additional information below. The issue is that the fields_changed field in changedescs_changedescription is truncated to 65535 characters as shown below, and the python object is missing the ']}} termination characters to have a well formed string that JSON could parse (I'm using simplejson). mysql> select id, right(fields_changed,100) from changedescs_changedescription where length(fields_changed)>65000 ; +-------+------------------------------------------------------------------------------------------------------+ | id | right(fields_changed,100) | +-------+------------------------------------------------------------------------------------------------------+ | 10043 | 3153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532 | +-------+------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select id, left(fields_changed,100) from changedescs_changedescription where length(fields_changed)>65000 ; +-------+------------------------------------------------------------------------------------------------------+ | id | left(fields_changed,100) | +-------+------------------------------------------------------------------------------------------------------+ | 10043 | {"testing_done": {"new": ["1234567891011121314151617181920212223242526272829303132333435363738394041 | +-------+------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select length(fields_changed) from changedescs_changedescription where length(fields_changed)>65000 ; +------------------------+ | length(fields_changed) | +------------------------+ | 65535 | +------------------------+ 1 row in set (0.00 sec) mysql> select id, right(testing_done, 100) from reviews_reviewrequest where length(testing_done)>65000 ; +------+------------------------------------------------------------------------------------------------------+ | id | right(testing_done, 100) | +------+------------------------------------------------------------------------------------------------------+ | 4246 | 091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815A | +------+------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select id, length(testing_done) from reviews_reviewrequest where length(testing_done)>65000 ; +------+----------------------+ | id | length(testing_done) | +------+----------------------+ | 4246 | 65537 | +------+----------------------+ 1 row in set (0.01 sec) Clearly, it's not very reasonable to have such a large data set, but I think we need to protect from it. As the fields_changed can contain several fields, the problem could be recreated using different combination of old and new fields as well.
I reproduced the issue on the demo server 1.1 alpha 3 (dev), but I'm getting an additional error at submission time. It's a bit better, but the review is still not accessible: http://demo.reviewboard.org/r/3217/ Warning at /api/json/reviewrequests/3217/publish/ Data truncated for column 'fields_changed' at row 1 Request Method: POST Request URL: http://demo.reviewboard.org/api/json/reviewrequests/3217/publish/ Exception Type: Warning Exception Value: Data truncated for column 'fields_changed' at row 1 Exception Location: /usr/lib/python2.5/warnings.py in warn_explicit, line 102 Python Executable: /usr/bin/python Python Version: 2.5.2 Python Path: ['/var/www/demo.reviewboard.org/conf', '/usr/lib/python2.5/site-packages/python_memcached-1.40-py2.5.egg', '/usr/lib/python2.5/site-packages/BuildBatter-0.1-py2.5.egg', '/usr/lib/python2.5/site-packages/virtualenv-1.3-py2.5.egg', '/usr/lib/python2.5/site-packages/django_evolution-0.0.0-py2.5.egg', '/usr/lib/python2.5/site-packages/flup-1.0.1-py2.5.egg', '/usr/lib/python2.5/site-packages/docutils-0.5-py2.5.egg', '/usr/lib/python2.5/site-packages/Jinja2-2.1.1-py2.5-linux-i686.egg', '/usr/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg', '/usr/lib/python2.5/site-packages/JCC-2.1-py2.5-linux-i686.egg', '/usr/lib/python2.5/site-packages/pytz-2009f-py2.5.egg', '/usr/lib/python2.5/site-packages/gitosis-0.2-py2.5.egg', '/usr/lib/python2.5/site-packages/buildbot-0.7.10p1-py2.5.egg', '/usr/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg', '/usr/lib/python2.5/site-packages/Sphinx-0.6.3-py2.5.egg', '/usr/lib/python2.5/site-packages/recaptcha_client-1.0.5-py2.5.egg', '/usr/lib/python2.5/site-packages/paramiko-1.7.6-py2.5.egg', '/usr/lib/python2.5/site-packages/Pygments-1.1.1-py2.5.egg', '/usr/lib/python2.5/site-packages/pycrypto-2.0.1-py2.5-linux-i686.egg', '/usr/lib/python2.5/site-packages/ReviewBoard-1.1alpha3.dev_20100113-py2.5.egg', '/usr/lib/python2.5/site-packages/Djblets-0.5.7alpha0.dev_20100113-py2.5.egg', '/usr/lib/python25.zip', '/usr/lib/python2.5', '/usr/lib/python2.5/plat-linux2', '/usr/lib/python2.5/lib-tk', '/usr/lib/python2.5/lib-dynload', '/usr/local/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages', '/usr/lib/python2.5/site-packages/PIL', '/var/lib/python-support/python2.5'] Server time: Mon, 1 Feb 2010 12:05:04 -0800 Traceback Switch to copy-and-paste view * /usr/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/core/handlers/base.py in get_response 85. # Apply view middleware 86. for middleware_method in self._view_middleware: 87. response = middleware_method(request, callback, callback_args, callback_kwargs) 88. if response: 89. return response 90. 91. try: 92. response = callback(request, *callback_args, **callback_kwargs) ... 93. except Exception, e: 94. # If the view raised an exception, run it through exception 95. # middleware, and if the exception middleware returns a 96. # response, use that. Otherwise, reraise the exception. 97. for middleware_method in self._exception_middleware: 98. response = middleware_method(request, e) ? Local vars Variable Value callback <function review_request_publish at 0x9733a04> callback_args () callback_kwargs {'api_format': u'json', 'review_request_id': u'3217'} e Warning(u"Data truncated for column 'fields_changed' at row 1",) exc_info (<class '_mysql_exceptions.Warning'>, Warning(u"Data truncated for column 'fields_changed' at row 1",), <traceback object at 0xa4f0d24>) exceptions <module 'django.core.exceptions' from '/usr/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/core/exceptions.pyc'> middleware_method <bound method LoggingMiddleware.process_exception of <djblets.log.middleware.LoggingMiddleware object at 0xa16718c>> receivers [(<function _rollback_on_exception at 0x8f59a04>, None)] request <ModPythonRequest path:/api/json/reviewrequests/3217/publish/, GET:<QueryDict: {}>, POST:<QueryDict: {u'dummy': [u'']}>, COOKIES:{'__utma': '78002967.1485541389.1255497952.1264623807.1265052397.42', '__utmb': '78002967.3.10.1265052397', '__utmc': '78002967', '__utmz': '78002967.1264623807.41.24.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=reviewboard%20admin', 'collapsediffs': 'True', 'rbsessionid': '15e22e0f7022de794508d3159bedfbb9'}, META:{'AUTH_TYPE': None, 'CONTENT_LENGTH': '6', 'CONTENT_TYPE': 'application/x-www-form-urlencoded; charset=UTF-8', 'GATEWAY_INTERFACE': 'CGI/1.1', 'HTTP_ACCEPT': 'application/json, text/javascript, */*', 'HTTP_ACCEPT_CHARSET': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'HTTP_ACCEPT_ENCODING': 'gzip,deflate', 'HTTP_ACCEPT_LANGUAGE': 'en-us,en;q=0.5', 'HTTP_CACHE_CONTROL': 'no-cache', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_CONTENT_LENGTH': '6', 'HTTP_CONTENT_TYPE': 'application/x-www-form-urlencoded; charset=UTF-8', 'HTTP_COOKIE': '__utma=78002967.1485541389.1255497952.1264623807.1265052397.42; __utmz=78002967.1264623807.41.24.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=reviewboard%20admin; __utmc=78002967; __utmb=78002967.3.10.1265052397; rbsessionid=15e22e0f7022de794508d3159bedfbb9; collapsediffs=True', 'HTTP_HOST': 'demo.reviewboard.org', 'HTTP_PRAGMA': 'no-cache', 'HTTP_REFERER': 'http://demo.reviewboard.org/r/3217/', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7', 'HTTP_VIA': '1.1 nc-corpse (NetCache NetApp/6.0.3)', 'HTTP_X_FORWARDED_FOR': '10.34.25.33', 'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest', 'PATH_INFO': u'/api/json/reviewrequests/3217/publish/', 'PATH_TRANSLATED': None, 'QUERY_STRING': None, 'REMOTE_ADDR': '198.95.226.224', 'REMOTE_HOST': None, 'REMOTE_IDENT': None, 'REMOTE_USER': None, 'REQUEST_METHOD': 'POST', 'SCRIPT_NAME': '', 'SERVER_NAME': 'demo.reviewboard.org', 'SERVER_PORT': 80, 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'mod_python'}> resolver <RegexURLResolver djblets.util.rooturl (None:None) ^/> response None self <django.core.handlers.modpython.ModPythonHandler object at 0xa21eecc> settings <django.conf.LazySettings object at 0x8d1386c> urlconf 'djblets.util.rooturl' urlresolvers <module 'django.core.urlresolvers' from '/usr/lib/python2.5/site-packages/Django-1.1.1-py2.5.egg/django/core/urlresolvers.pyc'> *
Attaching the complete traceback on submission.
-
+
We've experienced this recently on a couple of reviews. Contemplating changing fields_changed in relation changedescs_changedescription from MySQL 'text' type to 'mediumtext' or 'longtext' but curious what others have done or if there is recommended solution besides telling users not to post so much content in description.
It's a problem of djblets' JSONField. Please remove 'db_type' method from JSONField, and everything goes well, because TextField uses 'longtext' in default. class JSONField(models.TextField): """ A field for storing JSON-encoded data. The data is accessible as standard Python data types and is transparently encoded/decoded to/from a JSON string in the database. """ serialize_to_string = True def __init__(self, verbose_name=None, name=None, encoder=DjangoJSONEncoder(), **kwargs): models.TextField.__init__(self, verbose_name, name, blank=True, **kwargs) self.encoder = encoder - def db_type(self, connection=None): - return "text" Django TextField's mysql type is defined at django.db.backends.mysql.creation Related issue (Django): https://code.djangoproject.com/ticket/489
sorry, diff above is invalid. new one here: diff --git a/djblets/util/fields.py b/djblets/util/fields.py index 33b901b..30671fc 100644 --- a/djblets/util/fields.py +++ b/djblets/util/fields.py @@ -149,8 +149,8 @@ class JSONField(models.TextField): **kwargs) self.encoder = encoder - def db_type(self, connection=None): - return "text" + def get_internal_type(self): + return "TextField" def contribute_to_class(self, cls, name): def get_json(model_instance):
Why is the get_internal_type needed? We should automatically get this from TextField.get_internal_type.
You are right. I misunderstood something. We don't need get_internal_type here. Related changeset: https://code.djangoproject.com/changeset/7133 Sorry for confusing post.
Fixed on Djblets 0.6.10 (a04eae9).