Skip to content

Commit 0419d28

Browse files
committed
XXE: overapproximate feature flag values for & and | operators
1 parent 089f9d8 commit 0419d28

File tree

1 file changed

+13
-30
lines changed

1 file changed

+13
-30
lines changed

ql/lib/codeql/ruby/frameworks/XmlParsing.qll

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ private API::Node parseOptionsModule() {
9898
result = API::getTopLevelMember("XML").getMember("Options")
9999
}
100100

101+
private predicate bitWiseAndOr(CfgNodes::ExprNodes::OperationCfgNode operation) {
102+
operation.getExpr() instanceof BitwiseAndExpr or
103+
operation.getExpr() instanceof AssignBitwiseAndExpr or
104+
operation.getExpr() instanceof BitwiseOrExpr or
105+
operation.getExpr() instanceof AssignBitwiseOrExpr
106+
}
107+
101108
private DataFlow::LocalSourceNode trackFeature(Feature f, boolean enable, TypeTracker t) {
102109
t.start() and
103110
(
@@ -112,38 +119,14 @@ private DataFlow::LocalSourceNode trackFeature(Feature f, boolean enable, TypeTr
112119
enable = true and
113120
result = parseOptionsModule().getMember(f.getConstantName()).getAUse()
114121
or
115-
// If a feature is enabled in any of the operands of the `|` and `|=` operators
116-
// then the feature is also enabled in the result of the operators.
117-
exists(CfgNodes::ExprNodes::OperationCfgNode operation |
118-
operation = result.asExpr().(CfgNodes::ExprNodes::OperationCfgNode) and
119-
(
120-
operation.getExpr() instanceof BitwiseOrExpr or
121-
operation.getExpr() instanceof AssignBitwiseOrExpr
122-
)
123-
|
124-
enable = true and
125-
operation.getAnOperand() = trackFeature(f, true).asExpr()
126-
or
127-
enable = false and
128-
operation.getAnOperand() = trackFeature(f, false).asExpr() and
129-
forall(DataFlow::Node n | n.asExpr() = operation.getAnOperand() | n != trackFeature(f, true))
130-
)
131-
or
132-
// If a feature is disabled in any of the operands of the `&` and `&=` operators
133-
// then the feature is also disabled in the result of the operators.
122+
// Treat `&`, `&=`, `|` and `|=` operators as if they preserve the on/off states
123+
// of their operands. This is an overapproximation but likely to work well in practice
124+
// because it makes little sense to explicitly set a feature to both `on` and `off` in the
125+
// same code.
134126
exists(CfgNodes::ExprNodes::OperationCfgNode operation |
127+
bitWiseAndOr(operation) and
135128
operation = result.asExpr().(CfgNodes::ExprNodes::OperationCfgNode) and
136-
(
137-
operation.getExpr() instanceof BitwiseAndExpr or
138-
operation.getExpr() instanceof AssignBitwiseAndExpr
139-
)
140-
|
141-
enable = false and
142-
operation.getAnOperand() = trackFeature(f, false).asExpr()
143-
or
144-
enable = true and
145-
operation.getAnOperand() = trackFeature(f, true).asExpr() and
146-
forall(DataFlow::Node n | n.asExpr() = operation.getAnOperand() | n != trackFeature(f, false))
129+
operation.getAnOperand() = trackFeature(f, enable).asExpr()
147130
)
148131
or
149132
// The complement operator toggles a feature from enabled to disabled and vice-versa

0 commit comments

Comments
 (0)