diff --git a/zerver/lib/actions.py b/zerver/lib/actions.py index 4d136285d2..10600bd265 100644 --- a/zerver/lib/actions.py +++ b/zerver/lib/actions.py @@ -1553,6 +1553,9 @@ def check_message(sender, client, addressee, message_content = message_content_raw.rstrip() if len(message_content) == 0: 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) if realm is None: @@ -1652,6 +1655,7 @@ def _internal_prep_message(realm, sender, addressee, content): messages together as one database query. 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: content = content[0:3900] + "\n\n[message was too long and has been truncated]" diff --git a/zerver/tests/test_messages.py b/zerver/tests/test_messages.py index c085816918..62551d479a 100644 --- a/zerver/tests/test_messages.py +++ b/zerver/tests/test_messages.py @@ -1085,11 +1085,21 @@ class MessagePOSTTest(ZulipTestCase): self.assertEqual(ujson.loads(result1.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): # type: () -> None """ - Sending a message longer than the maximum message length succeeds but is - truncated. + A message with mixed whitespace at the end is cleaned up. """ self.login(self.example_email("hamlet")) post_data = {"type": "stream", "to": "Verona", "client": "test suite",