Compartilhar via


Aviso C26864

O campo Dia de um objeto var de data-hora foi modificado supondo 365 dias por ano sem a devida verificação de ano bissexto: expr

Essa regra foi adicionada no Visual Studio 2022 17.8.

Comentários

No calendário gregoriano, cada ano exatamente divisível por quatro é um ano bissexto - exceto para anos que são exatamente divisíveis por 100. Os anos centuriais também são anos bissextos se forem exatamente divisíveis por 400.

Um bug de ano bissexto ocorre quando o software não dá conta dessa lógica de ano bissexto ou usa lógica falha. Isso pode afetar a confiabilidade, a disponibilidade ou até mesmo a segurança do sistema afetado.

Você deve levar em conta os anos bissextos ao executar operações aritméticas em uma variável que representa uma data. Não é seguro assumir que um ano tem 365 dias. Um ano bissexto tem 366 dias por causa do "dia bissexto" adicionado como um dia 29 em fevereiro.

Para avançar corretamente um ano, determine se o período de tempo contém um dia bissexto e, em seguida, execute o cálculo usando o número correto de dias. É melhor se o ano estiver diretamente adiantado, com uma verificação apropriada do dia bissexto na data resultante. Como alternativa, use uma rotina de biblioteca estabelecida que lide com anos bissextos corretamente.

Nome da análise de código: DATETIME_MANIPULATION_ASSUMING_365_DAYS_WITHOUT_LEAPYEAR_CHECK

Exemplo

O código a seguir tenta obter a hora atual do sistema, adiantar o dia em um ano adicionando 365 dias ao campo de dia e ajustar a regra de data por ano bissexto. No entanto, o resultado pode não cair no mesmo mês/data do próximo ano:

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

    GetSystemTime(&st); 

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

Para corrigir esse problema, adiante o campo de ano diretamente e ajuste a data de acordo com a regra de ano bissexto:

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

Heurística

Esta regra só reconhece o Windows SYSTEMTIME struct e tm C struct.

Essa regra será aplicada se o campo de data for modificado diretamente por 365 dias. Ele não considera se o valor do campo de data é atribuído a outra variável e, em seguida, manipulado e, portanto, pode perder erros equivalentes.

Essa regra é uma regra de aceitação, o que significa que a análise de código deve usar um arquivo de conjunto de regras, e a regra deve ser explicitamente incluída no arquivo de conjunto de regras e habilitada para que seja aplicada. Para obter mais informações sobre como criar um conjunto de regras personalizado para análise de código, consulte Usar conjuntos de regras para especificar as C++ regras a serem executadas.

Confira também

C6393
C6394
C26861
C26862
C26863