Skip to content

Commit 1dba99f

Browse files
authored
Merge pull request #21292 from microsoft/UncheckedLeaprYearAfterModification_Refactor_Upstream
C++: Refactor of UncheckedLeapYearAfterModification
2 parents ca41ae0 + 38219f6 commit 1dba99f

File tree

9 files changed

+2160
-164
lines changed

9 files changed

+2160
-164
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results.

cpp/ql/lib/semmle/code/cpp/commons/DateTime.qll

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ class PackedTimeType extends Type {
1414
}
1515
}
1616

17-
private predicate timeType(string typeName) { typeName = ["_SYSTEMTIME", "SYSTEMTIME", "tm"] }
17+
private predicate timeType(string typeName) {
18+
typeName = ["_SYSTEMTIME", "SYSTEMTIME", "tm", "TIME_FIELDS", "_TIME_FIELDS", "PTIME_FIELDS"]
19+
}
1820

1921
/**
2022
* A type that is used to represent times and dates in an 'unpacked' form, that is,
@@ -95,3 +97,24 @@ class StructTmMonthFieldAccess extends MonthFieldAccess {
9597
class StructTmYearFieldAccess extends YearFieldAccess {
9698
StructTmYearFieldAccess() { this.getTarget().getName() = "tm_year" }
9799
}
100+
101+
/**
102+
* A `DayFieldAccess` for the `TIME_FIELDS` struct.
103+
*/
104+
class TimeFieldsDayFieldAccess extends DayFieldAccess {
105+
TimeFieldsDayFieldAccess() { this.getTarget().getName() = "Day" }
106+
}
107+
108+
/**
109+
* A `MonthFieldAccess` for the `TIME_FIELDS` struct.
110+
*/
111+
class TimeFieldsMonthFieldAccess extends MonthFieldAccess {
112+
TimeFieldsMonthFieldAccess() { this.getTarget().getName() = "Month" }
113+
}
114+
115+
/**
116+
* A `YearFieldAccess` for the `TIME_FIELDS` struct.
117+
*/
118+
class TimeFieldsYearFieldAccess extends YearFieldAccess {
119+
TimeFieldsYearFieldAccess() { this.getTarget().getName() = "Year" }
120+
}

cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,37 @@ private module PossibleYearArithmeticOperationCheckConfig implements DataFlow::C
308308

309309
module PossibleYearArithmeticOperationCheckFlow =
310310
TaintTracking::Global<PossibleYearArithmeticOperationCheckConfig>;
311+
312+
/**
313+
* A time conversion function where either
314+
* 1) an incorrect leap year date would result in an error that can be checked from the return value or
315+
* 2) an incorrect leap year date is auto corrected (no checks required)
316+
*/
317+
class TimeConversionFunction extends Function {
318+
boolean autoLeapYearCorrecting;
319+
320+
TimeConversionFunction() {
321+
autoLeapYearCorrecting = false and
322+
(
323+
this.getName() =
324+
[
325+
"FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
326+
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
327+
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
328+
"RtlTimeToSecondsSince1970", "_mkgmtime", "SetSystemTime", "VarUdateFromDate", "from_tm"
329+
]
330+
or
331+
// Matches all forms of GetDateFormat, e.g. GetDateFormatA/W/Ex
332+
this.getName().matches("GetDateFormat%")
333+
)
334+
or
335+
autoLeapYearCorrecting = true and
336+
this.getName() =
337+
["mktime", "_mktime32", "_mktime64", "SystemTimeToVariantTime", "VariantTimeToSystemTime"]
338+
}
339+
340+
/**
341+
* Holds if the function is expected to auto convert a bad leap year date.
342+
*/
343+
predicate isAutoLeapYearCorrecting() { autoLeapYearCorrecting = true }
344+
}

0 commit comments

Comments
 (0)