def _replacement_with_reused_rowids(self): replacement = self.account / 'rowids-reused.tmp' db = sqlite3.connect(replacement) try: db.execute('CREATE TABLE message_table(sender_id TEXT,conversation_id TEXT,content_type INTEGER,send_time INTEGER,content BLOB,server_id TEXT,client_id TEXT)') db.executemany('INSERT INTO message_table VALUES(?,?,?,?,?,?,?)', [('other', 'M:999', 2, 900 + i, 'OTHER CONVERSATION PRIVATE BODY', f'other-{i}', '') for i in range(3)]) db.commit() finally: db.close() return replacement def test_database_replaced_between_index_and_message_read_cannot_leak_conversation(self): browser._message_index(self.database) replacement = self._replacement_with_reused_rowids() original = browser._read_message_rows def replace_before_read(*args, **kwargs): os.replace(replacement, self.database) return original(*args, **kwargs) with mock.patch.object(browser, '_read_message_rows', side_effect=replace_before_read): messages = browser._messages(self.database, '100', 'M:200', {}, 12) self.assertEqual(messages, []) refreshed = self.snapshot() self.assertEqual(refreshed['selectedConversation'], 'M:999') def test_database_replaced_between_index_and_preview_read_cannot_leak_conversation(self): browser._message_index(self.database) replacement = self._replacement_with_reused_rowids() original = browser._read_message_rows def replace_before_read(*args, **kwargs): os.replace(replacement, self.database) return original(*args, **kwargs) with mock.patch.object(browser, '_read_message_rows', side_effect=replace_before_read): rows, _, _ = browser._conversation_rows(self.database, '100', {}, {}, '', 8) self.assertTrue(rows) self.assertTrue(all(item['preview'] == '' for item in rows))