mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-08-08 06:56:10 +00:00
test: pin that unknown file TLVs are skipped, not fatal (#1550)
`BitchatFilePacket.decode` skips tags it does not recognise (`case nil: continue`), which is what keeps the TLV list a floor rather than a ceiling: a field the sender considered optional costs the receiver that field, not the whole file. Nothing pinned it. The behaviour is load-bearing for any peer, version or third-party client that adds a field this build has not seen, and it is also where the two implementations diverge — the Android decoder returns null on an unknown tag, which is why `PrivateMediaMessageIdentity` has to derive its receipt key from fields already on the wire instead of adding one. Worth a test on the side that gets it right so it cannot quietly drift into the strict behaviour. Two cases, both hand-built so they do not depend on our own encoder: an unknown TLV between MIME_TYPE and CONTENT (where an encoder appending content last would put it), and one trailing CONTENT. Changing `case nil: continue` to `return nil` fails both. Co-authored-by: jack <212554440+jackjackbits@users.noreply.github.com>
This commit is contained in:
parent
7b39d72bec
commit
59a9f628df
@ -75,6 +75,70 @@ final class BitchatFilePacketTests: XCTestCase {
|
||||
XCTAssertEqual(decoded.content, content)
|
||||
}
|
||||
|
||||
/// The TLV tag list is a floor, not a ceiling: a decoder that bails on the
|
||||
/// first tag it does not know makes the format unextendable, because a field
|
||||
/// the sender considered optional costs the receiver the whole file. This
|
||||
/// decoder skips them (`case nil: continue`) and that has to stay true — it
|
||||
/// is load-bearing for any peer, version or third-party client that adds a
|
||||
/// field we have not seen. `PrivateMediaMessageIdentity` exists precisely
|
||||
/// because the Android decoder does *not* do this, so the asymmetry is real
|
||||
/// and worth pinning on the side that gets it right.
|
||||
func testDecodeSkipsUnknownTLVTypesInsteadOfDroppingTheFile() throws {
|
||||
let content = Data((0..<64).map { UInt8($0) })
|
||||
let unknownValue = Data("some-message-id".utf8)
|
||||
var data = Data()
|
||||
|
||||
// fileName
|
||||
data.append(0x01)
|
||||
data.append(contentsOf: [0x00, 0x09])
|
||||
data.append(Data("photo.jpg".utf8))
|
||||
// fileSize
|
||||
data.append(0x02)
|
||||
data.append(contentsOf: [0x00, 0x04])
|
||||
data.append(contentsOf: [0x00, 0x00, 0x00, UInt8(content.count)])
|
||||
// mimeType
|
||||
data.append(0x03)
|
||||
data.append(contentsOf: [0x00, 0x0A])
|
||||
data.append(Data("image/jpeg".utf8))
|
||||
// An unknown tag, where an encoder appending content last would put it
|
||||
data.append(0x05)
|
||||
data.append(contentsOf: [0x00, UInt8(unknownValue.count)])
|
||||
data.append(unknownValue)
|
||||
// content
|
||||
data.append(0x04)
|
||||
data.append(contentsOf: [0x00, 0x00, 0x00, UInt8(content.count)])
|
||||
data.append(content)
|
||||
|
||||
let decoded = try XCTUnwrap(BitchatFilePacket.decode(data))
|
||||
XCTAssertEqual(decoded.fileName, "photo.jpg")
|
||||
XCTAssertEqual(decoded.mimeType, "image/jpeg")
|
||||
XCTAssertEqual(decoded.fileSize, UInt64(content.count))
|
||||
XCTAssertEqual(decoded.content, content)
|
||||
}
|
||||
|
||||
/// Same contract for an extension that trails the content, which a decoder
|
||||
/// stopping at the first unknown tag would also lose.
|
||||
func testDecodeSkipsAnUnknownTLVTrailingTheContent() throws {
|
||||
let content = Data(repeating: 0x7F, count: 16)
|
||||
var data = Data()
|
||||
|
||||
data.append(0x01)
|
||||
data.append(contentsOf: [0x00, 0x08])
|
||||
data.append(Data("note.m4a".utf8))
|
||||
data.append(0x04)
|
||||
data.append(contentsOf: [0x00, 0x00, 0x00, UInt8(content.count)])
|
||||
data.append(content)
|
||||
data.append(0x7F)
|
||||
data.append(contentsOf: [0x00, 0x04])
|
||||
data.append(Data([0x11, 0x11, 0x11, 0x11]))
|
||||
|
||||
let decoded = try XCTUnwrap(BitchatFilePacket.decode(data))
|
||||
XCTAssertEqual(decoded.fileName, "note.m4a")
|
||||
XCTAssertNil(decoded.mimeType)
|
||||
XCTAssertEqual(decoded.fileSize, UInt64(content.count))
|
||||
XCTAssertEqual(decoded.content, content)
|
||||
}
|
||||
|
||||
func testPrivateMediaMessageIdentityConvergesAcrossPeerIDAliases() throws {
|
||||
let senderKey = Data(repeating: 0x11, count: 32)
|
||||
let recipientKey = Data(repeating: 0x22, count: 32)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user