Редагувати

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


Warning C6394

A lookup table of size 365 isn't sufficient to handle leap years

This rule was added in Visual Studio 2022 17.8.

Remarks

In the Gregorian calendar, every year exactly divisible by four is a leap year--except for years that are exactly divisible by 100. The centurial years are also leap years if they're exactly divisible by 400.

A leap year bug occurs when software doesn't account for this leap year logic, or uses flawed logic. The can affect reliability, availability, or even the security of the affected system.

Lookup tables of size 365 are often used to quickly find the month a given day corresponds to, and so on. However, it isn't correct because a leap year has 366 days.

Code analysis name: LEAP_YEAR_INVALID_DATE_KEYED_LOOKUP_MUTABLE

Example

The following code creates a lookup table for the day of the year, but assumes there are 365 days per year. However, this produces the wrong result, or can cause an out-of-bounds access of the lookup table, if the year is a leap year:

#include <vector> 
  
void foo(int year) 
{ 
    std::vector<int> items(365);  // C6394 
    // Initialize items and use it... 
    // Another item may be added to the vector if year is a leap year, but this
    // rule doesn't check if that is the case.
}

To fix this problem, adjust the size of the lookup table as the table is created according to the result of a leap year check:

#include <vector> 
  
void foo(int year) 
{ 
    bool isLeapYear = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); 
    const std::vector<int> items(isLeapYear ? 366 : 365); 
    // Initialize items and use it... 
}

Heuristics

This rule is enforced by checking if a lookup table has an initial size of 365 elements, but can be expanded to 366. However, it doesn't check if the table’s size is adjusted through proper leap year check or not, and so is a low confidence warning.

See also

C6393
C26861
C26862
C26863
C26864