分享方式:


警告 C26861

已修改日期時間物件的 var 欄位,而不需進行適當的閏年檢查: expr

此規則已在 Visual Studio 2022 17.8 中新增。

備註

在公曆中,每年只有四分之一的可分割是一個閏年,除了100年完全可見的年份。 百年也是閏年,如果他們完全被400分分。

當軟體不考慮這個閏年邏輯,或使用有缺陷的邏輯時,就會發生閏年錯誤。 可能會影響受影響系統的可靠性、可用性,甚至是安全性。

不安全地在日期時間物件的年、月或日欄位中新增或減去某些數位,而不考慮閏年。 此計算通常會執行,以判斷憑證的到期日,例如。 在許多日期,天真的計算可能會產生所需的結果。 不過,當結果為 2 月 29 日(閏日)且年份不是閏年時,結果會無效。

例如,將一年新增至 2020-01-31 會產生 2021-01-31。 但是,將一年新增至 2020-02-29 會產生 2021-02-29,這不是有效的日期,因為 2021 年不是閏年。

在操作代表日期值的變數時請小心。 正確處理閏年和閏天,或使用可安全地處理日期算術的 API 或連結庫。

程式代碼分析名稱: DATETIME_MANIPULATION_WITHOUT_LEAPYEAR_CHECK

範例

下列程式代碼會藉由遞增代表系統時間之日期時間物件的年份欄位,將系統時間往前移一年。 不過,如果修改前的日期是 2 月 29 日,它可能會產生無效的日期時間對象,因為明年不是閏年:

SYSTEMTIME st; 
GetSystemTime(&st); 
st.wYear++;  // warning C26861 

若要避免因為閏年而建立無效的日期時間物件,請檢查產生的日期是否仍然有效,並進行必要的調整,使其有效,如下列範例所示:

SYSTEMTIME st; 
GetSystemTime(&st); 
st.wYear++; 
if (st.wMonth == 2 && st.wDay == 29) 
{ 
    // move back a day when landing on Feb 29 in a non-leap year 
    bool isLeapYear = st.wYear % 4 == 0 && (st.wYear % 100 != 0 || st.wYear % 400 == 0); 
    if (!isLeapYear) 
    { 
        st.wDay = 28; 
    } 
}

啟發學習法

目前,此規則只會辨識 Windows SYSTEMTIME 結構與 C tm 結構。

此規則會採用簡化的啟發學習法來尋找潛在的風險變更,並報告警告,除非有適當的閏年或閏日檢查。 它不會嘗試驗證修改日期時間物件是否正確執行閏年或閏日檢查。

此規則是加入加入規則,這表示程式代碼分析應該使用規則集檔案,而且規則應該明確包含在規則集檔案中,並啟用規則以套用規則集檔案。 如需建立程式代碼分析自定義規則集的詳細資訊,請參閱: 使用規則集指定要 C++ 執行的規則。

另請參閱

C6393
C6394
C26862
C26863
C26864