경고 C26864
날짜-시간 개체
var
의 일 필드는 적절한 윤년 검사 없이 연간 365일로 가정하여 수정되었습니다.expr
이 규칙은 Visual Studio 2022 17.8에 추가되었습니다.
설명
그레고리오력에서는 매년 정확히 4개로 나눌 수 있으며, 100으로 정확히 나눌 수 있는 연도를 제외하고는 윤년입니다. 수세기는 400으로 정확히 나눌 수 있다면 윤년입니다.
소프트웨어가 이 윤년 논리를 고려하지 않거나 결함이 있는 논리를 사용하는 경우 윤년 버그가 발생합니다. 안정성, 가용성 또는 영향을 받는 시스템의 보안에도 영향을 줄 수 있습니다.
날짜를 나타내는 변수에 대해 산술 연산을 수행할 때는 윤년을 고려해야 합니다. 1년이 365일이라고 가정하는 것은 안전하지 않습니다. 윤년은 2월에 29일로 추가된 '윤일'로 인해 366일이 있습니다.
1년을 올바르게 진행하려면 시간 범위에 윤일이 포함되어 있는지 확인한 다음 올바른 일 수를 사용하여 계산을 수행합니다. 연도가 직접 진행되면 결과 날짜에 적절한 윤일 검사를 하는 것이 좋습니다. 또는 윤년을 올바르게 처리하는 설정된 라이브러리 루틴을 사용합니다.
코드 분석 이름: DATETIME_MANIPULATION_ASSUMING_365_DAYS_WITHOUT_LEAPYEAR_CHECK
예시
다음 코드는 현재 시스템 시간을 가져오고, 일 필드에 365일을 추가하고, 윤년별 규칙을 조정하여 1년씩 하루를 진행하려고 합니다. 그러나 결과는 다음 해의 동일한 월/날짜에 속하지 않을 수 있습니다.
#include <Windows.h>
void foo()
{
SYSTEMTIME st;
GetSystemTime(&st);
// Advance a year by adding 365 days
st.wDay += 365; // C26864
}
이 문제를 해결하려면 연도 필드를 직접 진행하고 윤년 규칙에 따라 날짜를 조정합니다.
#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;
}
}
}
경험적 학습
이 규칙은 Windows SYSTEMTIME
구조체 및 C tm
구조체만 인식합니다.
이 규칙은 날짜 필드가 365일로 직접 수정되는 경우에 적용됩니다. 날짜 필드 값이 다른 변수에 할당된 다음 조작되었는지는 고려하지 않으므로 동일한 실수를 놓칠 수 있습니다.
이 규칙은 옵트인 규칙입니다. 즉, 코드 분석에서 규칙 집합 파일을 사용해야 하며 규칙이 규칙 집합 파일에 명시적으로 포함되어 적용되도록 설정되어야 합니다. 코드 분석을 위한 사용자 지정 규칙 집합을 만드는 방법에 대한 자세한 내용은 규칙 집합을 사용하여 실행할 규칙 지정 C++
을 참조하세요.