Skip to content

Commit b013012

Browse files
committed
Misc. updates. Specifically including how constant values are used to ignore certain opeartions. Also added an ignorable function class to be used to ignore operation sources.
1 parent 2f1a850 commit b013012

1 file changed

Lines changed: 44 additions & 36 deletions

File tree

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

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ import cpp
1313
import LeapYear
1414
import semmle.code.cpp.controlflow.IRGuards
1515

16+
/**
17+
* Functions whose operations should never be considered a
18+
* source of a dangerous leap year operation.
19+
*/
20+
class IgnorableFunction extends Function {
21+
IgnorableFunction() {
22+
// Helper utility in postgres with string time conversions
23+
this.getName() = "DecodeISO8601Interval"
24+
}
25+
}
26+
1627
/**
1728
* The set of expressions which are ignorable; either because they seem to not be part of a year mutation,
1829
* or because they seem to be a conversion pattern of mapping date scalars.
@@ -22,14 +33,15 @@ abstract class IgnorableOperation extends Expr { }
2233
class IgnorableExprRem extends IgnorableOperation instanceof RemExpr { }
2334

2435
/**
25-
* Anything involving a sub expression with char literal 48, ignore as a likely string conversion
36+
* Anything involving an operation with 10, 100, 1000, 10000 is often a sign of conversion
37+
* or atoi.
2638
*/
2739
class IgnorableExpr10MulipleComponent extends IgnorableOperation {
2840
IgnorableExpr10MulipleComponent() {
29-
this.(MulExpr).getAnOperand().getValue().toInt() in [10, 100, 100]
41+
this.(Operation).getAnOperand().getValue().toInt() in [10, 100, 1000, 10000]
3042
or
31-
exists(AssignMulExpr a | a.getRValue() = this |
32-
a.getRValue().getValue().toInt() in [10, 100, 100]
43+
exists(AssignOperation a | a.getRValue() = this |
44+
a.getRValue().getValue().toInt() in [10, 100, 1000, 10000]
3345
)
3446
}
3547
}
@@ -56,28 +68,29 @@ class IgnorableCharLiteralArithmetic extends IgnorableOperation {
5668
}
5769
}
5870

59-
/*
60-
* linux time conversions expect the year to start from 1900, so subtracting or
61-
* adding 1900 or anything involving 1900 as a generalization is probably
62-
* a conversion that is ignorable
71+
/**
72+
* Constants often used in date conversions (from one date data type to another)
6373
*/
64-
74+
bindingset[c]
6575
predicate isLikelyConversionConstant(int c) {
66-
c = 146097 or // days in 400-year Gregorian cycle
67-
c = 36524 or // days in 100-year Gregorian subcycle
68-
c = 1461 or // days in 4-year cycle (incl. 1 leap)
69-
c = 32044 or // Fliegel–van Flandern JDN epoch shift
70-
c = 1721425 or // JDN of 0001‑01‑01 (Gregorian)
71-
c = 1721119 or // alt epoch offset
72-
c = 2400000 or // MJD → JDN conversion
73-
c = 2400001 or
74-
c = 2400000 or
75-
c = 2141 or // fixed‑point month/day extraction
76-
c = 2000 or
77-
c = 65536 or
78-
c = 7834 or
79-
c = 256 or
80-
c = 1900 // struct tm base‑year offset; harmless
76+
exists(int i | i = c.abs() | i >= 100)
77+
// c = 146097 or // days in 400-year Gregorian cycle
78+
// c = 36524 or // days in 100-year Gregorian subcycle
79+
// c = 1461 or // days in 4-year cycle (incl. 1 leap)
80+
// c = 32044 or // Fliegel–van Flandern JDN epoch shift
81+
// c = 1721425 or // JDN of 0001‑01‑01 (Gregorian)
82+
// c = 1721119 or // alt epoch offset
83+
// c = 2400000 or // MJD → JDN conversion
84+
// c = 2400001 or // alt MJD → JDN conversion
85+
// c = 2141 or // fixed‑point month/day extraction
86+
// c = 2000 or // observed in some conversions
87+
// c = 65536 or // observed in some conversions
88+
// c = 7834 or // observed in some conversions
89+
// c = 256 or // observed in some conversions
90+
// c = 1900 or // struct tm base‑year offset; harmless
91+
// c = 1899 or // Observed in uses with 1900 to address off by one scenarios
92+
// c = 292275056 or // qdatetime.h Qt Core year range first year constant
93+
// c = 292278994 // qdatetime.h Qt Core year range last year constant
8194
}
8295

8396
/**
@@ -133,6 +146,7 @@ class IgnorablePointerOrCharArithmetic extends IgnorableOperation {
133146
*/
134147
predicate isOperationSourceCandidate(Expr e) {
135148
not e instanceof IgnorableOperation and
149+
not e.getEnclosingFunction() instanceof IgnorableFunction and
136150
(
137151
e instanceof SubExpr
138152
or
@@ -361,31 +375,25 @@ predicate isUsedInFeb29Check(YearFieldAccess fa) {
361375
)
362376
}
363377

364-
class MonthEqualityCheck extends EqualityOperation{
365-
MonthEqualityCheck(){
366-
this.getAnOperand() instanceof MonthFieldAccess
367-
}
378+
class MonthEqualityCheck extends EqualityOperation {
379+
MonthEqualityCheck() { this.getAnOperand() instanceof MonthFieldAccess }
368380

369-
Expr getExprCompared(){
381+
Expr getExprCompared() {
370382
exists(Expr e |
371383
e = this.getAnOperand() and
372384
not e instanceof MonthFieldAccess and
373385
result = e
374386
)
375387
}
376388

377-
MonthFieldAccess getMonthFieldAccess(){
378-
result = this.getAnOperand()
379-
}
389+
MonthFieldAccess getMonthFieldAccess() { result = this.getAnOperand() }
380390
}
381391

382-
class MonthEqualityCheckGuard extends GuardCondition instanceof MonthEqualityCheck{
383-
MonthEqualityCheckGuard(){ any() }
384-
}
392+
class MonthEqualityCheckGuard extends GuardCondition instanceof MonthEqualityCheck { }
385393

386394
bindingset[e]
387395
pragma[inline_late]
388-
predicate isControlledByMonthEqualityCheckNonFebruary(Expr e){
396+
predicate isControlledByMonthEqualityCheckNonFebruary(Expr e) {
389397
exists(MonthEqualityCheckGuard monthGuard |
390398
monthGuard.controls(e.getBasicBlock(), true) and
391399
not monthGuard.(MonthEqualityCheck).getExprCompared().getValueText() = "2"

0 commit comments

Comments
 (0)