From 8af6be402eba48a02853bebc5f9f6d5b9e8844f3 Mon Sep 17 00:00:00 2001
From: Serhii Kostiuk <serhii.o.kostiuk@globallogic.com>
Date: Thu, 23 Jul 2020 15:37:29 +0300
Subject: Quectel Delta Radio Firmware Upgrade support - libmts-io
 implementation

Added more strict handling for comma-separated data in URC messages to prevent out-of-bounds reads.
---
 src/MTS_IO_QuectelRadio.cpp | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

(limited to 'src')

diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp
index 39c0601..59170fe 100644
--- a/src/MTS_IO_QuectelRadio.cpp
+++ b/src/MTS_IO_QuectelRadio.cpp
@@ -1016,11 +1016,12 @@ ICellularRadio::CODE QuectelRadio::fumoWaitUpgradeFinished(ICellularRadio::Updat
         }
 
         const auto vParts = MTS::Text::split(MTS::Text::trim(sResponse), ',', 3);
-        const std::string& sStage = vParts[1];
+        const std::string& sStage = getByIndex(vParts, 1, "NOT_DEFINED");
+
         if (sStage == sFotaUrcEnd) {
             // FOTA finished
             printTrace("Got FOTA END message");
-            const std::string& sCode = vParts[2];
+            const std::string& sCode = getByIndex(vParts, 2, "-1");
 
             if (sCode == "0") {
                 // finished successfully
@@ -1034,11 +1035,11 @@ ICellularRadio::CODE QuectelRadio::fumoWaitUpgradeFinished(ICellularRadio::Updat
             printTrace("Got FOTA START message");
         } else if (sStage == sFotaUrcProgress) {
             printTrace("Got FOTA progress message");
-            const std::string& sPercents = vParts[2];
+            const std::string& sPercents = getByIndex(vParts, 2, "0");
             printInfo("FOTA progress: [%s]", sPercents.c_str());
             callNextStep(stepCb, "FUMO Info: firmware apply progress " + sPercents);
         } else {
-            printInfo("FOTA unexpected URC code: [%s]", sStage.c_str());
+            printInfo("FOTA unexpected URC code: [%s]", sResponse.c_str());
         }
     }
 
-- 
cgit v1.2.3


From cb4e2bf0e1902ef91fe10fe6e6aa9c91e04d7c90 Mon Sep 17 00:00:00 2001
From: Serhii Kostiuk <serhii.o.kostiuk@globallogic.com>
Date: Thu, 23 Jul 2020 16:03:09 +0300
Subject: Quectel Delta Radio Firmware Upgrade support - libmts-io
 implementation

During testing it was discovered that rarely CellularRadio::sendCommand implementation
returns not one line with URC output but multiple lines.

It happened once during testing and development. But is likely to happen again under
increased CPU load and/or when CPU does not keep pace with the serial data flow.
---
 src/MTS_IO_QuectelRadio.cpp | 68 ++++++++++++++++++++++++++++++---------------
 1 file changed, 46 insertions(+), 22 deletions(-)

(limited to 'src')

diff --git a/src/MTS_IO_QuectelRadio.cpp b/src/MTS_IO_QuectelRadio.cpp
index 59170fe..8656973 100644
--- a/src/MTS_IO_QuectelRadio.cpp
+++ b/src/MTS_IO_QuectelRadio.cpp
@@ -1001,10 +1001,11 @@ ICellularRadio::CODE QuectelRadio::fumoWaitUpgradeFinished(ICellularRadio::Updat
     const std::string sFotaUrcEnd = "\"END\"";
     const std::vector<std::string> vFotaBailStrings{ sFotaUrcPrefix };
 
+    bool bFinished = false;
     CODE rc = FAILURE;
     std::string sResponse;
 
-    while (true) {  // breaks on "FOTA","END"
+    while (!bFinished) {  // breaks on "FOTA","END"
         sResponse = sendCommand("", vFotaBailStrings, duUrcTimeout, 0x00);
         printTrace("Radio response: [%s]", sResponse.c_str());
 
@@ -1015,31 +1016,54 @@ ICellularRadio::CODE QuectelRadio::fumoWaitUpgradeFinished(ICellularRadio::Updat
             break;
         }
 
-        const auto vParts = MTS::Text::split(MTS::Text::trim(sResponse), ',', 3);
-        const std::string& sStage = getByIndex(vParts, 1, "NOT_DEFINED");
+        // Occasionally sendCommand returns multiple lines in one chunk.
+        // Handle each line separately for such cases.
+        const auto vLines = MTS::Text::split(sResponse, '\r');
 
-        if (sStage == sFotaUrcEnd) {
-            // FOTA finished
-            printTrace("Got FOTA END message");
-            const std::string& sCode = getByIndex(vParts, 2, "-1");
+        for (const auto& sLine : vLines) {
+            const auto& sTrimmedLine = MTS::Text::trim(sLine);
 
-            if (sCode == "0") {
-                // finished successfully
-                rc = SUCCESS;
+            if (sTrimmedLine.empty()) {
+                // whitespace characters only, ignore
+                continue;
+            }
+
+            printTrace("Processing line: [%s]", sTrimmedLine.c_str());
+
+            if (sTrimmedLine.find(sFotaUrcPrefix) == std::string::npos) {
+                printDebug("URC message not found, line skipped");
+                continue;
+            }
+
+            const auto vParts = MTS::Text::split(sTrimmedLine, ',', 3);
+            const std::string& sStage = getByIndex(vParts, 1, "NOT_DEFINED");
+
+            if (sStage == sFotaUrcEnd) {
+                // FOTA finished
+                printTrace("Got FOTA END message");
+                const std::string& sCode = getByIndex(vParts, 2, "-1");
+
+                if (sCode == "0") {
+                    // finished successfully
+                    rc = SUCCESS;
+                    bFinished = true;
+                    break;
+                }
+
+                // attempt failed, the radio attempts to recover
+                callNextStep(stepCb, "FUMO Error: radio returned error code " + sCode);
+                bFinished = true;
                 break;
+            } else if (sStage == sFotaUrcStart) {
+                printTrace("Got FOTA START message");
+            } else if (sStage == sFotaUrcProgress) {
+                printTrace("Got FOTA progress message");
+                const std::string& sPercents = getByIndex(vParts, 2, "0");
+                printInfo("FOTA progress: [%s]", sPercents.c_str());
+                callNextStep(stepCb, "FUMO Info: firmware apply progress " + sPercents);
+            } else {
+                printInfo("FOTA unexpected URC code: [%s]", sLine.c_str());
             }
-            // attempt failed, the radio attempts to recover
-            callNextStep(stepCb, "FUMO Error: radio returned error code " + sCode);
-            break;
-        } else if (sStage == sFotaUrcStart) {
-            printTrace("Got FOTA START message");
-        } else if (sStage == sFotaUrcProgress) {
-            printTrace("Got FOTA progress message");
-            const std::string& sPercents = getByIndex(vParts, 2, "0");
-            printInfo("FOTA progress: [%s]", sPercents.c_str());
-            callNextStep(stepCb, "FUMO Info: firmware apply progress " + sPercents);
-        } else {
-            printInfo("FOTA unexpected URC code: [%s]", sResponse.c_str());
         }
     }
 
-- 
cgit v1.2.3