Skip to content

Commit c88b877

Browse files
committed
Merge branch 'jb1/ap1-maturity' of https://github.com/microsoft/codeql into jb1/ap1-maturity
2 parents 1f63bee + c7553d5 commit c88b877

File tree

1 file changed

+55
-38
lines changed

1 file changed

+55
-38
lines changed

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

Lines changed: 55 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import cpp
1313
import LeapYear
1414
import semmle.code.cpp.controlflow.IRGuards
15+
import semmle.code.cpp.ir.IR
1516
import semmle.code.cpp.dataflow.new.TaintTracking
1617
import semmle.code.cpp.commons.DateTime
1718

@@ -117,6 +118,8 @@ class IgnorableExpr48Mapping extends IgnorableOperation {
117118
}
118119
}
119120

121+
/** A binary or arithemtic operation whereby one of the components is textual or a string.
122+
*/
120123
class IgnorableCharLiteralArithmetic extends IgnorableOperation {
121124
IgnorableCharLiteralArithmetic() {
122125
exists(this.(BinaryArithmeticOperation).getAnOperand().(TextLiteral).getValue())
@@ -136,32 +139,33 @@ class IgnorableCharLiteralArithmetic extends IgnorableOperation {
136139
bindingset[c]
137140
predicate isLikelyConversionConstant(int c) {
138141
exists(int i | i = c.abs() |
139-
//| i >= 100)
140-
i = 146097 or // days in 400-year Gregorian cycle
141-
i = 36524 or // days in 100-year Gregorian subcycle
142-
i = 1461 or // days in 4-year cycle (incl. 1 leap)
143-
i = 32044 or // Fliegel–van Flandern JDN epoch shift
144-
i = 1721425 or // JDN of 0001‑01‑01 (Gregorian)
145-
i = 1721119 or // alt epoch offset
146-
i = 2400000 or // MJD → JDN conversion
147-
i = 2400001 or // alt MJD → JDN conversion
148-
i = 2141 or // fixed‑point month/day extraction
149-
i = 65536 or // observed in some conversions
150-
i = 7834 or // observed in some conversions
151-
i = 256 or // observed in some conversions
152-
i = 292275056 or // qdatetime.h Qt Core year range first year constant
153-
i = 292278994 or // qdatetime.h Qt Core year range last year constant
154-
i = 1601 or // Windows FILETIME epoch start year
155-
i = 1970 or // Unix epoch start year
156-
i = 70 or // Unix epoch start year short form
157-
i = 1899 or // Observed in uses with 1900 to address off by one scenarios
158-
i = 1900 or // Used when converting a 2 digit year
159-
i = 2000 or // Used when converting a 2 digit year
160-
i = 1400 or // Hijri base year, used when converting a 2 digit year
161-
i = 1980 or // FAT filesystem epoch start year
162-
i = 227013 or // constant observed for Hirji year conversion, and Hirji years are not applicable for gregorian leap year
163-
i = 10631 or // constant observed for Hirji year conversion, and Hirji years are not applicable for gregorian leap year
164-
i = 0
142+
i = [
143+
146097, // days in 400-year Gregorian cycle
144+
36524, // days in 100-year Gregorian subcycle
145+
1461, // days in 4-year cycle (incl. 1 leap)
146+
32044, // Fliegel–van Flandern JDN epoch shift
147+
1721425, // JDN of 0001‑01‑01 (Gregorian)
148+
1721119, // alt epoch offset
149+
2400000, // MJD → JDN conversion
150+
2400001, // alt MJD → JDN conversion
151+
2141, // fixed‑point month/day extraction
152+
65536, // observed in some conversions
153+
7834, // observed in some conversions
154+
256, // observed in some conversions
155+
292275056, // qdatetime.h Qt Core year range first year constant
156+
292278994, // qdatetime.h Qt Core year range last year constant
157+
1601, // Windows FILETIME epoch start year
158+
1970, // Unix epoch start year
159+
70, // Unix epoch start year short form
160+
1899, // Observed in uses with 1900 to address off by one scenarios
161+
1900, // Used when converting a 2 digit year
162+
2000, // Used when converting a 2 digit year
163+
1400, // Hijri base year, used when converting a 2 digit year
164+
1980, // FAT filesystem epoch start year
165+
227013, // constant observed for Hirji year conversion, and Hirji years are not applicable for gregorian leap year
166+
10631, // constant observed for Hirji year conversion, and Hirji years are not applicable for gregorian leap year
167+
0
168+
]
165169
)
166170
}
167171

@@ -191,6 +195,9 @@ class IgnorableUnaryMinus extends IgnorableOperation {
191195
}
192196
}
193197

198+
/**
199+
* An argument to a function is ignorable if the function that is called is an ignored function
200+
*/
194201
class OperationAsArgToIgnorableFunction extends IgnorableOperation {
195202
OperationAsArgToIgnorableFunction() {
196203
exists(Call c |
@@ -494,7 +501,7 @@ predicate isControlledByMonthEqualityCheckNonFebruary(Expr e) {
494501
}
495502

496503
/**
497-
* From from a year field access to a time conversion function
504+
* Flow from a year field access to a time conversion function
498505
* that auto converts feb29 in non-leap year, or through a conversion function that doesn't
499506
* auto convert to a sanity check guard of the result for error conditions.
500507
*/
@@ -779,6 +786,19 @@ module CandidateConstantToDayOrMonthAssignmentFlow =
779786

780787
import OperationToYearAssignmentFlow::PathGraph
781788

789+
/**
790+
* The value that the assignment resolves to doesn't represent February,
791+
* and/or if it represents a day, is a 'safe' day (meaning the 27th or prior).
792+
*/
793+
bindingset[dayOrMonthValSrcExpr]
794+
predicate isSafeValueForAssignmentOfMonthOrDayValue(Assignment a, Expr dayOrMonthValSrcExpr){
795+
a.getLValue() instanceof MonthFieldAccess and
796+
dayOrMonthValSrcExpr.getValue().toInt() != 2
797+
or
798+
a.getLValue() instanceof DayFieldAccess and
799+
dayOrMonthValSrcExpr.getValue().toInt() <= 27
800+
}
801+
782802
from OperationToYearAssignmentFlow::PathNode src, OperationToYearAssignmentFlow::PathNode sink
783803
where
784804
OperationToYearAssignmentFlow::flowPath(src, sink) and
@@ -791,20 +811,17 @@ where
791811
not exists(DataFlow::Node dayOrMonthValSrc, DataFlow::Node dayOrMonthValSink, Assignment a |
792812
CandidateConstantToDayOrMonthAssignmentFlow::flow(dayOrMonthValSrc, dayOrMonthValSink) and
793813
a.getRValue() = dayOrMonthValSink.asExpr() and
794-
(
814+
dayOrMonthValSink.getBasicBlock() = sink.getNode().getBasicBlock() and
815+
exists(IRBlock dayOrMonthValBB |
816+
dayOrMonthValBB = dayOrMonthValSrc.getBasicBlock() and
795817
// The source of the day is set in the same block as the source for the year
796818
// or the source for the day is set in the same block as the sink for the year
797-
dayOrMonthValSrc.getBasicBlock() = src.getNode().getBasicBlock() or
798-
dayOrMonthValSrc.getBasicBlock() = sink.getNode().getBasicBlock()
819+
dayOrMonthValBB in [
820+
src.getNode().getBasicBlock(),
821+
sink.getNode().getBasicBlock()
822+
]
799823
) and
800-
dayOrMonthValSink.getBasicBlock() = sink.getNode().getBasicBlock() and
801-
(
802-
a.getLValue() instanceof MonthFieldAccess and
803-
dayOrMonthValSrc.asExpr().getValue().toInt() != 2
804-
or
805-
a.getLValue() instanceof DayFieldAccess and
806-
dayOrMonthValSrc.asExpr().getValue().toInt() <= 27
807-
)
824+
isSafeValueForAssignmentOfMonthOrDayValue(a, dayOrMonthValSrc.asExpr())
808825
)
809826
// TODO: all days to sink are safe?
810827
select sink, src, sink,

0 commit comments

Comments
 (0)