Sdílet prostřednictvím


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í.

Viz také

C6393
C6394
C26862
C26863
C26864