Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample query for identifying write loops via AST only #473

Merged
merged 1 commit into from
Nov 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.shiftleft.dataflowengine

import io.shiftleft.codepropertygraph.generated.nodes
import io.shiftleft.codepropertygraph.generated.nodes.AstNodeBase
import io.shiftleft.dataflowengine.language.nodemethods.TrackingPointMethods
import io.shiftleft.semanticcpg.language.Steps
import io.shiftleft.semanticcpg.language._
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.shiftleft.semanticcpg.samplequeries

import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.semanticcpg.testfixtures.CodeToCpgFixture
import org.scalatest.{Matchers, WordSpec}
import io.shiftleft.semanticcpg.language._

class CopyOperations extends WordSpec with Matchers {

val code =
"""
int array_indexing_in_loop (char *dst, char *src, int offset) {
for(i = 0; i < strlen(src); i++) {
dst[i + + j*8 + offset] = src[i];
}
}
"""

CodeToCpgFixture(code) { cpg =>
"find indexed buffer assigment targets" in {
indexBufferAssigns(cpg).l.map(_._2) shouldBe List(Set("i", "j", "offset"))
}

/**
* Determine assignments where target (argument(1)) contains a computed member
* access. For that access, determine the destination buffer and all indices
* */
def indexBufferAssigns(cpg: Cpg) =
cpg
.call(".*assign.*")
.argument(1)
.ast
.isCall
.name(".*op.*computedMemberAccess.*")
.map { call =>
val indices = call.argument(2).ast.isIdentifier.code.toSet
val buf = call.argument(1)
(buf, indices)
}

"find indexed buffer assignment targets in loops where index is incremented" in {

/**
* For (buf, indices) pairs, determine those inside control structures (for, while, if ...)
* where any of the calls made outside of the body (block) are Inc operations. Determine
* the first argument of that Inc operation and check if they are used as indices for
* the write operation into the buffer.
* */
indexBufferAssigns(cpg)
.where {
case (buf, indices) =>
val incIdentifiers = buf.start.inAst.isControlStructure.astChildren
.filterNot(_.isBlock)
.ast
.isCall
.name(".*Inc.*")
.argument(1)
.code
.toSet
(incIdentifiers & indices).nonEmpty
}
.map(_._1)
.code
.l shouldBe List("dst")

}

}

}