diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index d3800d1eea2..26432311d0c 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -28,6 +28,14 @@ predicate sqlite_encryption_used() { any(FunctionCall fc).getTarget().getName().matches("sqlite%\\_key\\_%") } +/** + * Gets a field of the class `c`, or of another class contained in `c`. + */ +Field getRecField(Class c) { + result = c.getAField() or + result = getRecField(c.getAField().getUnspecifiedType().stripType()) +} + /** * A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink. */ @@ -44,6 +52,19 @@ class FromSensitiveConfiguration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } + + override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) { + // flow out from fields at the sink (only). + isSink(node) and + // constrain `content` to a field inside the node. + exists(Class c | + node.asExpr().getUnspecifiedType().stripType() = c and + content.(DataFlow::FieldContent).getField() = getRecField(c) + ) + or + // any default implicit reads + super.allowImplicitRead(node, content) + } } from