1313
1414import cpp
1515import semmle.code.cpp.security.SensitiveExprs
16- import semmle.code.cpp.security.TaintTracking
17- import TaintedWithPath
18-
19- class UserInputIsSensitiveExpr extends SecurityOptions {
20- override predicate isUserInput ( Expr expr , string cause ) {
21- expr instanceof SensitiveExpr and cause = "sensitive information"
22- }
23- }
16+ import semmle.code.cpp.dataflow.TaintTracking
17+ import DataFlow:: PathGraph
2418
2519class SqliteFunctionCall extends FunctionCall {
2620 SqliteFunctionCall ( ) { this .getTarget ( ) .getName ( ) .matches ( "sqlite%" ) }
@@ -34,25 +28,51 @@ predicate sqlite_encryption_used() {
3428 any ( FunctionCall fc ) .getTarget ( ) .getName ( ) .matches ( "sqlite%\\_key\\_%" )
3529}
3630
37- class Configuration extends TaintTrackingConfiguration {
38- override predicate isSource ( Expr source ) {
39- super .isSource ( source ) and source instanceof SensitiveExpr
31+ /**
32+ * Gets a field of the class `c`, or of another class contained in `c`.
33+ */
34+ Field getRecField ( Class c ) {
35+ result = c .getAField ( ) or
36+ result = getRecField ( c .getAField ( ) .getUnspecifiedType ( ) .stripType ( ) )
37+ }
38+
39+ /**
40+ * A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink.
41+ */
42+ class FromSensitiveConfiguration extends TaintTracking:: Configuration {
43+ FromSensitiveConfiguration ( ) { this = "FromSensitiveConfiguration" }
44+
45+ override predicate isSource ( DataFlow:: Node source ) { source .asExpr ( ) instanceof SensitiveExpr }
46+
47+ override predicate isSink ( DataFlow:: Node sink ) {
48+ any ( SqliteFunctionCall c ) .getASource ( ) = sink .asExpr ( ) and
49+ not sqlite_encryption_used ( )
50+ }
51+
52+ override predicate isSanitizer ( DataFlow:: Node node ) {
53+ node .asExpr ( ) .getUnspecifiedType ( ) instanceof IntegralType
4054 }
4155
42- override predicate isSink ( Element taintedArg ) {
43- exists ( SqliteFunctionCall sqliteCall |
44- taintedArg = sqliteCall .getASource ( ) and
45- not sqlite_encryption_used ( )
56+ override predicate allowImplicitRead ( DataFlow:: Node node , DataFlow:: ContentSet content ) {
57+ // flow out from fields at the sink (only).
58+ this .isSink ( node ) and
59+ // constrain `content` to a field inside the node.
60+ exists ( Class c |
61+ node .asExpr ( ) .getUnspecifiedType ( ) .stripType ( ) = c and
62+ content .( DataFlow:: FieldContent ) .getField ( ) = getRecField ( c )
4663 )
64+ or
65+ // any default implicit reads
66+ super .allowImplicitRead ( node , content )
4767 }
4868}
4969
5070from
51- SensitiveExpr taintSource , Expr taintedArg , SqliteFunctionCall sqliteCall , PathNode sourceNode ,
52- PathNode sinkNode
71+ FromSensitiveConfiguration config , SensitiveExpr sensitive , DataFlow :: PathNode source ,
72+ DataFlow :: PathNode sink , SqliteFunctionCall sqliteCall
5373where
54- taintedWithPath ( taintSource , taintedArg , sourceNode , sinkNode ) and
55- taintedArg = sqliteCall . getASource ( )
56- select sqliteCall , sourceNode , sinkNode ,
57- "This SQLite call may store $@ in a non-encrypted SQLite database" , taintSource ,
58- "sensitive information"
74+ config . hasFlowPath ( source , sink ) and
75+ source . getNode ( ) . asExpr ( ) = sensitive and
76+ sqliteCall . getASource ( ) = sink . getNode ( ) . asExpr ( )
77+ select sqliteCall , source , sink , "This SQLite call may store $@ in a non-encrypted SQLite database" ,
78+ sensitive , "sensitive information"
0 commit comments