JS: Model JSON.stringify with "deep" read operators

This commit is contained in:
Asger F
2023-10-03 16:01:45 +02:00
parent 0c2e52baba
commit e31ae3a1bf
4 changed files with 42 additions and 0 deletions

View File

@@ -661,6 +661,19 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
c = ContentSet::promiseValue()
)
or
// For deep reads, generate read edges with a self-loop
exists(Node origin, ContentSet contentSet |
FlowSummaryImpl::Private::Steps::summaryReadStep(origin.(FlowSummaryNode).getSummaryNode(),
contentSet, node2.(FlowSummaryNode).getSummaryNode()) and
node1 = [origin, node2]
|
contentSet = MkAnyPropertyDeep() and
c = ContentSet::anyProperty()
or
contentSet = MkArrayElementDeep() and
c = ContentSet::arrayElement()
)
or
DataFlow::AdditionalFlowStep::readStep(node1, c, node2)
}

View File

@@ -205,6 +205,14 @@ SummaryComponent interpretComponentSpecific(Private::AccessPathToken c) {
c.getName() = "Awaited" and
c.getNumArgument() = 0 and
result = SummaryComponent::content(MkAwaited())
or
c.getName() = "AnyMemberDeep" and
c.getNumArgument() = 0 and
result = SummaryComponent::content(MkAnyPropertyDeep())
or
c.getName() = "ArrayElementDeep" and
c.getNumArgument() = 0 and
result = SummaryComponent::content(MkArrayElementDeep())
}
private string getMadStringFromContentSetAux(ContentSet cs) {

View File

@@ -4,6 +4,7 @@ private import AsyncAwait
private import ForOfLoops
private import Generators
private import Iterators2
private import JsonStringify
private import Maps2
private import Promises2
private import Sets2

View File

@@ -0,0 +1,20 @@
/**
* Contains implicit read steps at the input to any function that converts a deep object to a string, such as `JSON.stringify`.
*/
private import javascript
private import FlowSummaryUtil
private import semmle.javascript.dataflow.internal.AdditionalFlowInternal
private import semmle.javascript.dataflow.FlowSummary
private class JsonStringifySummary extends SummarizedCallable {
JsonStringifySummary() { this = "JSON.stringify" }
override DataFlow::InvokeNode getACall() { result instanceof JsonStringifyCall }
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
preservesValue = false and
input = ["Argument[0]", "Argument[0].AnyMemberDeep"] and
output = "ReturnValue"
}
}