Advertencia C26861
El campo de un objeto
var
de fecha y hora se ha modificado sin una comprobación de año bisiesto adecuada:expr
Esta regla se agregó en Visual Studio 2022 17.8.
Comentarios
En el calendario gregoriano, cada año exactamente divisible por cuatro es un año bisiesto, excepto por años que son exactamente divisibles en 100. Los siglos también son años bisiestos si son exactamente divisibles en 400.
Se produce un error de año bisiesto cuando el software no tiene en cuenta esta lógica de año bisiesto o usa lógica errónea. puede afectar a la confiabilidad, disponibilidad o incluso a la seguridad del sistema afectado.
No es seguro agregar o restar algún número al campo año, mes o día de un objeto de fecha y hora sin tener en cuenta años bisiestos. Este cálculo se suele realizar para determinar la fecha de expiración de un certificado, por ejemplo. En muchas fechas, un cálculo naïve puede producir el resultado deseado. Sin embargo, cuando el resultado es el 29 de febrero (un día bisiesto) y el año no es un año bisiesto, el resultado no es válido.
Por ejemplo, agregar un año a 2020-01-31 genera 2021-01-31. Pero agregar un año al 2020-02-29 genera 2021-02-29, que no es una fecha válida porque 2021 no es un año bisiesto.
Tenga cuidado al manipular variables que representan valores de fecha. Controle los años bisiestos y los días bisiestos correctamente, o use una API o biblioteca que controle la aritmética de fecha de forma segura.
Nombre de análisis de código: DATETIME_MANIPULATION_WITHOUT_LEAPYEAR_CHECK
Ejemplo
El código siguiente avanza la hora del sistema en un año incrementando el campo año del objeto de fecha y hora que representa la hora del sistema. Sin embargo, puede producir un objeto de fecha y hora no válido si la fecha era el 29 de febrero antes de la modificación, ya que el próximo año no es un año bisiesto:
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear++; // warning C26861
Para evitar crear un objeto de fecha y hora no válido debido a un año bisiesto, compruebe si la fecha resultante sigue siendo válida y realice los ajustes necesarios para que sea válido, como en este ejemplo:
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
Actualmente, esta regla solo reconoce la estructura de Windows SYSTEMTIME
y la estructura de C tm
.
Esta regla emplea una heurística simplificada para encontrar cambios potencialmente arriesgados e informa de advertencias a menos que haya una comprobación de año bisiesto o día bisiesto adecuada. No intenta comprobar si la comprobación del año bisiesto o del día bisiesto se realiza correctamente para el objeto de fecha y hora modificado.
Esta regla es una regla de participación, lo que significa que el análisis de código debe usar un archivo de conjunto de reglas y la regla debe incluirse explícitamente en el archivo del conjunto de reglas y habilitarla para que se aplique. Para obtener más información sobre cómo crear un conjunto de reglas personalizado para el análisis de código, vea: Usar conjuntos de reglas para especificar las C++
reglas que se van a ejecutar.