Поделиться через


Предупреждение C26861

Поле объекта var даты и времени было изменено без надлежащей проверки високосного года: expr

Это правило было добавлено в Visual Studio 2022 17.8.

Замечания

В григорианском календаре каждый год точно делится на четыре високосный год, за исключением лет, которые точно делятся на 100. Вековые годы также високосные годы, если они точно делятся на 400.

Ошибка високосного года возникает, когда программное обеспечение не учитывает логику этого високосного года или использует несовершенную логику. Это может повлиять на надежность, доступность или даже безопасность затронутой системы.

Небезопасно добавлять или вычитать некоторое число в поле года, месяца или дня объекта даты и времени без учета високосных лет. Это вычисление обычно выполняется для определения даты окончания срока действия сертификата, например. Во многих датах наивное вычисление может привести к желаемому результату. Однако, когда результат 29 февраля (високосный день) и год не является високосным годом, результат является недопустимым.

Например, добавление года к 2020-01-31 производит 2021-01-31. Но добавление года к 2020-02-29 производит 2021-02-29, которая не является допустимой датой, потому что 2021 год не високосный год.

Будьте осторожны при управлении переменными, представляющими значения даты. Обработайте лет високосные и скачковые дни должным образом, или используйте API или библиотеку, которая обрабатывает арифметические арифметические даты безопасно.

Имя анализа кода: DATETIME_MANIPULATION_WITHOUT_LEAPYEAR_CHECK

Пример

Следующий код увеличивает системное время на год путем увеличения поля года объекта даты и времени, представляющего системное время. Однако он может создать недопустимый объект даты и времени, если дата была 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