Skip to content

Commit 782a18f

Browse files
Lenny HalsethLenny Halseth
authored andcommitted
Add unit tests for java parsing signature matching
1 parent c0e6c3b commit 782a18f

File tree

3 files changed

+134
-0
lines changed

3 files changed

+134
-0
lines changed
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.sample;
2+
3+
public class Main {
4+
5+
public static void main(String[] args) {
6+
// write your code here
7+
}
8+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright 2018 Secure Decisions, a division of Applied Visions, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* This material is based on research sponsored by the Department of Homeland
17+
* Security (DHS) Science and Technology Directorate, Cyber Security Division
18+
* (DHS S&T/CSD) via contract number HHSP233201600058C.
19+
*/
20+
package com.secdec.codepulse.data.bytecode.parse.test
21+
22+
import java.io.FileInputStream
23+
import scala.util.{ Failure, Success, Try }
24+
25+
import com.secdec.codepulse.data.bytecode.AsmVisitors
26+
import com.secdec.codepulse.data.bytecode.parse.{ JavaBinaryMethodSignature, JavaSourceParsing, MethodSignature }
27+
import org.scalatest.FunSpec
28+
import org.scalatest._
29+
import org.scalatest.Matchers._
30+
31+
class JavaParsingSuite extends FunSpec with Matchers {
32+
val SOURCE = getClass.getResource("Main.java").getPath
33+
val BINARY = getClass.getResource("Main.class").getPath
34+
35+
val MAIN_SIGNATURE = "com/sample/Main.main;void;String[]"
36+
37+
def signatureAsString(signature: MethodSignature): String = {
38+
signature.name + ";" + signature.simplifiedReturnType.name + ";" + signature.simplifiedArgumentTypes.map(_.name).mkString(";")
39+
}
40+
41+
describe("Java interpretation") {
42+
it("should recognize source method information") {
43+
// get stream to source
44+
val stream = new FileInputStream(SOURCE)
45+
46+
// use java parsing on stream to build hierarchy
47+
val source = JavaSourceParsing.tryParseJavaSource(stream)
48+
49+
// get desired method signature as a string
50+
val clazz = source.map(hierarchy => hierarchy.head)
51+
val method = source.map(hierarchy => hierarchy.head.memberMethods.head)
52+
val methodAsSignature = for {
53+
className <- clazz.map(c => c.signature.name.slashedName)
54+
methodSignature <- method.map(m => signatureAsString(m.signature))
55+
} yield { className + "." + methodSignature }
56+
57+
// match to canned result expectation
58+
val matches = methodAsSignature.filter(sig => sig == MAIN_SIGNATURE) match {
59+
case Success(sig) => true
60+
case Failure(_) => false
61+
}
62+
63+
matches should equal(true)
64+
}
65+
66+
it("should recognize binary method information") {
67+
// get stream to binary
68+
val stream = new FileInputStream(BINARY)
69+
70+
// use asm on stream to get method signature as string
71+
val methods = AsmVisitors.parseMethodsFromClass(stream)
72+
val (_, name, _, _) = methods.last
73+
74+
val Array(nameStr: String, accessStr: String, rawSignature: String) = name.split(";", 3)
75+
val binaryMethodSignature = Try(JavaBinaryMethodSignature.parseMemoV1(String.join(";", accessStr, nameStr, rawSignature)))
76+
val methodAsSignature = binaryMethodSignature.map(sig => signatureAsString(sig))
77+
78+
// match to canned result expectation
79+
val matches = methodAsSignature.filter(sig => sig == MAIN_SIGNATURE) match {
80+
case Success(sig) => true
81+
case Failure(_) => false
82+
}
83+
84+
matches should equal(true)
85+
}
86+
87+
it("should generate equivalent data for source and binary method information") {
88+
// get source method signature
89+
// get stream to source
90+
val sourceStream = new FileInputStream(SOURCE)
91+
92+
// use java parsing on stream to build hierarchy
93+
val source = JavaSourceParsing.tryParseJavaSource(sourceStream)
94+
95+
// get desired method signature as a string
96+
val sourceClass = source.map(hierarchy => hierarchy.head)
97+
val sourceMethod = source.map(hierarchy => hierarchy.head.memberMethods.head)
98+
val sourceMethodAsSignature = for {
99+
className <- sourceClass.map(c => c.signature.name.slashedName)
100+
methodSignature <- sourceMethod.map(m => signatureAsString(m.signature))
101+
} yield { className + "." + methodSignature }
102+
103+
// get binary method signature
104+
// get stream to binary
105+
val binaryStream = new FileInputStream(BINARY)
106+
107+
// use asm on stream to get method signature as string
108+
val binaryMethods = AsmVisitors.parseMethodsFromClass(binaryStream)
109+
val (_, binaryName, _, _) = binaryMethods.last
110+
111+
val Array(binaryNameStr: String, binaryAccessStr: String, binaryRawSignature: String) = binaryName.split(";", 3)
112+
val binaryMethodSignature = Try(JavaBinaryMethodSignature.parseMemoV1(String.join(";", binaryAccessStr, binaryNameStr, binaryRawSignature)))
113+
val binaryMethodAsSignature = binaryMethodSignature.map(sig => signatureAsString(sig))
114+
115+
// match signatures
116+
val matches = (for {
117+
sourceSignature <- sourceMethodAsSignature
118+
binarySignature <- binaryMethodAsSignature
119+
} yield {
120+
sourceSignature == binarySignature
121+
}).get
122+
123+
matches should equal(true)
124+
}
125+
}
126+
}

0 commit comments

Comments
 (0)