近來業界對於「記憶體安全語言在嵌入式領域的價值」有許多討論,特別是在產品的安全性與功能安全層面上。

缺乏記憶體安全性是導致產品出現資安漏洞的主要原因之一,會同時影響產品的功能安全與資安風險。

經過多年來與多個嵌入式團隊合作,親眼見證這些問題在實際專案中的真實樣貌。因此本文將分享 IAR 平台如何透過內建的動態程式碼檢查工具,有效找出 C 和 C++ 程式碼中的記憶體安全問題,讓這些原本不具備記憶體安全的語言變得更安全好用。

記憶體安全一般可分為兩種類型:

  • 空間記憶體安全:是否會進行越界存取,即讀寫了本不應該存取的記憶體位置?
  • 時序記憶體安全:暫時使用的記憶體是否會以不安全的方式影響整體記憶體管理?

在 C 語言中,第一類問題常見於宣告一個固定大小的陣列後,仍然存取其邊界以外的元素,而這在 C 和 C++ 中是語法上允許的。

第二類問題與堆積記憶體(heap)的配置有關,通常透過 malloc() 與 free() 配對使用。若頻繁呼叫 malloc() 而未適當釋放記憶體,容易導致記憶體洩漏,甚至更嚴重的是,超出堆積範圍的存取會覆寫到其他記憶體區段,例如全域變數。

雖然 C++ 在某些情況下提供較多自動化處理,但仍然可以手動配置記憶體,因此也面臨相同風險。

這正是 IAR Embedded Workbench 以及整個 IAR 平台能發揮價值的地方。

IAR 提供一個名為 C-RUN 的動態程式碼檢查工具。

這個工具可偵測多種危險行為,包括陣列越界存取與堆積溢位,能在即時除錯期間協助提升 C/C++ 程式碼的記憶體安全性。

C-RUN 的設定介面可讓開發者在即時除錯階段啟用各種檢查功能,這些功能整合在同一介面中,屬於完整 IAR 平台的一部分。

下圖顯示從專案選項中啟用所有 C-RUN 功能的設定畫面。

從專案選項中啟用所有 C-RUN 功能的設定畫面

畫面中紅框區塊表示 C-RUN 已啟用,並已開啟堆積使用與陣列邊界檢查功能。

這樣的設定可即時檢查 C/C++ 中最常見的兩種記憶體安全問題來源。

此外,C-RUN 也能檢查數學運算錯誤(設定介面右側),雖然這對驗證程式碼完整性也有幫助,但本篇不著墨於此。

當在 IAR C-SPY 除錯器中執行時,C-RUN 標記過的程式碼可在記憶體洩漏或陣列越界存取真正執行前攔截下來,避免對系統行為造成影響。

範例:陣列越界存取

例如,程式建立一個含有 100 個元素的陣列,每個元素預設值為其索引值。

這時,終端輸入視窗要求使用者輸入小於 100 的數字作為陣列索引。

若使用者輸入 102,程式就會嘗試越界存取陣列。

此時除錯器會在執行該行程式碼之前中斷,並於 C-RUN 訊息視窗中顯示詳細錯誤資訊。

此時除錯器會在執行該行程式碼之前中斷,並於 C-RUN 訊息視窗中顯示詳細錯誤資訊。

具體來說,除錯器會在即將執行越界操作的那一行程式碼停止,也就是試圖存取索引為 102 的陣列元素,而該陣列實際上只包含索引 0 到 99 的元素。

在 C-RUN 訊息視窗中,錯誤訊息會明確指出問題發生於 main.c 第 21 行,並回溯指出陣列是在第 8 行宣告的。

在 C-RUN 訊息視窗中,錯誤訊息會明確指出問題發生於 main.c 第 21 行,並回溯指出陣列是在第 8 行宣告的

如果程式繼續執行而未中止,系統可能不會立刻當機,但該陣列索引 102 所回傳的值將是 134229899,一個顯然無效的數值。

如果程式繼續執行而未中止,系統可能不會立刻當機,但該陣列索引 102 所回傳的值將是 134229899,一個顯然無效的數值。

此外,C-RUN 也會回報堆積記憶體的配置狀況。例如,若堆積空間設為 0x2000 位元組,而程式在迴圈中每次呼叫 malloc() 配置 0x800 位元組,那麼在總計配置了 6228 位元組之後,C-RUN 會攔截第 4 次 malloc() 呼叫,避免堆積溢位。

這樣的機制可避免某個記憶體區塊回傳指向非堆積區域的指標,進而導致不安全的存取行為。

雖然使用 C-RUN 進行即時除錯在開發階段能有效捕捉錯誤,但現今節奏快速的嵌入式專案還需要更多自動化支援。

團隊不再只處理單一產品版本或測試環境,而是要同時管理多種軟體版本、硬體配置與發表分支,且時程緊迫。

這正是自動化變得不可或缺的時機點。

人工在每次建置與每個目標上檢查記憶體安全性已無法擴展。為了符合持續交付的需求,團隊必須將記憶體安全性檢查自動化,納入 CI/CD 工作流程,而這正是 C-RUN 發揮完整潛能的地方。

現代嵌入式開發早已不再只是人工除錯。為了跟上快速的發表節奏並在大規模下維持產品品質,團隊需要自動化,而 C-RUN 正是為此而設計。

C-RUN 可在 IAR C-SPY 除錯器的批次模式下執行,無縫整合至自動化測試流程中。

這讓你可以:

  • 在不同建置中自動套用預先定義的規則與設定
  • 將輸出結果導向日誌檔或外部報告工具,以利集中管理與追蹤
  • 將記憶體安全性檢查直接納入持續整合(CI)流程中
C-RUN 可在 IAR C-SPY 除錯器的批次模式下執行,無縫整合至自動化測試流程中。

透過此設計,C-RUN 支援可擴展的測試流程,確保每一次軟體變更,不論版本或配置為何,在進入量產前都能通過記憶體安全檢查。

本文示範了 IAR 平台中的 C-RUN 動態程式碼檢查工具,如何有效移除 C/C++ 程式碼中的不安全記憶體操作。

透過這種整合式解法,團隊就不必因記憶體安全問題而改用其他語言,避免產生額外挑戰或打斷既有的開發流程。

十多年來,C-RUN 一直是 IAR 工具鏈的一部分,是協助團隊在熟悉的 C/C++ 開發環境下,撰寫記憶體安全程式碼的成熟且可靠工具。

對嵌入式開發者來說,重點不只是擁有個別工具,而是擁有一個完整的平台,從開發工作站一路延伸到自動化 CI/CD 流程,在整體開發流程中全面提升安全性、資安與程式品質。

如果像是緩衝區溢位或堆積誤用等記憶體問題正在拖慢您的開發進度,甚至導致安全或資安風險,您並不孤單,而且無需更換開發語言就能解決這些問題。

若想實際看看如何運作,歡迎觀看IAR的隨選網路研討會《沒有 DevOps 團隊也能生存:嵌入式團隊的 CI/CD、除錯與容器應用》,了解即時檢查、自動化與現代化開發流程如何幫助小型團隊交付更安全的嵌入式軟體。

或者您正在找尋可擴展的 DevSecOps 方法,歡迎參考《打破 CI/CD 瓶頸:透過容器與自動化擴展嵌入式 DevSecOps》,了解如直何將 C-RUN 整合到你的自動化測試流程中。

本文由IAR提供

延伸閱讀⎟