RFC-0149:FIDL 編碼驗證並非必要 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 不再需要在 FIDL 編碼期間進行驗證。不過,驗證仍會在解碼期間進行,且填充值在編碼期間必須設為零。 |
Gerrit 變更 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2021-11-19 |
審查日期 (年-月-日) | 2022-01-22 |
摘要
不再需要在 FIDL 編碼期間進行驗證。不過,驗證仍會在解碼期間進行,且填充資料在編碼期間必須設為零。
提振精神
這項 RFC 的動機在於放寬設計限制,目前規定繫結必須在編碼期間驗證。這並不表示繫結一定會變更行為,只是表示繫結的限制較少。事實上,在大多數情況下,這些項目不太可能因本 RFC 而有所變更。
不過,我們不再強制要求在編碼期間進行驗證,原因如下:
在編碼期間,驗證會產生額外的額外負載。舉例來說,如果結構體中包含需要驗證的列舉欄位,就無法使用許多繫結中的
memcpy
,因為結構體編碼有快速路徑,可將其縮減為memcpy
。對於 HLCPP 繫結而言,效能影響特別顯著,因為這會兩次檢查要編碼的物件,一次是進行編碼,另一次是進行驗證 (不過,這可以透過重新設計繫結來避免)。程式碼大小:驗證邏輯會增加程式碼大小。對於產生程式碼或使用巨集的繫結,這個程式碼大小增加幅度最為顯著,因為驗證邏輯會在輸出內容中重複多次。
相關人員
導師:pascallouis
審查者:pascallouis、yifeit、mkember
諮詢:
azaslavsky
社會化:
本 RFC 已在 FEC 討論郵寄清單上發布。
設計
繫結可能會在編碼期間驗證 FIDL 物件,也可能不會。更精確地說,系統不再要求以保證物件在解碼期間一律通過驗證的方式進行編碼。
繫結項目必須確保填充位元組在編碼後會歸零。不過,編碼器本身不必將填充值設為零,例如,可透過程式設計語言的保證將其設為零。
繫結必須在解碼期間驗證 FIDL 物件。
實作
這個 RFC 沒有立即可交付的成果,因為目前的繫結會驗證 FIDL 物件,且可能會繼續這樣做。不過,日後的繫結將可放寬驗證檢查。
成效
效能效果取決於使用情境和綁定方式。以下列舉驗證對效能造成的部分影響:
在 Rust 中,如果結構體包含 15 個 uint8 和 1 個布林值,在進行布林值驗證時,編碼速度會比不驗證時慢 3.2 倍 (52 毫秒)。如果結構體包含 254 個 uint8 和 1 個布林值,速度會變慢 21 倍 (844 毫秒)。不過,在 LLCPP 中,相同結構的效能成本微乎其微。我們選擇這個測試案例,是因為在許多繫結中,結構體、陣列或向量主體中的單一布林值或枚舉會防止
memcpy
最佳化。在 LLCPP 中,256 個列舉的陣列編碼速度比 Rust 慢 2.2 倍 (2.6us),在 Rust 中比 Go 慢 1.2 倍 (192ns),在 Go 中比 Go 慢 9 倍 (1.1us)。
驗證後,HLCPP 物件的編碼速度會變慢 1 到 5 倍。16 個元素的表格編碼速度比 400ns 慢 1.7 倍,而訊息標頭的編碼速度則比 37ns 慢 1.3 倍。
這些測量值來自搭載 Intel Core i5-7300U CPU @ 2.60GHz 的機器。請注意,這些是微型基準測試,實際效能可能有所不同。
用於這些基準測試的 CL:
人體工學
這應該不會影響繫結的人體工學。不過,如果繫結在編碼期間停用驗證功能,則在某些可能影響使用者的失敗模式下,就不會再「快速失敗」。
回溯相容性
這項變更不會影響回溯相容性。
安全性考量
填充位元組一向會歸零而非驗證,未來也會繼續歸零。這一點很重要,因為 FIDL 物件可在舊的配置上分配,如果記憶體複製到線路上,就會導致記憶體外洩。對於大多數其他類型的驗證,資料外洩的風險較低。
系統會執行兩種主要驗證類別。
值限制
布林值、列舉、位元:驗證可確保這些類型的支援整數位於預期範圍內。
浮點 - 浮點驗證目前並非規格規定的一部分,但繫結可能仍會執行一些驗證,特別是為了避免 NaN 值。
UTF-8:FIDL 字串是載荷中含有 UTF-8 資料的向量。驗證可確保這些字串為 UTF-8。
這類型別的欄位通常是由使用者透過繫結 API 指派。驗證可確保使用者透過 API 提供有效的輸入內容,且不會有其他形式的意外錯誤 (例如記憶體毀損) 變更值。請注意,記憶體毀損錯誤可能會發生在處理物件的任何階段,因此期待透過布林值驗證等方式偵測到這類錯誤,有點不切實際。
- 大小限制:某些物件 (例如表格) 的大小有限制。
傳輸程序必須遵守特定大小限制,例如管道傳輸的 64k
訊息大小限制,以免訊息大小無限擴大。因此,一般來說,這並非在到達解碼器前需要立即處理的問題。
州/省錯誤
非選填類型視為選填 - 基本上是缺少酬載的非選填類型。
信封內嵌位元組:信封含有欄位,可指出是否應將資料內嵌儲存。封套的大小可能小於或等於 4 個位元組,且應內嵌儲存,但缺少內嵌位元標記。
向量不存在,但計數非零:編碼期間不應發生這種情況。
在遇到解碼器之前,這些都不會造成重大負面影響。這些問題也可能為 FIDL 實作中的內部問題,可透過其他方式保證其正確性。
結語
雖然需要考量安全性疑慮,但一般來說,這些問題通常會在解碼端而非編碼端發生,因為解碼端發生資訊外洩的風險較低。
隱私權注意事項
不會影響隱私權。
測試
這項 RFC 通常會降低測試需求。
說明文件
因此,我們需要更新 FIDL 繫結規格。
缺點、替代方案和未知事項
限制越多,彈性就越低。就驗證而言,更多限制可帶來相對的安全性優勢,而彈性則可改善效能和程式碼大小。這份 RFC 指出,安全性效益並不明顯,因此 FIDL 應考慮移除這項規定。
移除這項規定後,繫結會提供保留或移除現有編碼端驗證的選項。實際上,繫結應盡可能移除這項驗證,但某些繫結可能會繼續在偵錯模式中進行驗證,以便提早找出問題。
既有技術與參考資料
無