Avviso C26861
Il campo di un oggetto
var
data/ora è stato modificato senza il controllo dell'anno bisestile corretto: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.
Non è possibile aggiungere o sottrarre alcuni numeri da o verso il campo anno, mese o giorno di un oggetto data/ora senza prendere in considerazione anni bisestili. Questo calcolo viene in genere eseguito per determinare la data di scadenza per un certificato, ad esempio. In molte date, un calcolo ingenuo può produrre il risultato desiderato. Tuttavia, quando il risultato è il 29 febbraio (un giorno bisestile) e l'anno non è bisestile, il risultato non è valido.
Ad esempio, l'aggiunta di un anno a 2020-01-31 produce 2021-01-31. Ma l'aggiunta di un anno al 2020-02-29 produce 2021-02-29, che non è una data valida perché il 2021 non è un anno bisestile.
Prestare attenzione quando si modificano variabili che rappresentano valori di data. Gestire correttamente gli anni bisestili e i giorni intercalari oppure usare un'API o una libreria che gestisce in modo sicuro l'aritmetica della data.
Nome dell'analisi del codice: DATETIME_MANIPULATION_WITHOUT_LEAPYEAR_CHECK
Esempio
Il codice seguente sposta in avanti l'ora di sistema di un anno incrementando il campo year dell'oggetto data e ora che rappresenta l'ora di sistema. Tuttavia, può produrre un oggetto data-ora non valido se la data era il 29 febbraio prima della modifica, perché l'anno successivo non è bisestile:
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear++; // warning C26861
Per evitare di creare un oggetto data/ora non valido a causa di un anno bisestile, verificare se la data risultante è ancora valida e apportare le modifiche necessarie per renderlo valido, come in questo esempio:
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;
}
}
Euristica
Attualmente, questa regola riconosce solo lo struct di Windows SYSTEMTIME
e lo struct C tm
.
Questa regola usa un'euristica semplificata per trovare modifiche potenzialmente rischiose e segnala avvisi, a meno che non sia presente un controllo bisestile o bisestile appropriato. Non tenta di verificare se il controllo dell'anno bisestile o del giorno bisestile viene eseguito correttamente per l'oggetto data/ora modificato.
Questa regola è una regola di consenso esplicito, il che significa che 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.