@@ -851,10 +851,10 @@ bool tp_intermediaryVar(struct timespec now, struct logtime ×tamp_remote)
851851 timestamp_remote.tm = tm_parsed;
852852 timestamp_remote.tm .tm_isdst = -1 ;
853853 timestamp_remote.usec = now.tv_nsec * 0.001 ;
854- for (year = tm_now.tm_year + 1 ;; --year) // $ Source
854+ for (year = tm_now.tm_year + 1 ;; --year)
855855 {
856856 // assert(year >= tm_now.tm_year - 1);
857- timestamp_remote.tm .tm_year = year; // $ Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
857+ timestamp_remote.tm .tm_year = year;
858858 if (mktime (×tamp_remote.tm ) < t_now + 7 * 24 * 60 * 60 )
859859 break ;
860860 }
@@ -1381,4 +1381,159 @@ void constant_day_on_year_modification1(WORD year, WORD offset, WORD month){
13811381 // which is dangerous.
13821382 set_time (year+1 , month, 31 );// $ Source
13831383 }
1384- }
1384+ }
1385+
1386+
1387+ void modification_after_conversion1 (tm timeinfo){
1388+ // convert a tm year into a civil year, then modify after conversion
1389+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1390+ // and never reassigned to another struct.
1391+ WORD year = timeinfo.tm_year + 1900 ;
1392+
1393+ year += 1 ; // $ MISSING: Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1394+ }
1395+
1396+ WORD get_civil_year (tm timeinfo){
1397+ return timeinfo.tm_year + 1900 ;
1398+ }
1399+
1400+ void modification_after_conversion2 (tm timeinfo){
1401+ // convert a tm year into a civil year, then modify after conversion
1402+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1403+ // and never reassigned to another struct.
1404+ WORD year = get_civil_year (timeinfo);
1405+ year += 1 ; // $ MISSING: Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1406+ }
1407+
1408+ void modification_after_conversion_saved_to_other_time_struct1 (tm timeinfo){
1409+ // convert a tm year into a civil year, then modify after conversion
1410+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1411+ // and never reassigned to another struct.
1412+ WORD year = timeinfo.tm_year + 1900 ;
1413+
1414+ year += 1 ; // $ Source
1415+
1416+ SYSTEMTIME s;
1417+ // FALSE NEGATIVE: missing this because the conversion happens locally before
1418+ // the year adjustment, which seems as though it is part of a conversion itself
1419+ s.wYear = year; // $ MISSING: Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1420+ }
1421+
1422+
1423+
1424+ void modification_after_conversion_saved_to_other_time_struct2 (tm timeinfo){
1425+ // convert a tm year into a civil year, then modify after conversion
1426+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1427+ // and never reassigned to another struct.
1428+ WORD year = get_civil_year (timeinfo);
1429+
1430+ year += 1 ; // $ Source
1431+
1432+ SYSTEMTIME s;
1433+ s.wYear = year; // $ Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1434+ }
1435+
1436+ void modification_after_conversion_saved_to_other_time_struct3 (tm timeinfo){
1437+ // convert a tm year into a civil year, then modify after conversion
1438+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1439+ // and never reassigned to another struct.
1440+ WORD year = timeinfo.tm_year + 1900 ;
1441+
1442+ year = year + 1 ; // $ Source
1443+
1444+ SYSTEMTIME s;
1445+ // FALSE NEGATIVE: missing this because the conversion happens locally before
1446+ // the year adjustment, which seems as though it is part of a conversion itself
1447+ s.wYear = year; // $ MISSING: Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1448+ }
1449+
1450+
1451+ void year_saved_to_variable_then_modified1 (tm timeinfo){
1452+ // A modified year is not directly assigned to the year, rather, the year is
1453+ // saved to a variable, modified, used, but never assigned back.
1454+ WORD year = timeinfo.tm_year ;
1455+
1456+ // NOTE: should we even try to detect cases like this?
1457+ // Our current rationale is that a year in a struct is more dangerous than a year in isolation
1458+ // A year in isolation is harder to interpret
1459+ year += 1 ; // MISSING: $ Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1460+ }
1461+
1462+ void modification_before_conversion1 (tm timeinfo){
1463+ timeinfo.tm_year += 1 ; // $ Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1464+ // convert a tm year into a civil year, then modify after conversion
1465+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1466+ // and never reassigned to another struct.
1467+ WORD year = timeinfo.tm_year + 1900 ;
1468+ }
1469+
1470+ void modification_before_conversion2 (tm timeinfo){
1471+ timeinfo.tm_year += 1 ; // $ Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1472+ // convert a tm year into a civil year, then modify after conversion
1473+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1474+ // and never reassigned to another struct.
1475+ WORD year = get_civil_year (timeinfo);
1476+ }
1477+
1478+
1479+
1480+ void year_saved_to_variable_then_modified_with_leap_check1 (tm timeinfo){
1481+ // A modified year is not directly assigned to the year, rather, the year is
1482+ // saved to a variable, modified, used, but never assigned back.
1483+ WORD year = timeinfo.tm_year ;
1484+
1485+ year += 1 ;
1486+
1487+ // performing a check is considered good enough, even if not used correctly
1488+ bool b = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0 );
1489+ }
1490+
1491+
1492+ void modification_after_conversion_with_leap_check1 (tm timeinfo){
1493+ // convert a tm year into a civil year, then modify after conversion
1494+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1495+ // and never reassigned to another struct.
1496+ WORD year = timeinfo.tm_year + 1900 ;
1497+
1498+ year += 1 ;
1499+
1500+ // performing a check is considered good enough, even if not used correctly
1501+ bool b = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0 );
1502+ }
1503+
1504+ void modification_after_conversion_with_leap_check2 (tm timeinfo){
1505+ // convert a tm year into a civil year, then modify after conversion
1506+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1507+ // and never reassigned to another struct.
1508+ WORD year = get_civil_year (timeinfo);
1509+
1510+ year += 1 ;
1511+
1512+ // performing a check is considered good enough, even if not used correctly
1513+ bool b = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0 );
1514+ }
1515+
1516+ void modification_before_conversion_with_leap_check1 (tm timeinfo){
1517+ timeinfo.tm_year += 1 ;
1518+ // convert a tm year into a civil year, then modify after conversion
1519+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1520+ // and never reassigned to another struct.
1521+ WORD year = timeinfo.tm_year + 1900 ;
1522+
1523+ // performing a check is considered good enough, even if not used correctly
1524+ bool b = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0 );
1525+ }
1526+
1527+ void modification_before_conversion_with_leap_check2 (tm timeinfo){
1528+ timeinfo.tm_year += 1 ;
1529+ // convert a tm year into a civil year, then modify after conversion
1530+ // This case shows a false negative where the year might be used and it is incorrectly modified,
1531+ // and never reassigned to another struct.
1532+ WORD year = get_civil_year (timeinfo);
1533+
1534+ // performing a check is considered good enough, even if not used correctly
1535+ bool b = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0 );
1536+ }
1537+
1538+
1539+
0 commit comments