So I run this query to the next source code:
\nusing System;\n\nnamespace example2\n{\n\tpublic class Program\n\t{\n\t\tpublic static void Main(string[] args)\n\t\t{\n\t\t\tint levels = 5;\n\t\t\tTreeNode root = new TreeNode(levels);\n\t\t\tint result = root.addTree(); // *\n\t\t\tvar slicingVariable1 = result; // *\n\t\t\tSystem.Console.WriteLine(\"Done!\");\n\t\t}\n\t}\n\n\tinternal class TreeNode\n\t{\n\t\tprivate int value = 0;\n\t\tprivate TreeNode left = null;\n\t\tprivate TreeNode right = null;\n\n\t\tinternal TreeNode(int levels)\n\t\t{\n\t\t\tvalue = 1;\n\t\t\tif (levels <= 1)\n\t\t\t{\n\t\t\t\tif (levels <= 0)\n\t\t\t\t\tthrow new System.Exception(\"Number of levels must be positive no.\");\n\t\t\t\tleft = null;\n\t\t\t\tright = null;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tleft = new TreeNode(levels - 1);\n\t\t\t\tright = new TreeNode(levels - 1);\n\t\t\t}\n\t\t}\n\n\t\tinternal virtual int addTree()\n\t\t{\n\t\t\tint total = value; // *\n\t\t\tif (left != null) // *\n\t\t\t\ttotal += left.addTree(); // *\n\t\t\tif (right != null) // *\n\t\t\t\ttotal += right.addTree(); // *\n\t\t\treturn total; // *\n\t\t}\n\t}\n}After running the query I collect every line in every path, and I get these lines: {11, 12, 42, 43, 44, 45, 46, 47} (marked with // *).
\nIn this case, I expected more lines.
For example,
\nIf I run the same query, recursively (with an external program) adding previous lines as new targets
\n(performing one query for line 12, but also for line 42, 43, 44, 45, .. etc.) I get these lines:
\n{9, 10, 11, 12, 19, 20, 21, 23, 25, 26, 28, 30, 31, 35, 36, 40, 42, 43, 44, 45, 46, 47}.
\nThis is what I really want, a kind of closure of data dependencies over control dependencies.
\nI thought that I can reach that using isAdditionalTaintStep but I see that is not the same,
Any suggestions?
\nI want to avoid performing several queries for getting the final \"static slice\".
\nThanks everybody in advance,
\nRegards.
Hi @asoifer,
\nI'm sorry to say that our data-flow analysis has a specific limitation that disallows defining sources/sinks of a data-flow configuration based on paths found with that configuration. For the security queries we are writing, that has not been a big problem so far. In some cases, we've had to have two layers of data-flow, which we have managed by just introducing a separate copy of the whole data-flow analysis, and then each part can sit in it's own \"layer\". In this way we can define sources/sinks in one layer based on the results form the other layer.
\nFor C# this would be DataFlow, DataFlow2, DataFlow3, DataFlow4, DataFlow5. And as an example of actually combining such two layers, I will highlight path injection query in Python.
\nBut I think this would at best be a band-aid for the specific problem you are trying to solve, where I would assume you want to reach a fixed point, and not just do a few iterations at most.
\nAlso sorry for the very late reply. This question somehow slipped off the radar 😐
","upvoteCount":2,"url":"https://github.com/github/codeql/discussions/6239#discussioncomment-1355934"}}}-
|
Dear everybody, CodeQL Query: /**
* @name Static slicing
* @description An attempt to perform a static slice
* @id cs/static-slicing
* @problem.severity error
* @precision very-high
* @tags security
* @kind path-problem
*/
import csharp
import semmle.code.csharp.security.dataflow.flowsources.Remote
import semmle.code.csharp.commons.Util
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
import semmle.code.csharp.controlflow.Guards
import semmle.code.csharp.controlflow.BasicBlocks
import semmle.code.csharp.ExprOrStmtParent
class TaintTrackingConfiguration extends TaintTracking::Configuration {
TaintTrackingConfiguration() { this = "CustomSlice" }
override predicate isSource(DataFlow::Node source) {
any()
}
override predicate isSink(DataFlow::Node sink) {
sink.asExpr().getLocation().getFile().getAbsolutePath().indexOf("Program.cs") > 0
and sink.asExpr().getLocation().getStartLine() = 12 // Target of the slicer (catching the variable result)
}
// An attempt to add the control dependencies
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
exists (Guard g, BasicBlock b, AbstractValue v |
g.getAControlFlowNode() = pred.getControlFlowNode() and
b.getANode() = succ.getControlFlowNode() and
g.controlsBasicBlock(b, v)
)
}
}
from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink
where c.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Msg", source.getNode(), "Msg"So I run this query to the next source code: using System;
namespace example2
{
public class Program
{
public static void Main(string[] args)
{
int levels = 5;
TreeNode root = new TreeNode(levels);
int result = root.addTree(); // *
var slicingVariable1 = result; // *
System.Console.WriteLine("Done!");
}
}
internal class TreeNode
{
private int value = 0;
private TreeNode left = null;
private TreeNode right = null;
internal TreeNode(int levels)
{
value = 1;
if (levels <= 1)
{
if (levels <= 0)
throw new System.Exception("Number of levels must be positive no.");
left = null;
right = null;
}
else
{
left = new TreeNode(levels - 1);
right = new TreeNode(levels - 1);
}
}
internal virtual int addTree()
{
int total = value; // *
if (left != null) // *
total += left.addTree(); // *
if (right != null) // *
total += right.addTree(); // *
return total; // *
}
}
}After running the query I collect every line in every path, and I get these lines: {11, 12, 42, 43, 44, 45, 46, 47} (marked with // *). For example, Any suggestions? |
Beta Was this translation helpful? Give feedback.
-
|
Hi @asoifer, I'm sorry to say that our data-flow analysis has a specific limitation that disallows defining sources/sinks of a data-flow configuration based on paths found with that configuration. For the security queries we are writing, that has not been a big problem so far. In some cases, we've had to have two layers of data-flow, which we have managed by just introducing a separate copy of the whole data-flow analysis, and then each part can sit in it's own "layer". In this way we can define sources/sinks in one layer based on the results form the other layer. For C# this would be DataFlow, DataFlow2, DataFlow3, DataFlow4, DataFlow5. And as an example of actually combining such two layers, I will highlight path injection query in Python. But I think this would at best be a band-aid for the specific problem you are trying to solve, where I would assume you want to reach a fixed point, and not just do a few iterations at most. Also sorry for the very late reply. This question somehow slipped off the radar 😐 |
Beta Was this translation helpful? Give feedback.
Hi @asoifer,
I'm sorry to say that our data-flow analysis has a specific limitation that disallows defining sources/sinks of a data-flow configuration based on paths found with that configuration. For the security queries we are writing, that has not been a big problem so far. In some cases, we've had to have two layers of data-flow, which we have managed by just introducing a separate copy of the whole data-flow analysis, and then each part can sit in it's own "layer". In this way we can define sources/sinks in one layer based on the results form the other layer.
For C# this would be DataFlow, DataFlow2, DataFlow3, DataFlow4, DataFlow5. And as an example of actually combining such two la…