Ostrzeżenie C26864
Pole dzień obiektu
var
daty/godziny zostało zmodyfikowane przy założeniu, że 365 dni rocznie bez odpowiedniego sprawdzania roku przestępnego:expr
Ta reguła została dodana w programie Visual Studio 2022 17.8.
Uwagi
W kalendarzu gregoriańskim każdy rok dokładnie dzielący przez cztery jest rokiem przestępnym — z wyjątkiem lat, które są dokładnie podzielne przez 100. Lata centurialne są również lat przestępnych, jeśli są dokładnie podzielne przez 400.
Błąd roku przestępnego występuje, gdy oprogramowanie nie uwzględnia tej logiki roku przestępnego lub używa wadliwej logiki. Może to mieć wpływ na niezawodność, dostępność, a nawet bezpieczeństwo systemu, którego dotyczy problem.
Należy wziąć pod uwagę lata przestępne podczas wykonywania operacji arytmetycznych na zmiennej reprezentującej datę. Nie można bezpiecznie założyć, że rok wynosi 365 dni. Rok przestępny ma 366 dni ze względu na "dzień przestępny" dodany jako 29 dzień w lutym.
Aby prawidłowo przejść rok, określ, czy przedział czasu zawiera dzień przestępny, a następnie wykonaj obliczenia przy użyciu poprawnej liczby dni. Lepiej jest, jeśli rok jest bezpośrednio zaawansowany, z odpowiednim sprawdzaniem dnia przestępnego w dacie wynikowej. Alternatywnie należy użyć ustalonej procedury biblioteki, która prawidłowo obsługuje lata przestępne.
Nazwa analizy kodu: DATETIME_MANIPULATION_ASSUMING_365_DAYS_WITHOUT_LEAPYEAR_CHECK
Przykład
Poniższy kod próbuje uzyskać bieżący czas systemowy, przejść dzień o jeden rok, dodając 365 dni do pola dnia i dostosowując datę na regułę roku przestępnego. Jednak wynik może nie spaść na ten sam miesiąc/datę następnego roku:
#include <Windows.h>
void foo()
{
SYSTEMTIME st;
GetSystemTime(&st);
// Advance a year by adding 365 days
st.wDay += 365; // C26864
}
Aby rozwiązać ten problem, przejdź bezpośrednio do pola rok i dostosuj datę dla reguły roku przestępowego:
#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;
}
}
}
Algorytmy heurystyczne
Ta reguła rozpoznaje tylko strukturę systemu Windows SYSTEMTIME
i strukturę języka C tm
.
Ta reguła jest wymuszana, jeśli pole daty jest bezpośrednio modyfikowane przez 365 dni. Nie uwzględnia, czy wartość pola daty jest przypisywana do innej zmiennej, a następnie manipulowana, a więc może przegapić równoważne błędy.
Ta reguła jest regułą zgody, co oznacza, że analiza kodu powinna używać pliku zestawu reguł, a reguła powinna zostać jawnie dołączona do pliku zestawu reguł i włączona, aby została zastosowana. Aby uzyskać więcej informacji na temat tworzenia niestandardowego zestawu reguł na potrzeby analizy kodu, zobacz Używanie zestawów reguł do określania C++
reguł do uruchomienia.