다음을 통해 공유


경고 C26861

날짜-시간 개체 var 의 필드는 적절한 윤년 검사 없이 수정되었습니다. expr

이 규칙은 Visual Studio 2022 17.8에 추가되었습니다.

설명

그레고리오력에서는 매년 정확히 4개로 나눌 수 있으며, 100으로 정확히 나눌 수 있는 연도를 제외하고는 윤년입니다. 수세기는 400으로 정확히 나눌 수 있다면 윤년입니다.

소프트웨어가 이 윤년 논리를 고려하지 않거나 결함이 있는 논리를 사용하는 경우 윤년 버그가 발생합니다. 안정성, 가용성 또는 영향을 받는 시스템의 보안에도 영향을 줄 수 있습니다.

윤년을 고려하지 않고 날짜/시간 개체의 연도, 월 또는 일 필드에 일부 숫자를 추가하거나 빼는 것은 안전하지 않습니다. 이 계산은 인증서의 만료 날짜를 결정하기 위해 일반적으로 수행됩니다. 예를 들면 다음과 같습니다. 많은 날짜에서 순진한 계산은 원하는 결과를 생성할 수 있습니다. 그러나 결과가 2월 29일(윤일)이고 연도가 윤년이 아닌 경우 결과는 유효하지 않습니다.

예를 들어 2020-01-31에 연도를 추가하면 2021-01-31이 생성됩니다. 그러나 2020-02-29에 1년을 추가하면 2021-02-29가 생성되며, 이는 2021년이 윤년이 아니기 때문에 유효한 날짜가 아닙니다.

날짜 값을 나타내는 변수를 조작할 때는 주의해야 합니다. 윤년 및 윤일을 올바르게 처리하거나 날짜 산술 연산을 안전하게 처리하는 API 또는 라이브러리를 사용합니다.

코드 분석 이름: DATETIME_MANIPULATION_WITHOUT_LEAPYEAR_CHECK

예시

다음 코드는 시스템 시간을 나타내는 날짜-시간 개체의 연도 필드를 증가시켜 시스템 시간을 1년씩 진행합니다. 그러나 다음 해는 윤년이 아니므로 수정하기 전의 날짜가 2월 29일인 경우 잘못된 날짜-시간 개체를 생성할 수 있습니다.

SYSTEMTIME st; 
GetSystemTime(&st); 
st.wYear++;  // warning C26861 

윤년으로 인해 잘못된 날짜-시간 개체를 만들지 않도록 하려면 결과 날짜가 여전히 유효한지 확인하고 이 예제와 같이 유효하도록 필요한 조정을 수행합니다.

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

경험적 학습

현재 이 규칙은 Windows SYSTEMTIME 구조체 및 C tm 구조체만 인식합니다.

이 규칙은 간단한 추론을 사용하여 잠재적으로 위험한 변경 내용을 찾고 적절한 윤년 또는 윤일 검사가 없는 한 경고를 보고합니다. 수정된 날짜-시간 개체에 대해 윤년 또는 윤일 검사가 올바르게 수행되는지는 확인하지 않습니다.

이 규칙은 옵트인 규칙입니다. 즉, 코드 분석에서 규칙 집합 파일을 사용해야 하며 규칙이 규칙 집합 파일에 명시적으로 포함되어 적용되도록 설정되어야 합니다. 코드 분석을 위한 사용자 지정 규칙 집합을 만드는 방법에 대한 자세한 내용은 다음을 참조하세요. 규칙 집합을 사용하여 실행할 규칙을 지정 C++ 합니다.

참고 항목

C6393
C6394
C26862
C26863
C26864