linux 使用不安全的sprintf函式,儲存字元越界導致程式莫名崩潰問題

weixin_34037977發表於2017-10-09

linux c++程式設計

問題背景

在處理一個公共模組的程式碼中,其中有以下程式碼片段

1 //程式碼片段-組合一組字串並存放到szSignKey陣列中
2 char szSignKey[256] = {0};                                                                                                                                                                                                      sprintf(szSignKey, "userid&%u&version&%s&msg_body&%s&%s", uiUserID, strVersion.c_str(), strMsgBody.c_str(), SIGN_KEY);
strMsgBody是一組json格式的字串,裡面會根據協議請求傳入不同資料的json格式字串。
當strMsgBody請求的字串過大,導致要存入szSignKey陣列中的字串超過255個時,會導致字元陣列越界,超出的字元會在陣列後面的記憶體空間中儲存。
但是這個問題不會馬上暴露出來,printf szSignKey的時候,還是會輸出完整的越界字串陣列。但是在函式執行完return後,解構函式內的區域性變數的時候導致程式崩潰。
使用gdb除錯的時候,顯示的也是一些其他臨時物件析構導致崩潰,無法找到真正的崩潰原因。

問題原因:
sprintf函式是不安全的c 字元處理函式,它在寫字串到字元陣列時不會考慮字元陣列的大小,當要儲存的字元超過陣列長度時,會把超出的字元寫在陣列後面的記憶體空間中,導致字元陣列儲存越界。
型別的C函式還有strcpy()等

解決辦法:
使用安全的字元處理函式strncpy()、 snprintf()等。使用安全的字元處理函式會要求寫入字元數粗的最大長度引數,超出的部分不會寫入到陣列中。
上面的sprintf程式碼可以修改成
1 char szSignKey[256] = {0};                                                                                                     
snprintf(szSignKey,sizeof(szSignKey),"userid&%u&version&%s&msg_body&%s&%s", uiUserID,strVersion.c_str(),strMsgBody.c_str(), SIGN_KEY);

  超出的字元會被截斷掉,不會導致字元陣列越界問題。



相關文章