Aviso C26861
O campo de um objeto
var
de data-hora foi modificado 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.
Não é seguro adicionar ou subtrair algum número de ou para o campo de ano, mês ou dia de um objeto de data-hora sem levar em conta os anos bissextos. Esse cálculo geralmente é realizado para determinar a data de expiração de um certificado, por exemplo. Em muitas datas, um cálculo ingênuo pode produzir o resultado desejado. No entanto, quando o resultado é 29 de fevereiro (um dia bissexto) e o ano não é um ano bissexto, o resultado é inválido.
Por exemplo, adicionar um ano a 2020-01-31 produz 2021-01-31. Mas adicionar um ano a 29-02-2020 produz 29-02-2021, que não é uma data válida porque 2021 não é um ano bissexto.
Seja cauteloso ao manipular variáveis que representam valores de data. Lide com anos bissextos e dias bissextos corretamente ou use uma API ou biblioteca que lide com aritmética de data com segurança.
Nome da análise de código: DATETIME_MANIPULATION_WITHOUT_LEAPYEAR_CHECK
Exemplo
O código a seguir avança a hora do sistema em um ano incrementando o campo ano do objeto date-time que representa a hora do sistema. No entanto, ele pode produzir um objeto de data-hora inválido se a data foi 29 de fevereiro antes da modificação, porque o próximo ano não é um ano bissexto:
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear++; // warning C26861
Para evitar a criação de um objeto de data-hora inválido devido a um ano bissexto, verifique se a data resultante ainda é válida e faça os ajustes necessários para torná-la válida, como neste exemplo:
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;
}
}
Heurística
Atualmente, essa regra só reconhece o Windows SYSTEMTIME
struct e C tm
struct.
Essa regra emprega uma heurística simplificada para encontrar alterações potencialmente arriscadas e relata avisos, a menos que haja verificação apropriada de ano bissexto ou dia bissexto. Ele não tenta verificar se a verificação de ano bissexto ou dia bissexto é executada corretamente para o objeto de data-hora modificado.
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.