1212import cpp
1313import LeapYear
1414import semmle.code.cpp.controlflow.IRGuards
15+ import semmle.code.cpp.ir.IR
1516import semmle.code.cpp.dataflow.new.TaintTracking
1617import 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+ */
120123class IgnorableCharLiteralArithmetic extends IgnorableOperation {
121124 IgnorableCharLiteralArithmetic ( ) {
122125 exists ( this .( BinaryArithmeticOperation ) .getAnOperand ( ) .( TextLiteral ) .getValue ( ) )
@@ -136,32 +139,33 @@ class IgnorableCharLiteralArithmetic extends IgnorableOperation {
136139bindingset [ c]
137140predicate 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+ */
194201class 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
780787import 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+
782802from OperationToYearAssignmentFlow:: PathNode src , OperationToYearAssignmentFlow:: PathNode sink
783803where
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?
810827select sink , src , sink ,
0 commit comments