@@ -45,18 +45,52 @@ class IgnorableExpr48Mapping extends IgnorableOperation {
4545 }
4646}
4747
48+ class IgnorableCharLiteralArithmetic extends IgnorableOperation {
49+ IgnorableCharLiteralArithmetic ( ) {
50+ exists ( this .( BinaryArithmeticOperation ) .getAnOperand ( ) .( TextLiteral ) .getValue ( ) )
51+ or
52+ exists ( AssignArithmeticOperation e | e .getRValue ( ) = this |
53+ exists ( this .( TextLiteral ) .getValue ( ) )
54+ )
55+ }
56+ }
57+
4858/*
4959 * linux time conversions expect the year to start from 1900, so subtracting or
5060 * adding 1900 or anything involving 1900 as a generalization is probably
5161 * a conversion that is ignorable
5262 */
5363
54- class IgnorableExprExpr1900Mapping extends IgnorableOperation {
55- IgnorableExprExpr1900Mapping ( ) {
56- this .( Operation ) .getAnOperand ( ) .( Literal ) .getValue ( ) .toInt ( ) = 1900
57- or
58- exists ( AssignArithmeticOperation a | this = a .getRValue ( ) |
59- a .getRValue ( ) .( Literal ) .getValue ( ) .toInt ( ) = 1900
64+ predicate isLikelyConversionConstant ( int c ) {
65+ c = 146097 or // days in 400-year Gregorian cycle
66+ c = 36524 or // days in 100-year Gregorian subcycle
67+ c = 1461 or // days in 4-year cycle (incl. 1 leap)
68+ c = 32044 or // Fliegel–van Flandern JDN epoch shift
69+ c = 1721425 or // JDN of 0001‑01‑01 (Gregorian)
70+ c = 1721119 or // alt epoch offset
71+ c = 2400000 or // MJD → JDN conversion
72+ c = 2400001 or
73+ c = 2400000 or
74+ c = 2141 or // fixed‑point month/day extraction
75+ c = 65536 or
76+ c = 7834 or
77+ c = 256 or
78+ c = 1900 // struct tm base‑year offset; harmless
79+ }
80+
81+ /**
82+ * Some constants indicate conversion that are ignorable, e.g.,
83+ * julian to gregorian conversion or conversions from linux time structs
84+ * that start at 1900, etc.
85+ */
86+ class IgnorableConstantArithmetic extends IgnorableOperation {
87+ IgnorableConstantArithmetic ( ) {
88+ exists ( int i | isLikelyConversionConstant ( i ) |
89+ this .( Operation ) .getAnOperand ( ) .( Literal ) .getValue ( ) .toInt ( ) = i
90+ or
91+ exists ( AssignArithmeticOperation a | this = a .getRValue ( ) |
92+ a .getRValue ( ) .( Literal ) .getValue ( ) .toInt ( ) = i
93+ )
6094 )
6195 }
6296}
@@ -69,6 +103,26 @@ class IgnorableUnaryBitwiseOperation extends IgnorableOperation instanceof Unary
69103class IgnorableAssignmentBitwiseOperation extends IgnorableOperation instanceof AssignBitwiseOperation
70104{ }
71105
106+ /**
107+ * Any arithmetic operation where one of the operands is a pointer or char type, ignore it
108+ */
109+ class IgnorablePointerOrCharArithmetic extends IgnorableOperation {
110+ IgnorablePointerOrCharArithmetic ( ) {
111+ this instanceof BinaryArithmeticOperation and
112+ (
113+ this .( BinaryArithmeticOperation ) .getAnOperand ( ) .getUnspecifiedType ( ) instanceof PointerType
114+ or
115+ this .( BinaryArithmeticOperation ) .getAnOperand ( ) .getUnspecifiedType ( ) instanceof CharType
116+ )
117+ or
118+ exists ( AssignArithmeticOperation a | a .getRValue ( ) = this |
119+ a .getAnOperand ( ) .getUnspecifiedType ( ) instanceof PointerType
120+ or
121+ a .getAnOperand ( ) .getUnspecifiedType ( ) instanceof CharType
122+ )
123+ }
124+ }
125+
72126/**
73127 * An expression that is a candidate source for an dataflow configuration for an Operation that could flow to a Year field.
74128 */
@@ -147,6 +201,27 @@ class OperationSource extends Expr {
147201 }
148202}
149203
204+ class YearFieldAssignmentNode extends DataFlow:: Node {
205+ YearFieldAssignmentNode ( ) {
206+ this .asExpr ( ) instanceof YearFieldAssignment
207+ or
208+ this .asDefiningArgument ( ) instanceof YearFieldAccess
209+ or
210+ // TODO: is there a better way to do this?
211+ // i.e., without having to be cognizant of the addressof
212+ // occurring, especially if this occurs on a dataflow
213+ exists ( AddressOfExpr aoe |
214+ aoe = this .asDefiningArgument ( ) and
215+ aoe .getOperand ( ) instanceof YearFieldAccess
216+ )
217+ }
218+
219+ YearFieldAccess getYearFieldAccess ( ) {
220+ result = this .asDefiningArgument ( ) or
221+ result = this .asExpr ( ) .( YearFieldAssignment ) .getYearFieldAccess ( )
222+ }
223+ }
224+
150225/**
151226 * An assignment to a year field, which will be a sink
152227 * NOTE: could not make this abstract, it was binding to all expressions
@@ -190,15 +265,20 @@ class YearFieldAssignmentUnary extends YearFieldAssignment instanceof CrementOpe
190265module OperationToYearAssignmentConfig implements DataFlow:: ConfigSig {
191266 predicate isSource ( DataFlow:: Node n ) { n .asExpr ( ) instanceof OperationSource }
192267
193- predicate isSink ( DataFlow:: Node n ) { n . asExpr ( ) instanceof YearFieldAssignment }
268+ predicate isSink ( DataFlow:: Node n ) { n instanceof YearFieldAssignmentNode }
194269
195270 predicate isBarrier ( DataFlow:: Node n ) {
196271 exists ( ArrayExpr arr | arr .getArrayOffset ( ) = n .asExpr ( ) )
197272 or
198273 n .asExpr ( ) .getUnspecifiedType ( ) instanceof PointerType
199274 or
275+ n .asExpr ( ) .getUnspecifiedType ( ) instanceof CharType
276+ or
200277 n .asExpr ( ) instanceof IgnorableOperation
201278 }
279+
280+ predicate isBarrierOut ( DataFlow:: Node n ) { isSink ( n ) }
281+ // DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
202282}
203283
204284module OperationToYearAssignmentFlow = TaintTracking:: Global< OperationToYearAssignmentConfig > ;
@@ -240,7 +320,7 @@ predicate isRootOperationSource(OperationSource e) {
240320 * A flow configuration from a Year field access to some Leap year check or guard
241321 */
242322module YearFieldAccessToLeapYearCheckConfig implements DataFlow:: ConfigSig {
243- predicate isSource ( DataFlow:: Node source ) { source . asExpr ( ) instanceof YearFieldAccess }
323+ predicate isSource ( DataFlow:: Node source ) { source instanceof YearFieldAssignmentNode }
244324
245325 predicate isSink ( DataFlow:: Node sink ) {
246326 // Local leap year check
@@ -261,14 +341,19 @@ module YearFieldAccessToLeapYearCheckConfig implements DataFlow::ConfigSig {
261341
262342 predicate isAdditionalFlowStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
263343 // flow from a YearFieldAccess to the qualifier
264- node1 .asExpr ( ) instanceof YearFieldAccess and
265344 node2 .asExpr ( ) = node1 .asExpr ( ) .( YearFieldAccess ) .getQualifier ( )
266345 }
346+
267347 // Use this to make the sink for leap year check intra-proc only
268348 // i.e., the sink must be in the same scope (function) as the source.
269349 // DataFlow::FlowFeature getAFeature() {
270350 // result instanceof DataFlow::FeatureEqualSourceSinkCallContext
271351 // }
352+ /**
353+ * Enforcing the check must occur in the same call context as the source,
354+ * i.e., do not return from the source function and check in a caller.
355+ */
356+ DataFlow:: FlowFeature getAFeature ( ) { result instanceof DataFlow:: FeatureHasSourceCallContext }
272357}
273358
274359module YearFieldAccessToLeapYearCheckFlow =
@@ -287,7 +372,7 @@ predicate isYearModifiedWithCheck(YearFieldAccess fa) {
287372/**
288373 * If there is a flow from a date struct year field access/assignment to a Feb 29 check
289374 */
290- predicate isUsedInFeb29Check ( YearFieldAccess fa ) {
375+ predicate isUsedInFeb29Check ( YearFieldAccess fa ) {
291376 exists ( DateFebruary29Check check |
292377 DataFlow:: localExprFlow ( fa .getQualifier ( ) , check .getDateQualifier ( ) )
293378 or
0 commit comments