簡體   English   中英

strtok_s 和編譯器 C11 向前兼容

[英]strtok_s and compilers C11 onward compliance

C11 中strtok_s的聲明及其用法看起來與編譯器中的strtok_s非常不同,例如與 Visual Studio 2022 (17.4.4) 捆綁在一起的最新版本以及 GCC 12.2.0(查看 MinGW64 發行版)。

我擔心這種不同的形式早在 C11 之前就已被開發為strtok的更安全且被接受的替代品。 如果有人想使用strtok_s並保持 C11 兼容,現在會發生什么?

編譯器提供的庫是否符合 C11 標准?

也許只是我被一些明顯的事情所愚弄,有人可以幫助我......


這是 C11(類似於 C17 和 C23 的早期草稿):

char *strtok_s(char * restrict s1,
    rsize_t * restrict s1max,
    const char * restrict s2,
    char ** restrict ptr);

同樣可以在safec 庫中找到很好的參考

雖然MSC/VC和 GCC 具有以下形式

char* strtok_s(
    char* str,
    const char* delimiters,
    char** context
);

C11“附件 K 邊界檢查接口”受到了很多質疑,實際上幾乎沒有標准庫實現它。 請參閱附件 K 的現場經驗示例 - 邊界檢查接口

至於 MSVC 編譯器,它不符合任何 C 標准,也從未做出這樣的聲明 - 你可以試試這個來檢查你是否使用這樣的編譯器:

#if !defined(__STDC__) || (__STDC__==0)
  #error This compiler is non-conforming.
#endif

特別是,MSVC 也沒有實現 Annex K,但在 C11 之前已經有了非標准庫擴展。

在實踐中_s意味着:

  • 可能更安全也可能更不安全,這取決於使用情況和程序員的預期。
  • 不可攜帶。
  • 可能不符合要求。

如果可移植性和標准一致性很重要,那么請避免使用_s函數。

在實踐中, _s函數可以防止兩件事:傳遞未凈化的輸入或 null 指針。 因此,假設您進行了適當的輸入清理並且沒有將 null 指針傳遞給庫函數,那么_s函數不會給您額外的安全性,只會帶來額外的執行膨脹和可移植性問題。

如果有人想使用strtok_s並保持 C11 兼容,現在會發生什么?

事實上不能

而且它不僅限於strtok_s() 整個 C11 Annex K 實現集是支離破碎的,因為與標准的主要偏差來自 Microsoft 的實現,可能永遠沒有辦法使用 Annex K 函數編寫可移植的、符合標准的代碼。

根據N1967 附件 K 的現場經驗 - 邊界檢查接口

可用的實現

盡管 API 的規范已經存在了十多年,但只有少數實現具有不同程度的完整性和一致性。 以下是對已知存在的實施及其狀態的調查。

雖然下面的兩個實現以可移植源代碼形式作為開源項目提供,但沒有一個流行的開源發行版(如 BSD 或 Linux)選擇將其中一個提供給他們的用戶。 至少有一個(GNU C 庫)一再拒絕包含的提議,原因與奧斯汀集團在他們對 TR 24731-1 N1106 的初步審查中指出的一些相同的原因。 這些發行版的未來版本似乎不太可能提供這些 API。

微軟視覺工作室

Microsoft Visual Studio 實現了早期版本的 API。 但是,該實現並不完整,既不符合 C11 也不符合原始 TR 24731-1。 例如,它不提供set_constraint_handler_s function 而是定義一個_invalid_parameter_handler _set_invalid_parameter_handler(_invalid_parameter_handler) function 具有類似的行為,但簽名略有不同且不兼容。 它還沒有定義abort_handler_signore_handler_s函數、 memset_s function(它不是 TR 的一部分)或RSIZE_MAX宏。 Microsoft 實現也不將重疊的源序列和目標序列視為運行時約束違規,而是在這種情況下具有未定義的行為。

由於與規范存在大量偏差,Microsoft 實施不能被視為符合規范或可移植。

...

保險箱 C 圖書館

Safe C 庫 [SafeC] 是一個相當高效和可移植但不幸的是非常不完整的 Annex K 實現,它支持<string.h>中聲明的函數的字符串操作子集。

由於它不支持<string.h>函數之外的 Annex K 設施,安全 C 庫不能被視為符合要求的實現。

甚至 Safe C 庫也不符合要求。

這些功能是否“更安全”值得商榷。 閱讀整個文檔。

不必要的使用

微軟為了提高 API 的采用率而棄用標准函數而產生的一個普遍謬論是,對標准函數的每次調用都必然是不安全的,應該用“更安全”的 API 來代替。因此,安全有思想的團隊有時會天真地開始長達數月的項目,重寫他們的工作代碼,並盡職盡責地用相應的 API 替換所有“已棄用”函數的實例。 這不僅會導致不必要的改動並增加將新錯誤注入正確代碼的風險,還會降低重寫代碼的效率。

此外,請閱讀更新后的N1969 更新現場經驗與附件 K — 邊界檢查接口

盡管自最初提議以來已有十多年,自 ISO/IEC TR 24731-1:2007 獲得批准已近十年,自將邊界檢查接口引入 C 標准已近五年,但仍未出現可行的合規實現. API 繼續存在爭議,實施請求繼續被實施者拒絕。

邊界檢查接口的設計雖然用心良苦,但存在太多問題需要糾正。 與依賴既定方法或現代技術相比,使用 API 已被認為會導致質量更差、安全性更低的軟件 更有效和侵入性更小的方法已變得司空見慣,並且通常受到用戶和安全專家的青睞。

因此,我們建議將 Annex K 從 C 標准的下一次修訂中刪除,或者棄用后再刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM