From 382fc6f05c7ea2a5783891aa924b9e0f27269fb3 Mon Sep 17 00:00:00 2001
From: Benoit Marty <benoitm@matrix.org>
Date: Wed, 19 Feb 2020 18:59:39 +0100
Subject: [PATCH] Fix issue with long transactionId

---
 .../crypto/verification/qrcode/QrCodeTest.kt     | 16 ++++++++++++++++
 .../crypto/verification/qrcode/Extensions.kt     | 13 ++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/qrcode/QrCodeTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/qrcode/QrCodeTest.kt
index 1cbc1a17df..7e835385cc 100644
--- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/qrcode/QrCodeTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/internal/crypto/verification/qrcode/QrCodeTest.kt
@@ -218,6 +218,22 @@ class QrCodeTest : InstrumentedTest {
         compareArray(byteArray.copyOfRange(23 + 64, byteArray.size), sharedSecretByteArray)
     }
 
+    @Test
+    fun testLongTransactionId() {
+        // Size on two bytes (2_000 = 0x07D0)
+        val longTransactionId = "PatternId_".repeat(200)
+
+        val qrCode = qrCode1.copy(transactionId = longTransactionId)
+
+        val result = qrCode.toEncodedString()
+        val expected = value1.replace("\u0000\u000DMaTransaction", "\u0007\u00D0$longTransactionId")
+
+        result shouldEqual expected
+
+        // Reverse operation
+        expected.toQrCodeData() shouldEqual qrCode
+    }
+
     // Error cases
     @Test
     fun testErrorHeader() {
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt
index cc16c2d725..b1da4a228c 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/qrcode/Extensions.kt
@@ -94,7 +94,10 @@ fun String.toQrCodeData(): QrCodeData? {
     cursor++
 
     // Get transaction length
-    val transactionLength = (byteArray[cursor].toInt() shr 8) + byteArray[cursor + 1].toInt()
+    val bigEndian1 = ensurePositive(byteArray[cursor])
+    val bigEndian2 = ensurePositive(byteArray[cursor + 1])
+
+    val transactionLength = bigEndian1 * 0x0100 + bigEndian2
 
     cursor++
     cursor++
@@ -121,3 +124,11 @@ fun String.toQrCodeData(): QrCodeData? {
         else -> null
     }
 }
+
+fun ensurePositive(byte: Byte): Int {
+    return if (byte < 0) {
+        256 + byte
+    } else {
+        byte.toInt()
+    }
+}