check_message: Reject null bytes in message content.

Postgres doesn't like them, we don't have an obvious way to escape
them, and they tend to be sent by buggy tools where it'd be better for
the user to get an error.

This fixes a 500 we were getting occasionally.
This commit is contained in:
Tim Abbott 2017-10-02 12:56:30 -07:00
parent 575bd0e255
commit 654562b942
2 changed files with 16 additions and 2 deletions

View File

@ -1553,6 +1553,9 @@ def check_message(sender, client, addressee,
message_content = message_content_raw.rstrip() message_content = message_content_raw.rstrip()
if len(message_content) == 0: if len(message_content) == 0:
raise JsonableError(_("Message must not be empty")) raise JsonableError(_("Message must not be empty"))
if '\x00' in message_content:
raise JsonableError(_("Message must not contain null bytes"))
message_content = truncate_body(message_content) message_content = truncate_body(message_content)
if realm is None: if realm is None:
@ -1652,6 +1655,7 @@ def _internal_prep_message(realm, sender, addressee, content):
messages together as one database query. messages together as one database query.
Call do_send_messages with a list of the return values of this method. Call do_send_messages with a list of the return values of this method.
""" """
# Remove any null bytes from the content
if len(content) > MAX_MESSAGE_LENGTH: if len(content) > MAX_MESSAGE_LENGTH:
content = content[0:3900] + "\n\n[message was too long and has been truncated]" content = content[0:3900] + "\n\n[message was too long and has been truncated]"

View File

@ -1085,11 +1085,21 @@ class MessagePOSTTest(ZulipTestCase):
self.assertEqual(ujson.loads(result1.content)['id'], self.assertEqual(ujson.loads(result1.content)['id'],
ujson.loads(result2.content)['id']) ujson.loads(result2.content)['id'])
def test_message_with_null_bytes(self):
# type: () -> None
"""
A message with null bytes in it is handled.
"""
self.login(self.example_email("hamlet"))
post_data = {"type": "stream", "to": "Verona", "client": "test suite",
"content": u" I like null bytes \x00 in my content", "subject": "Test subject"}
result = self.client_post("/json/messages", post_data)
self.assert_json_error(result, "Message must not contain null bytes")
def test_strip_message(self): def test_strip_message(self):
# type: () -> None # type: () -> None
""" """
Sending a message longer than the maximum message length succeeds but is A message with mixed whitespace at the end is cleaned up.
truncated.
""" """
self.login(self.example_email("hamlet")) self.login(self.example_email("hamlet"))
post_data = {"type": "stream", "to": "Verona", "client": "test suite", post_data = {"type": "stream", "to": "Verona", "client": "test suite",