From a83f0fa73509bef8c18ab6033ea8fc383a205f29 Mon Sep 17 00:00:00 2001 From: HAMZA OZTURK - Mobil Operasyonel Cozumler Mudurlugu Date: Fri, 10 Oct 2025 09:52:48 +0300 Subject: [PATCH 1/2] Enhance `PrivateMessagePacket` encoding and decoding for variable content lengths --- bitchat/Protocols/Packets.swift | 63 ++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/bitchat/Protocols/Packets.swift b/bitchat/Protocols/Packets.swift index 8914d4b7..bc9598be 100644 --- a/bitchat/Protocols/Packets.swift +++ b/bitchat/Protocols/Packets.swift @@ -114,20 +114,19 @@ struct PrivateMessagePacket { } func encode() -> Data? { - var data = Data() - data.reserveCapacity(2 + min(messageID.count, 255) + 2 + min(content.count, 255)) - - // TLV for messageID guard let messageIDData = messageID.data(using: .utf8), messageIDData.count <= 255 else { return nil } + guard let contentData = content.data(using: .utf8), contentData.count <= 65535 else { return nil } + + var data = Data() + let estimatedMessageLength = 1 + 1 + messageIDData.count + let estimatedContentLength = contentData.count > 255 ? 1 + 3 + contentData.count : 1 + 2 + contentData.count + data.reserveCapacity(estimatedMessageLength + estimatedContentLength) + data.append(TLVType.messageID.rawValue) data.append(UInt8(messageIDData.count)) data.append(messageIDData) - // TLV for content - guard let contentData = content.data(using: .utf8), contentData.count <= 255 else { return nil } - data.append(TLVType.content.rawValue) - data.append(UInt8(contentData.count)) - data.append(contentData) + appendContentTLV(value: contentData, into: &data) return data } @@ -141,17 +140,20 @@ struct PrivateMessagePacket { guard let type = TLVType(rawValue: data[offset]) else { return nil } offset += 1 - let length = Int(data[offset]) - offset += 1 - - guard offset + length <= data.count else { return nil } - let value = data[offset.. Int? { + guard offset < data.count else { return nil } + let firstByte = Int(data[offset]) + offset += 1 + + if firstByte < 255 { + return firstByte + } + + guard offset + 2 <= data.count else { return nil } + let high = Int(data[offset]) + let low = Int(data[offset + 1]) + offset += 2 + + let length = (high << 8) | low + return length <= 65535 ? length : nil + } } From cbdc880d074cc7c82bb750525e08fefb579ff6db Mon Sep 17 00:00:00 2001 From: hamzaozturk Date: Fri, 10 Oct 2025 12:29:07 +0300 Subject: [PATCH 2/2] Fix content length estimation in `PrivateMessagePacket` encoding and add unit tests for encoding/decoding --- bitchat/Protocols/Packets.swift | 4 +- .../Protocol/PrivateMessagePacketTests.swift | 40 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 bitchatTests/Protocol/PrivateMessagePacketTests.swift diff --git a/bitchat/Protocols/Packets.swift b/bitchat/Protocols/Packets.swift index bc9598be..4cd72750 100644 --- a/bitchat/Protocols/Packets.swift +++ b/bitchat/Protocols/Packets.swift @@ -119,7 +119,7 @@ struct PrivateMessagePacket { var data = Data() let estimatedMessageLength = 1 + 1 + messageIDData.count - let estimatedContentLength = contentData.count > 255 ? 1 + 3 + contentData.count : 1 + 2 + contentData.count + let estimatedContentLength = contentData.count >= 255 ? 1 + 3 + contentData.count : 1 + 2 + contentData.count data.reserveCapacity(estimatedMessageLength + estimatedContentLength) data.append(TLVType.messageID.rawValue) @@ -164,7 +164,7 @@ struct PrivateMessagePacket { private func appendContentTLV(value: Data, into buffer: inout Data) { buffer.append(TLVType.content.rawValue) - if value.count <= 255 { + if value.count < 255 { buffer.append(UInt8(value.count)) } else { buffer.append(0xFF) diff --git a/bitchatTests/Protocol/PrivateMessagePacketTests.swift b/bitchatTests/Protocol/PrivateMessagePacketTests.swift new file mode 100644 index 00000000..96d37f2e --- /dev/null +++ b/bitchatTests/Protocol/PrivateMessagePacketTests.swift @@ -0,0 +1,40 @@ +import XCTest +@testable import bitchat + +final class PrivateMessagePacketTests: XCTestCase { + func testEncodeDecodeSupportsLargeContent() throws { + let longContent = String(repeating: "A", count: 1024) + let packet = PrivateMessagePacket(messageID: "msg-123", content: longContent) + + let encoded = try XCTUnwrap(packet.encode()) + let decoded = try XCTUnwrap(PrivateMessagePacket.decode(from: encoded)) + + XCTAssertEqual(decoded.messageID, "msg-123") + XCTAssertEqual(decoded.content, longContent) + } + + func testEncodeDecodeContentExactly255Bytes() throws { + let content = String(repeating: "B", count: 255) + let packet = PrivateMessagePacket(messageID: "msg-255", content: content) + + let encoded = try XCTUnwrap(packet.encode()) + let decoded = try XCTUnwrap(PrivateMessagePacket.decode(from: encoded)) + + XCTAssertEqual(decoded.content.count, 255) + XCTAssertEqual(decoded.content, content) + } + + func testEncodeRejectsOversizedContent() { + let oversizedContent = String(repeating: "C", count: 70_000) + let packet = PrivateMessagePacket(messageID: "msg-oversize", content: oversizedContent) + + XCTAssertNil(packet.encode()) + } + + func testEncodeRejectsOversizedMessageID() { + let longID = String(repeating: "x", count: 256) + let packet = PrivateMessagePacket(messageID: longID, content: "ok") + + XCTAssertNil(packet.encode()) + } +}