Sdílet prostřednictvím


Upozornění C26864

Pole Den objektu var data a času bylo změněno za předpokladu, že 365 dní v roce 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.

Při provádění aritmetických operací u proměnné, která představuje datum, musíte vzít v úvahu přestupné roky. Není bezpečné předpokládat, že rok je dlouhý 365 dní. Přestupný rok má 366 dní kvůli "přestupný den" přidaný jako 29. den v únoru.

Chcete-li správně přejít na rok, určete, zda časové rozpětí obsahuje přestupný den, a pak proveďte výpočet pomocí správného počtu dní. Je lepší, pokud je rok přímo upřesňující, s odpovídající kontrolou přestupového dne ve výsledném datu. Případně můžete použít zavedenou rutinu knihovny, která zpracovává přestupné roky správně.

Název analýzy kódu: DATETIME_MANIPULATION_ASSUMING_365_DAYS_WITHOUT_LEAPYEAR_CHECK

Příklad

Následující kód se pokusí získat aktuální systémový čas, posunout den o jeden rok přidáním 365 dnů do pole dne a upravit datum za přestupný rok pravidlo. Výsledek ale nemusí spadat do stejného měsíce a data příštího roku:

#include <Windows.h> 
 
void foo() 
{ 
    SYSTEMTIME st; 

    GetSystemTime(&st); 

    // Advance a year by adding 365 days 
    st.wDay += 365;    // C26864 
}

Pokud chcete tento problém vyřešit, přejděte přímo do pole roku a upravte datum podle pravidla přestupového roku:

#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; 
        } 
    } 
}

Heuristika

Toto pravidlo rozpoznává pouze strukturu systému Windows SYSTEMTIME a strukturu jazyka C tm .

Toto pravidlo se vynucuje, pokud je pole data přímo změněno 365 dny. Nebere v úvahu, jestli je hodnota pole kalendářního data přiřazená jiné proměnné a pak manipulována, a proto může chybět ekvivalentní chyby.

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 naleznete v tématu Použití sad pravidel k určení C++ pravidel ke spuštění.

Viz také

C6393
C6394
C26861
C26862
C26863