Skip to content

Commit 3282718

Browse files
committed
Add TIME_FIELDS struct and test case
1 parent ce802bd commit 3282718

3 files changed

Lines changed: 51 additions & 3 deletions

File tree

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

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

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

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

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,11 @@ module OperationToYearAssignmentConfig implements DataFlow::ConfigSig {
312312
isLeapYearCheckSink(n)
313313
}
314314

315-
// Block flow out of an operation source to get the "closest" operation to the sink
315+
/** Block flow out of an operation source to get the "closest" operation to the sink */
316316
predicate isBarrierIn(DataFlow::Node n) { isSource(n) }
317317

318318
predicate isBarrierOut(DataFlow::Node n) { isSink(n) }
319+
319320
// DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
320321
}
321322

@@ -358,6 +359,7 @@ module YearFieldAccessToLeapYearCheckConfig implements DataFlow::ConfigSig {
358359
// DataFlow::FlowFeature getAFeature() {
359360
// result instanceof DataFlow::FeatureEqualSourceSinkCallContext
360361
// }
362+
361363
/**
362364
* Enforcing the check must occur in the same call context as the source,
363365
* i.e., do not return from the source function and check in a caller.
@@ -389,6 +391,9 @@ predicate isUsedInFeb29Check(YearFieldAccess fa) {
389391
)
390392
}
391393

394+
/**
395+
* An expression which checks the value of a Month field `a->month == 1`.
396+
*/
392397
class MonthEqualityCheck extends EqualityOperation {
393398
MonthEqualityCheck() { this.getAnOperand() instanceof MonthFieldAccess }
394399

@@ -405,6 +410,9 @@ class MonthEqualityCheck extends EqualityOperation {
405410

406411
class MonthEqualityCheckGuard extends GuardCondition instanceof MonthEqualityCheck { }
407412

413+
/**
414+
* Verifies if the expression is guarded by a check on the Month property of a date struct, that is NOT February.
415+
*/
408416
bindingset[e]
409417
pragma[inline_late]
410418
predicate isControlledByMonthEqualityCheckNonFebruary(Expr e) {

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,8 @@ void fn_year_set_through_out_arg(){
11151115
}
11161116

11171117

1118-
/* void
1118+
/* TODO: don't alert on simple copies from another struct where all three {year,month,day} are copied
1119+
void
11191120
GetEpochTime(struct pg_tm *tm)
11201121
{
11211122
struct pg_tm *t0;
@@ -1147,4 +1148,22 @@ fp_guarded_by_month(struct pg_tm *tm){
11471148
--tm->tm_year; // Negative Test Case
11481149
if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
11491150
++tm->tm_year; // Negative Test Case
1151+
}
1152+
1153+
typedef unsigned short CSHORT;
1154+
1155+
typedef struct _TIME_FIELDS {
1156+
CSHORT Year;
1157+
CSHORT Month;
1158+
CSHORT Day;
1159+
CSHORT Hour;
1160+
CSHORT Minute;
1161+
CSHORT Second;
1162+
CSHORT Milliseconds;
1163+
CSHORT Weekday;
1164+
} TIME_FIELDS, *PTIME_FIELDS;
1165+
1166+
void
1167+
tp_ptime(PTIME_FIELDS ptm){
1168+
ptm->Year = ptm->Year - 1; // Positive Test Case
11501169
}

0 commit comments

Comments
 (0)