Avviso C26864
Il campo giorno di un oggetto
var
data/ora è stato modificato presupponendo che 365 giorni all'anno senza un corretto controllo dell'anno bisestile:expr
Questa regola è stata aggiunta in Visual Studio 2022 17.8.
Osservazioni:
Nel calendario gregoriano, ogni anno esattamente divisibile per quattro è un anno bisestile, ad eccezione degli anni che sono esattamente divisibile per 100. Gli anni centuriali sono anche bisestili se sono esattamente divisibili per 400.
Un bug dell'anno bisestile si verifica quando il software non tiene conto di questa logica bisestile o usa logica difettosa. Può influire sull'affidabilità, la disponibilità o anche la sicurezza del sistema interessato.
È necessario prendere in considerazione anni bisestili quando si eseguono operazioni aritmetiche su una variabile che rappresenta una data. Non è sicuro presupporre che un anno sia lungo 365 giorni. Un anno bisestile ha 366 giorni a causa del 'bisestile' aggiunto come 29° giorno a febbraio.
Per avanzare correttamente un anno, determinare se l'intervallo di tempo contiene un giorno bisestile, quindi eseguire il calcolo usando il numero corretto di giorni. È meglio se l'anno è direttamente avanzato, con un controllo del giorno bisestile appropriato sulla data risultante. In alternativa, usare una routine di libreria stabilita che gestisce correttamente gli anni intercalare.
Nome dell'analisi del codice: DATETIME_MANIPULATION_ASSUMING_365_DAYS_WITHOUT_LEAPYEAR_CHECK
Esempio
Il codice seguente tenta di ottenere l'ora di sistema corrente, di avanzare il giorno per un anno aggiungendo 365 giorni al campo giorno e modificando la regola della data per anno bisestile. Tuttavia, il risultato potrebbe non rientrare nello stesso mese/data dell'anno successivo:
#include <Windows.h>
void foo()
{
SYSTEMTIME st;
GetSystemTime(&st);
// Advance a year by adding 365 days
st.wDay += 365; // C26864
}
Per risolvere questo problema, avanzare direttamente il campo dell'anno e regolare la data per la regola dell'anno bisestile:
#include <Windows.h>
void foo()
{
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear++; // Advance a year
// Adjust the date
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;
}
}
}
Euristica
Questa regola riconosce solo lo struct di Windows SYSTEMTIME
e lo struct C tm
.
Questa regola viene applicata se il campo data viene modificato direttamente da 365 giorni. Non viene considerato se il valore del campo data viene assegnato a un'altra variabile e quindi modificato e quindi può perdere errori equivalenti.It't consider if the value of date field is assigned to another variable and then manipulated, and so can miss equivalent errors.
Questa regola è una regola di consenso esplicito, ovvero l'analisi del codice deve usare un file del set di regole e la regola deve essere inclusa in modo esplicito nel file del set di regole e abilitata per l'applicazione. Per altre informazioni sulla creazione di un set di regole personalizzato per l'analisi del codice, vedere Usare set di regole per specificare le C++
regole da eseguire.