Skip to content

Commit 133df0e

Browse files
Lenny HalsethLenny Halseth
authored andcommitted
Update to include method end line as tree node data and change ASD match
1 parent 5275ac1 commit 133df0e

File tree

16 files changed

+193
-207
lines changed

16 files changed

+193
-207
lines changed

codepulse/src/main/scala/com/secdec/codepulse/data/bytecode/CodeForestBuilder.scala

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ class CodeForestBuilder {
5959
val sourceFileId = node.sourceFile.flatMap(source => getSourceFileId(rootGroup, source))
6060
val sourceLocationCount = node.sourceLocationCount
6161
val methodStartLine = node.methodStartLine
62+
val methodEndLine = node.methodEndLine
6263
val isSurfaceMethod = node.isSurfaceMethod
63-
root -> TreeNodeData(id, parentId, name, kind, size, sourceFileId, sourceLocationCount, methodStartLine, isSurfaceMethod)
64+
root -> TreeNodeData(id, parentId, name, kind, size, sourceFileId, sourceLocationCount, methodStartLine, methodEndLine, isSurfaceMethod)
6465
}
6566
}
6667

@@ -97,13 +98,13 @@ class CodeForestBuilder {
9798
this
9899
}
99100

100-
def getOrAddMethod(group: String, rawSig: String, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], isSurfaceMethod: Option[Boolean]): Option[CodeTreeNode] = {
101+
def getOrAddMethod(group: String, rawSig: String, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], methodEndLine: Option[Int], isSurfaceMethod: Option[Boolean]): Option[CodeTreeNode] = {
101102
sourceFile.foreach(addSourceFile(group, _))
102103

103-
MethodSignatureParser.parseSignature(rawSig, sourceFile) map { getOrAddMethod(group, _, size, sourceFile, sourceLocationCnt, methodStartLine, isSurfaceMethod) }
104+
MethodSignatureParser.parseSignature(rawSig, sourceFile) map { getOrAddMethod(group, _, size, sourceFile, sourceLocationCnt, methodStartLine, methodEndLine, isSurfaceMethod) }
104105
}
105106

106-
def getOrAddMethod(group: String, sig: MethodSignature, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], isSurfaceMethod: Option[Boolean]): CodeTreeNode = {
107+
def getOrAddMethod(group: String, sig: MethodSignature, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], methodEndLine: Option[Int], isSurfaceMethod: Option[Boolean]): CodeTreeNode = {
107108
sourceFile.foreach(addSourceFile(group, _))
108109

109110
val treePath = CodePath.parse(sig)
@@ -112,7 +113,7 @@ class CodeForestBuilder {
112113
def recurse(parent: CodeTreeNode, path: CodePath): CodeTreeNode = path match {
113114
case CodePath.Package(name, childPath) => recurse(addChildPackage(parent, name), childPath)
114115
case CodePath.Class(name, childPath) => recurse(addChildClass(parent, name, sourceFile, sourceLocationCnt), childPath)
115-
case CodePath.Method(name) => addChildMethod(parent, name, size, sourceFile, sourceLocationCnt, methodStartLine, isSurfaceMethod)
116+
case CodePath.Method(name) => addChildMethod(parent, name, size, sourceFile, sourceLocationCnt, methodStartLine, methodEndLine, isSurfaceMethod)
116117
}
117118

118119
recurse(startNode, treePath)
@@ -126,7 +127,7 @@ class CodeForestBuilder {
126127
sourceFile.foreach(addSourceFile(JSPGroupName, _))
127128

128129
def recurse(parent: CodeTreeNode, path: List[String]): CodeTreeNode = path match {
129-
case className :: Nil => addChildMethod(parent, className, size, sourceFile, sourceLocationCnt, None, None)
130+
case className :: Nil => addChildMethod(parent, className, size, sourceFile, sourceLocationCnt, None, None, None)
130131
case packageNode :: rest => recurse(addFolder(parent, packageNode), rest)
131132
}
132133

@@ -202,10 +203,10 @@ class CodeForestBuilder {
202203
}
203204
}
204205

205-
protected def addChildMethod(parent: CodeTreeNode, name: String, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], isSurfaceMethod: Option[Boolean]) = parent.findChild { node =>
206+
protected def addChildMethod(parent: CodeTreeNode, name: String, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], methodEndLine: Option[Int], isSurfaceMethod: Option[Boolean]) = parent.findChild { node =>
206207
node.name == name && node.kind == CodeTreeNodeKind.Mth
207208
} getOrElse {
208-
val node = nodeFactory.createMethodNode(name, size, sourceFile, sourceLocationCnt, methodStartLine, isSurfaceMethod)
209+
val node = nodeFactory.createMethodNode(name, size, sourceFile, sourceLocationCnt, methodStartLine, methodEndLine, isSurfaceMethod)
209210
parent.addChild(node)
210211
node
211212
}

codepulse/src/main/scala/com/secdec/codepulse/data/bytecode/CodeTree2.scala

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ trait CodeTreeNode {
3333
def sourceFile: Option[String]
3434
def sourceLocationCount: Option[Int]
3535
def methodStartLine: Option[Int]
36+
def methodEndLine: Option[Int]
3637
def isSurfaceMethod: Option[Boolean]
3738

3839
def parentId = parent map { _.id }
@@ -123,7 +124,7 @@ trait CodeTreeNodeFactory {
123124
def createGroupNode(name: String): CodeTreeNode
124125
def createPackageNode(name: String): CodeTreeNode
125126
def createClassNode(name: String, sourceFile: Option[String], sourceLocationCnt: Option[Int]): CodeTreeNode
126-
def createMethodNode(name: String, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], isSurfaceMethod: Option[Boolean]): CodeTreeNode
127+
def createMethodNode(name: String, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], methodEndLine: Option[Int], isSurfaceMethod: Option[Boolean]): CodeTreeNode
127128
}
128129

129130
object CodeTreeNodeFactory {
@@ -133,6 +134,7 @@ object CodeTreeNodeFactory {
133134
def sourceFile = None
134135
def sourceLocationCount = None
135136
def methodStartLine = None
137+
def methodEndLine = None
136138
def isSurfaceMethod = None
137139
}
138140
private case class PackageNode(id: Int, name: String) extends CodeTreeNode {
@@ -141,6 +143,7 @@ object CodeTreeNodeFactory {
141143
def sourceFile = None
142144
def sourceLocationCount = None
143145
def methodStartLine = None
146+
def methodEndLine = None
144147
def isSurfaceMethod = None
145148
}
146149
private case class ClassNode(id: Int, name: String, sourceFilePath: Option[String], sourceLocationCnt: Option[Int]) extends CodeTreeNode {
@@ -149,14 +152,16 @@ object CodeTreeNodeFactory {
149152
def sourceFile = sourceFilePath
150153
def sourceLocationCount = sourceLocationCnt
151154
def methodStartLine = None
155+
def methodEndLine = None
152156
def isSurfaceMethod = None
153157
}
154-
private case class MethodNode(id: Int, name: String, methodSize: Int, sourceFilePath: Option[String], sourceLocationCnt: Option[Int], methodStart: Option[Int], surfaceMethod: Option[Boolean]) extends CodeTreeNode {
158+
private case class MethodNode(id: Int, name: String, methodSize: Int, sourceFilePath: Option[String], sourceLocationCnt: Option[Int], methodStart: Option[Int], methodEnd: Option[Int], surfaceMethod: Option[Boolean]) extends CodeTreeNode {
155159
def kind = CodeTreeNodeKind.Mth
156160
def size = Some(methodSize)
157161
def sourceFile = sourceFilePath
158162
def sourceLocationCount = sourceLocationCnt
159163
def methodStartLine = methodStart
164+
def methodEndLine = methodEnd
160165
def isSurfaceMethod = surfaceMethod
161166
}
162167

@@ -168,7 +173,7 @@ object CodeTreeNodeFactory {
168173
def createGroupNode(name: String): CodeTreeNode = GroupNode(ids.next, name)
169174
def createPackageNode(name: String): CodeTreeNode = PackageNode(ids.next, name)
170175
def createClassNode(name: String, sourceFile: Option[String], sourceLocationCnt: Option[Int]): CodeTreeNode = ClassNode(ids.next, name, sourceFile, sourceLocationCnt)
171-
def createMethodNode(name: String, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], isSurfaceMethod: Option[Boolean]): CodeTreeNode = MethodNode(ids.next, name, size, sourceFile, sourceLocationCnt, methodStartLine, isSurfaceMethod)
176+
def createMethodNode(name: String, size: Int, sourceFile: Option[String], sourceLocationCnt: Option[Int], methodStartLine: Option[Int], methodEndLine: Option[Int], isSurfaceMethod: Option[Boolean]): CodeTreeNode = MethodNode(ids.next, name, size, sourceFile, sourceLocationCnt, methodStartLine, methodEndLine, isSurfaceMethod)
172177
}
173178
}
174179
sealed abstract class CodeTreeNodeKind(val label: String)

codepulse/src/main/scala/com/secdec/codepulse/data/dotnet/DotNet.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import com.secdec.codepulse.data.MethodSignature
2727
import org.apache.commons.io.{ FileUtils, FilenameUtils }
2828

2929
trait DotNetBuilder {
30-
def Methods: List[(MethodSignature, Int, Int, Int)]
30+
def Methods: List[(MethodSignature, Int, Int, Int, Int)]
3131
}
3232

3333
case class MethodInfo(
@@ -41,7 +41,8 @@ case class MethodInfo(
4141
instructions: Int,
4242
sequencePointCount: Int,
4343
surrogateFor: String,
44-
methodStartLine: Int
44+
methodStartLine: Int,
45+
methodEndLine: Int
4546
)
4647

4748
object DotNet {

codepulse/src/main/scala/com/secdec/codepulse/data/dotnet/SymbolReaderHTTPServiceConnector.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class SymbolReaderHTTPServiceConnector(assembly: File, symbols: File) extends Do
3535
val port = config.getString("cp.userSettings.symbolService.port")
3636
val symbolService = url(s"http://localhost:$port/api/methods")
3737

38-
override def Methods: List[(MethodSignature, Int, Int, Int)] = {
38+
override def Methods: List[(MethodSignature, Int, Int, Int, Int)] = {
3939
implicit val formats = DefaultFormats
4040

4141
val request = symbolService.POST.addBodyPart(new FilePart("assemblyFile", assembly)).addBodyPart(new FilePart("symbolsFile", symbols))
@@ -44,7 +44,7 @@ class SymbolReaderHTTPServiceConnector(assembly: File, symbols: File) extends Do
4444

4545
val methodInfos = parse(result).children.map(child => {
4646
val methodInfo = child.extract[MethodInfo]
47-
(methodInfo.id, methodInfo.surrogateFor, methodInfo.instructions, methodInfo.sequencePointCount, methodInfo.methodStartLine, (new MethodSignature(
47+
(methodInfo.id, methodInfo.surrogateFor, methodInfo.instructions, methodInfo.sequencePointCount, methodInfo.methodStartLine, methodInfo.methodEndLine, (new MethodSignature(
4848
methodInfo.fullyQualifiedName,
4949
methodInfo.containingClass,
5050
Option(methodInfo.file),
@@ -55,8 +55,8 @@ class SymbolReaderHTTPServiceConnector(assembly: File, symbols: File) extends Do
5555

5656
val methodSignaturesById = collection.mutable.Map[String, MethodSignature]().empty
5757

58-
methodInfos.map((methodInfo:(String, String, Int, Int, Int, MethodSignature)) => {
59-
methodSignaturesById(methodInfo._1) = methodInfo._6
58+
methodInfos.map((methodInfo:(String, String, Int, Int, Int, Int, MethodSignature)) => {
59+
methodSignaturesById(methodInfo._1) = methodInfo._7
6060
if (methodInfo._2 != "00000000-0000-0000-0000-000000000000") {
6161
val method = methodSignaturesById(methodInfo._2)
6262
val surrogateMethod = methodSignaturesById(methodInfo._1)
@@ -65,7 +65,7 @@ class SymbolReaderHTTPServiceConnector(assembly: File, symbols: File) extends Do
6565
method.file = surrogateMethod.file
6666
}
6767
}
68-
(methodInfo._6, methodInfo._3, methodInfo._4, methodInfo._5)
68+
(methodInfo._7, methodInfo._3, methodInfo._4, methodInfo._5, methodInfo._6)
6969
})
7070
}
7171
}

codepulse/src/main/scala/com/secdec/codepulse/data/dotnet/SymbolReaderMockService.scala

Lines changed: 0 additions & 54 deletions
This file was deleted.

codepulse/src/main/scala/com/secdec/codepulse/data/model/TreeNodeData.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ case class MethodSignatureNode(id: Int, signature: String, nodeId: Int)
3232
* @param size A number indicating the size of the node (e.g. lines of code). If unspecified,
3333
* the size of a node is assumed to be the sum of its childrens' sizes.
3434
*/
35-
case class TreeNodeData(id: Int, parentId: Option[Int], label: String, kind: CodeTreeNodeKind, size: Option[Int], sourceFileId: Option[Int], sourceLocationCount: Option[Int], methodStartLine: Option[Int], var isSurfaceMethod: Option[Boolean])
35+
case class TreeNodeData(id: Int, parentId: Option[Int], label: String, kind: CodeTreeNodeKind, size: Option[Int], sourceFileId: Option[Int], sourceLocationCount: Option[Int], methodStartLine: Option[Int], methodEndLine: Option[Int], var isSurfaceMethod: Option[Boolean])
3636

3737
sealed trait TreeNodeFlag
3838
object TreeNodeFlag {

codepulse/src/main/scala/com/secdec/codepulse/data/model/slick/TreeNodeDataDao.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ private[slick] class TreeNodeDataDao(val driver: JdbcProfile, val sourceDataDao:
5656
def sourceFileId = column[Option[Int]]("source_file_id", O.Nullable)
5757
def sourceLocationCount = column[Option[Int]]("source_location_count", O.Nullable)
5858
def methodStartLine = column[Option[Int]]("method_start_line", O.Nullable)
59+
def methodEndLine = column[Option[Int]]("method_end_line", O.Nullable)
5960
def isSurfaceMethod = column[Option[Boolean]]("is_surface_method", O.Nullable)
60-
def * = (id, parentId, label, kind, size, sourceFileId, sourceLocationCount, methodStartLine, isSurfaceMethod) <> (TreeNode.tupled, TreeNode.unapply)
61+
def * = (id, parentId, label, kind, size, sourceFileId, sourceLocationCount, methodStartLine, methodEndLine, isSurfaceMethod) <> (TreeNode.tupled, TreeNode.unapply)
6162
def labelIndex = index("tnd_label_index", label)
6263

6364
def sourceFile = foreignKey("tree_node_data_to_source_file", sourceFileId, sourceDataDao.sourceFilesQuery)(_.id, onDelete = ForeignKeyAction.Cascade)
@@ -234,7 +235,8 @@ private[slick] class TreeNodeDataDao(val driver: JdbcProfile, val sourceDataDao:
234235
treeNodeDataItem <- treeNodeData.sortBy(x => x.methodStartLine)
235236
sourceFile <- treeNodeDataItem.sourceFile
236237
if sourceFile.path === sourceFilePath &&
237-
treeNodeDataItem.methodStartLine >= startingLineNumber && treeNodeDataItem.methodStartLine <= endingLineNumber
238+
(treeNodeDataItem.methodEndLine >= startingLineNumber && treeNodeDataItem.methodStartLine <= endingLineNumber)
239+
238240
} yield (treeNodeDataItem.id)).list
239241
}
240242

codepulse/src/main/scala/com/secdec/codepulse/input/bytecode/ByteCodeProcessor.scala

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,23 @@ class ByteCodeProcessor() extends LanguageProcessor with Loggable {
7575
signature.name + ";" + signature.simplifiedReturnType.name + ";" + signature.simplifiedArgumentTypes.map(_.name).mkString(";")
7676
}
7777

78-
def getMethodAndStart(mi: MethodInfo, ci: ClassInfo): (String, Int) = {
79-
(ci.signature.name.slashedName + "." + signatureAsString(mi.signature), mi.lines.start)
78+
def getMethodAndRange(mi: MethodInfo, ci: ClassInfo): (String, Int, Int) = {
79+
(ci.signature.name.slashedName + "." + signatureAsString(mi.signature), mi.lines.start, mi.lines.end)
8080
}
8181

82-
def flattenToMethods(ls: List[ClassInfo]): List[(String, Int)] = {
82+
def flattenToMethods(ls: List[ClassInfo]): List[(String, Int, Int)] = {
8383
ls match {
8484
case Nil => Nil
85-
case l => l.flatMap(ci => ci.memberMethods.map(mi => getMethodAndStart(mi, ci))) ::: l.flatMap(ci => flattenToMethods(ci.memberClasses))
85+
case l => l.flatMap(ci => ci.memberMethods.map(mi => getMethodAndRange(mi, ci))) ::: l.flatMap(ci => flattenToMethods(ci.memberClasses))
8686
}
8787
}
8888

89-
val sourceMethods = new HashMap[String, List[(String, Int)]]
89+
val sourceMethods = new HashMap[String, List[(String, Int, Int)]]
9090
storage.readEntries(sourceType("java") _) { (filename, entryPath, entry, contents) =>
9191
val hierarchy = JavaSourceParsing.tryParseJavaSource(new CloseShieldInputStream(contents))
9292
val methodsAndStarts = hierarchy match {
9393
case Success(h) => flattenToMethods(h)
94-
case Failure(_) => List.empty[(String, Int)]
94+
case Failure(_) => List.empty[(String, Int, Int)]
9595
}
9696

9797
val authority = entryPath.flatMap(ep =>
@@ -134,16 +134,24 @@ class ByteCodeProcessor() extends LanguageProcessor with Loggable {
134134
case None => new NestedPath(List(fp))
135135
})
136136
authority = nestedPath.flatMap(np => authoritativePath(groupName, np).map (_.toString))
137-
methodsAndStartLines = authority.flatMap(sourceMethods.get)
137+
methodsAndRanges = authority.flatMap(sourceMethods.get)
138138
Array(nameStr, accessStr, rawSignature) = name.split(";", 3)
139139
binaryMethodSignature = Try(JavaBinaryMethodSignature.parseMemoV1(String.join(";", accessStr, nameStr, rawSignature)))
140140
startLine = binaryMethodSignature.toOption.flatMap(bms =>
141-
methodsAndStartLines.flatMap { l =>
142-
val potentials = l.filter { case (qualifiedName, line) => qualifiedName == signatureAsString(bms) }
141+
methodsAndRanges.flatMap { l =>
142+
val potentials = l.filter { case (qualifiedName, _, _) => qualifiedName == signatureAsString(bms) }
143143
val selection = potentials.headOption
144-
selection.map(_._2)
144+
val start = selection.map(_._2)
145+
start
145146
})
146-
treeNode <- builder.getOrAddMethod(groupName, name, size, authority, Option(lineCount), startLine, None)
147+
endLine = binaryMethodSignature.toOption.flatMap(bms =>
148+
methodsAndRanges.flatMap { l =>
149+
val potentials = l.filter { case (qualifiedName, _, _) => qualifiedName == signatureAsString(bms) }
150+
val selection = potentials.headOption
151+
val end = selection.map(_._3)
152+
end
153+
})
154+
treeNode <- builder.getOrAddMethod(groupName, name, size, authority, Option(lineCount), startLine, endLine, None)
147155
} {
148156
methodCorrelationsBuilder += (name -> treeNode.id)
149157
}

codepulse/src/main/scala/com/secdec/codepulse/input/dotnet/DotNETProcessor.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class DotNETProcessor() extends LanguageProcessor {
9292
})
9393

9494
for {
95-
(sig, size, sourceLocationCount, methodStartLine) <- methodsSorted
95+
(sig, size, sourceLocationCount, methodStartLine, methodEndLine) <- methodsSorted
9696
filePath = FilePath(sig.file)
9797
nestedPath = filePath.map(fp => entryPath match {
9898
case Some(ep) => new NestedPath(ep.paths :+ fp)
@@ -102,7 +102,7 @@ class DotNETProcessor() extends LanguageProcessor {
102102
case Some(np) => authoritativePath(groupName, np).map (_.toString)
103103
case None => None
104104
}
105-
treeNode <- Option(builder.getOrAddMethod(groupName, if (sig.isSurrogate) sig.surrogateFor.get else sig, size, authority, Option(sourceLocationCount), Option(methodStartLine), None))
105+
treeNode <- Option(builder.getOrAddMethod(groupName, if (sig.isSurrogate) sig.surrogateFor.get else sig, size, authority, Option(sourceLocationCount), Option(methodStartLine), Option(methodEndLine), None))
106106
} methodCorrelationsBuilder += (s"${sig.containingClass}.${sig.name};${sig.modifiers};(${sig.params mkString ","});${sig.returnType}" -> treeNode.id)
107107
}
108108

codepulse/src/main/scala/com/secdec/codepulse/tracer/export/ProjectImportReaderV1.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class ProjectImportReaderV1 extends ProjectImportReader with ProjectImportHelper
110110
var sourceLocationCount = None: Option[Int]
111111
var traced = None: Option[Boolean]
112112
var methodStartLine = None: Option[Int]
113+
var methodEndLine = None: Option[Int]
113114
var isSurfaceMethod = None: Option[Boolean]
114115

115116
while (jp.nextValue != END_OBJECT) {
@@ -155,6 +156,12 @@ class ProjectImportReaderV1 extends ProjectImportReader with ProjectImportHelper
155156
case _ => Some(jp.getIntValue)
156157
}
157158

159+
case "methodEndLine" =>
160+
methodEndLine = jp.getCurrentToken match {
161+
case VALUE_NULL => None
162+
case _ => Some(jp.getIntValue)
163+
}
164+
158165
case "isSurfaceMethod" =>
159166
isSurfaceMethod = jp.getCurrentToken match {
160167
case VALUE_NULL => None
@@ -172,6 +179,7 @@ class ProjectImportReaderV1 extends ProjectImportReader with ProjectImportHelper
172179
sourceFileId,
173180
sourceLocationCount,
174181
methodStartLine,
182+
methodEndLine,
175183
isSurfaceMethod),
176184
traced)
177185
}

0 commit comments

Comments
 (0)