Skip to content

Commit 63639ea

Browse files
committed
More FP tweaks.
1 parent bc76018 commit 63639ea

4 files changed

Lines changed: 73 additions & 3 deletions

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,8 @@ class TimeConversionFunction extends Function {
534534
"FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
535535
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
536536
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
537-
"RtlTimeToSecondsSince1970", "_mkgmtime", "SetSystemTime"
537+
"RtlTimeToSecondsSince1970", "_mkgmtime", "SetSystemTime", "SystemTimeToVariantTime",
538+
"VariantTimeToSystemTime"
538539
]
539540
}
540541
}

cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,19 @@ import semmle.code.cpp.controlflow.IRGuards
1616
/**
1717
* Functions whose operations should never be considered a
1818
* source or sink of a dangerous leap year operation.
19+
* The general concept is to add conversion functions
20+
* that convert one time type to another. Often
21+
* other ignorable operation heuristics will filter these,
22+
* but some cases, the simplest approach is to simply filter
23+
* the function entirely.
24+
* Note that flow through these functions should still be allowed
25+
* we just cannot start or end flow from an operation to a
26+
* year assignment in one of these functions.
1927
*/
2028
class IgnorableFunction extends Function {
2129
IgnorableFunction() {
30+
this instanceof TimeConversionFunction
31+
or
2232
// Helper utility in postgres with string time conversions
2333
this.getName() = "DecodeISO8601Interval"
2434
or
@@ -119,6 +129,9 @@ predicate isLikelyConversionConstant(int c) {
119129
i = 1899 or // Observed in uses with 1900 to address off by one scenarios
120130
i = 292275056 or // qdatetime.h Qt Core year range first year constant
121131
i = 292278994 or // qdatetime.h Qt Core year range last year constant
132+
i = 1601 or // Windows FILETIME epoch start year
133+
i = 1970 or // Unix epoch start year
134+
i = 70 or // Unix epoch start year short form
122135
i = 0
123136
)
124137
}
@@ -351,9 +364,12 @@ module OperationToYearAssignmentConfig implements DataFlow::ConfigSig {
351364
predicate isBarrier(DataFlow::Node n) {
352365
exists(ArrayExpr arr | arr.getArrayOffset() = n.asExpr())
353366
or
354-
n.asExpr().getUnspecifiedType() instanceof PointerType
367+
n.getType().getUnspecifiedType() instanceof PointerType
368+
or
369+
n.getType().getUnspecifiedType() instanceof CharType
355370
or
356-
n.asExpr().getUnspecifiedType() instanceof CharType
371+
// If a type resembles "string" ignore flow (likely string conversion, currently ignored)
372+
n.getType().getUnspecifiedType().stripType().getName().toLowerCase().matches("%string%")
357373
or
358374
n.asExpr() instanceof IgnorableOperation
359375
or

cpp/ql/test/query-tests/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification/UncheckedLeapYearAfterYearModification.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ edges
2222
| test.cpp:1083:2:1083:4 | ... ++ | test.cpp:1082:26:1082:26 | *x | provenance | |
2323
| test.cpp:1086:37:1086:37 | *x | test.cpp:1099:27:1099:35 | increment_arg_by_pointer output argument | provenance | |
2424
| test.cpp:1087:2:1087:7 | ... ++ | test.cpp:1086:37:1086:37 | *x | provenance | |
25+
| test.cpp:1183:2:1183:15 | ... += ... | test.cpp:1185:16:1185:19 | year | provenance | |
26+
| test.cpp:1183:10:1183:15 | offset | test.cpp:1183:2:1183:15 | ... += ... | provenance | |
2527
nodes
2628
| test.cpp:422:14:422:14 | 2 | semmle.label | 2 |
2729
| test.cpp:440:2:440:11 | ... ++ | semmle.label | ... ++ |
@@ -56,6 +58,9 @@ nodes
5658
| test.cpp:1099:27:1099:35 | increment_arg_by_pointer output argument | semmle.label | increment_arg_by_pointer output argument |
5759
| test.cpp:1133:3:1133:15 | -- ... | semmle.label | -- ... |
5860
| test.cpp:1153:14:1153:26 | ... - ... | semmle.label | ... - ... |
61+
| test.cpp:1183:2:1183:15 | ... += ... | semmle.label | ... += ... |
62+
| test.cpp:1183:10:1183:15 | offset | semmle.label | offset |
63+
| test.cpp:1185:16:1185:19 | year | semmle.label | year |
5964
subpaths
6065
testFailures
6166
| test.cpp:1075:2:1075:11 | ... ++ | Unexpected result: Alert |

cpp/ql/test/query-tests/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification/test.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,4 +1151,52 @@ typedef struct _TIME_FIELDS {
11511151
void
11521152
tp_ptime(PTIME_FIELDS ptm){
11531153
ptm->Year = ptm->Year - 1; // $ Alert[cpp/microsoft/public/leap-year/unchecked-after-arithmetic-year-modification]
1154+
}
1155+
1156+
1157+
bool isLeapYearRaw(WORD year)
1158+
{
1159+
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
1160+
}
1161+
1162+
void leap_year_checked_raw_false_positive1(WORD year, WORD offset, WORD day){
1163+
struct tm tmp;
1164+
1165+
year += offset;
1166+
1167+
if (isLeapYearRaw(year)){
1168+
// in this simplified example, assume the logic of this function
1169+
// can assume a day is 28 by default
1170+
// this check is more to establish the leap year guard is present
1171+
day += 1;
1172+
}
1173+
1174+
// Assume the check handled leap year correctly
1175+
tmp.tm_year = year; // GOOD
1176+
tmp.tm_mday = day;
1177+
}
1178+
1179+
1180+
void leap_year_checked_raw_false_positive2(WORD year, WORD offset, WORD day){
1181+
struct tm tmp;
1182+
1183+
year += offset;
1184+
1185+
tmp.tm_year = year; // GOOD, check performed immediately after on raw year
1186+
1187+
// Adding some additional checks to resemble cases observed in the wild
1188+
if ( day > 0)
1189+
{
1190+
if (isLeapYearRaw(year)){
1191+
// Assume logic that would adjust the day correctly
1192+
}
1193+
}
1194+
else{
1195+
if (isLeapYearRaw(year)){
1196+
// Assume logic that would adjust the day correctly
1197+
}
1198+
}
1199+
1200+
tmp.tm_mday = day;
1201+
11541202
}

0 commit comments

Comments
 (0)