Upozornění C26861
Pole objektu
var
data a času bylo změněno bez správné kontroly přestupného roku:expr
Toto pravidlo bylo přidáno v sadě Visual Studio 2022 17.8.
Poznámky
V gregoriánském kalendáři je každý rok přesně dělitelný čtyřmi lety - s výjimkou let, které jsou přesně dělitelné 100. Centurial roky jsou také přestupné roky, pokud jsou přesně dělitelné o 400.
K chybě přestupného roku dochází v případě, že software nebere v úvahu tuto logiku přestupného roku nebo používá chybnou logiku. Může mít vliv na spolehlivost, dostupnost nebo dokonce i na zabezpečení ovlivněného systému.
Není bezpečné sčítat nebo odčítat určité číslo do nebo od roku, měsíce nebo dne objektu data a času bez zohlednění přestupných roků. Tento výpočet se obvykle provádí k určení data vypršení platnosti certifikátu, například. V mnoha datech může výpočet naïvu vytvořit požadovaný výsledek. Pokud je ale výsledek 29. února (přestupný den) a rok není přestupný rok, výsledek je neplatný.
Například přidání roku do roku 2020-01-31 vytvoří 2021-01-31. Ale přidání roku do roku 2020-02-29 vytvoří 2021-02-29, což není platné datum, protože 2021 není přestupný rok.
Při manipulaci s proměnnými, které představují hodnoty kalendářních dat, buďte opatrní. Zachytávejte přestupné roky a přestupné dny správně nebo použijte rozhraní API nebo knihovnu, která bezpečně zpracovává aritmetické datum.
Název analýzy kódu: DATETIME_MANIPULATION_WITHOUT_LEAPYEAR_CHECK
Příklad
Následující kód předá systémový čas o rok zvýšením pole roku objektu data a času představujícího systémový čas. Může však vytvořit neplatný objekt data a času, pokud datum bylo 29. února před úpravou, protože příští rok není přestupným rokem:
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear++; // warning C26861
Pokud se chcete vyhnout vytvoření neplatného objektu data a času z důvodu přestupového roku, zkontrolujte, jestli je výsledné datum stále platné, a proveďte potřebné úpravy, aby byl platný, jako v tomto příkladu:
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;
}
}
Heuristika
V současné době toto pravidlo rozpozná pouze strukturu systému Windows SYSTEMTIME
a strukturu jazyka C tm
.
Toto pravidlo využívá zjednodušenou heuristiku k nalezení potenciálně rizikových změn a hlášení upozornění, pokud neexistuje vhodná kontrola přestupných dnů nebo přestupných dnů. Nepokouší se ověřit, jestli se pro upravený objekt data a času správně provádí kontrola přestupných dnů nebo přestupných dnů.
Toto pravidlo je pravidlo výslovného souhlasu, což znamená, že analýza kódu by měla používat soubor sady pravidel a pravidlo by mělo být explicitně zahrnuto do souboru sady pravidel a povoleno, aby se použilo. Další informace o vytvoření vlastní sady pravidel pro analýzu kódu najdete v tématu: Použití sad pravidel k určení C++
pravidel ke spuštění.