Fix decompression size limit to support max-sized file transfers

Root cause: BinaryProtocol.decode() was rejecting decompressed payloads
larger than maxPayloadBytes (1 MB), but TLV-encoded file transfers are
slightly larger due to metadata overhead.

Fixes:
- Changed decompression limit from maxPayloadBytes to maxFramedFileBytes
- This accounts for TLV overhead (~50 bytes) + binary protocol headers
- Now allows ~1.12 MB decompressed payloads (1 MB + overhead budget)

The failing test was:
- Creating 1 MB file content
- TLV encoding adds ~50 bytes (1,048,627 total)
- Compression reduces to ~1,084 bytes (highly repetitive data)
- During decode, decompression was rejecting the 1,048,627 byte output
- Now correctly allows it since 1,048,627 < 1,179,760 (maxFramedFileBytes)

All 154 tests now pass including 'Max-sized file transfer survives reassembly'
This commit is contained in:
jack
2025-10-18 14:47:43 +02:00
parent 7ca1ff0a7e
commit 1cf8449e22
2 changed files with 8 additions and 6 deletions
+2 -1
View File
@@ -333,7 +333,8 @@ struct BinaryProtocol {
originalSize = Int(rawSize)
}
// Guard to keep decompression bounded to sane BLE payload limits
guard originalSize >= 0 && originalSize <= FileTransferLimits.maxPayloadBytes else { return nil }
// Use maxFramedFileBytes to account for TLV overhead in file transfer payloads
guard originalSize >= 0 && originalSize <= FileTransferLimits.maxFramedFileBytes else { return nil }
let compressedSize = payloadLength - lengthFieldBytes
guard compressedSize >= 0, let compressed = readData(compressedSize) else { return nil }
+6 -5
View File
@@ -3395,7 +3395,7 @@ extension BLEService {
if peerID == myPeerID {
return
}
// Minimum header: 8 bytes ID + 2 index + 2 total + 1 type
guard packet.payload.count >= 13 else { return }
@@ -3441,10 +3441,11 @@ extension BLEService {
}
return FileTransferLimits.maxPayloadBytes
}()
guard currentSize + fragmentData.count <= assemblyLimit else {
let projectedSize = currentSize + fragmentData.count
guard projectedSize <= assemblyLimit else {
// Exceeds size limit - evict this assembly
SecureLogger.warning(
"🚫 Fragment assembly exceeds size limit (\(currentSize + fragmentData.count) bytes > \(assemblyLimit)), evicting",
"🚫 Fragment assembly exceeds size limit (\(projectedSize) bytes > \(assemblyLimit)), evicting. Type=\(originalType) Index=\(index)/\(total)",
category: .security
)
incomingFragments.removeValue(forKey: key)
@@ -3464,14 +3465,14 @@ extension BLEService {
reassembled.append(fragment)
}
}
// Decode the original packet bytes we reassembled, so flags/compression are preserved
if let originalPacket = BinaryProtocol.decode(reassembled) {
handleReceivedPacket(originalPacket, from: peerID)
} else {
SecureLogger.error("❌ Failed to decode reassembled packet (type=\(originalType), total=\(total))", category: .session)
}
// Cleanup
incomingFragments.removeValue(forKey: key)
fragmentMetadata.removeValue(forKey: key)