From 4594bf6e6db5db0cdbdab260ac0a4dd819571c2d Mon Sep 17 00:00:00 2001
From: Chilja Gossow <49635654+chiljamgossow@users.noreply.github.com>
Date: Fri, 23 Apr 2021 16:28:16 +0200
Subject: [PATCH] Fix RAT qr code invalid payload crash (DEV) (#2915)

* catch exception thrown when json is malformed

* comments

* catch decode exception
---
 .../qrcode/RapidAntigenQrCodeExtractor.kt     | 29 +++++++++++++------
 .../qrcode/CoronaTestQrCodeValidatorTest.kt   | 19 ++++++++----
 .../qrcode/RapidAntigenQrCodeExtractorTest.kt |  8 +++++
 3 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/RapidAntigenQrCodeExtractor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/RapidAntigenQrCodeExtractor.kt
index e05c6a6da..f74aa2d87 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/RapidAntigenQrCodeExtractor.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/RapidAntigenQrCodeExtractor.kt
@@ -40,16 +40,27 @@ class RapidAntigenQrCodeExtractor @Inject constructor() : QrCodeExtractor<Corona
     }
 
     private fun String.decode(): RawPayload {
-        val decoded = if (
-            this.contains("+") ||
-            this.contains("/") ||
-            this.contains("=")
-        ) {
-            BaseEncoding.base64().decode(this)
-        } else {
-            BaseEncoding.base64Url().decode(this)
+        val decoded = try {
+            if (
+                this.contains("+") ||
+                this.contains("/") ||
+                this.contains("=")
+            ) {
+                BaseEncoding.base64().decode(this)
+            } else {
+                BaseEncoding.base64Url().decode(this)
+            }
+        } catch (e: Exception) {
+            Timber.e(e)
+            throw InvalidQRCodeException("Unsupported encoding. Supported encodings are base64 and base64url.")
+        }
+
+        try {
+            return Gson().fromJson(decoded.commonToUtf8String())
+        } catch (e: Exception) {
+            Timber.e(e)
+            throw InvalidQRCodeException("Malformed payload.")
         }
-        return Gson().fromJson(decoded.commonToUtf8String())
     }
 
     private data class RawPayload(
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQrCodeValidatorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQrCodeValidatorTest.kt
index 2d9478b79..f9665d0af 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQrCodeValidatorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQrCodeValidatorTest.kt
@@ -1,6 +1,7 @@
 package de.rki.coronawarnapp.coronatest.qrcode
 
 import de.rki.coronawarnapp.coronatest.type.CoronaTest
+import io.kotest.assertions.throwables.shouldThrow
 import io.kotest.matchers.shouldBe
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
@@ -19,14 +20,20 @@ class CoronaTestQrCodeValidatorTest : BaseTest() {
     }
 
     @Test
-    fun `invalid code throws exception`() {
+    fun `invalid prefix throws exception`() {
         val invalidCode = "HTTPS://somethingelse/?123456-12345678-1234-4DA7-B166-B86D85475064"
         val instance = CoronaTestQrCodeValidator(RapidAntigenQrCodeExtractor(), PcrQrCodeExtractor())
-        return try {
+        shouldThrow<InvalidQRCodeException> {
             instance.validate(invalidCode)
-            false
-        } catch (e: InvalidQRCodeException) {
-            true
-        } shouldBe true
+        }
+    }
+
+    @Test
+    fun `invalid json throws exception`() {
+        val invalidCode = "https://s.coronawarn.app/?v=1#eyJ0aW1lc3RhbXAiOjE2"
+        val instance = CoronaTestQrCodeValidator(RapidAntigenQrCodeExtractor(), PcrQrCodeExtractor())
+        shouldThrow<InvalidQRCodeException> {
+            instance.validate(invalidCode)
+        }
     }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/qrcode/RapidAntigenQrCodeExtractorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/qrcode/RapidAntigenQrCodeExtractorTest.kt
index 459fff1d3..43e945ad8 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/qrcode/RapidAntigenQrCodeExtractorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/qrcode/RapidAntigenQrCodeExtractorTest.kt
@@ -59,4 +59,12 @@ class RapidAntigenQrCodeExtractorTest : BaseTest() {
     fun `personal data is only valid if complete or completely missing`() {
         shouldThrow<InvalidQRCodeException> { instance.extract(raQrIncompletePersonalData) }
     }
+
+    @Test
+    fun `invalid json throws exception`() {
+        val invalidCode = "https://s.coronawarn.app/?v=1#eyJ0aW1lc3RhbXAiOjE2"
+        shouldThrow<InvalidQRCodeException> {
+            RapidAntigenQrCodeExtractor().extract(invalidCode)
+        }
+    }
 }
-- 
GitLab