Skip to content

Commit a7864af

Browse files
committed
8182774: Verify code in javap
Reviewed-by: mcimadamore
1 parent 778ad00 commit a7864af

File tree

6 files changed

+101
-0
lines changed

6 files changed

+101
-0
lines changed

src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.lang.classfile.ClassSignature;
4343
import java.lang.classfile.ClassFile;
4444
import static java.lang.classfile.ClassFile.*;
45+
import java.lang.classfile.ClassHierarchyResolver;
4546
import java.lang.classfile.constantpool.*;
4647
import java.lang.classfile.FieldModel;
4748
import java.lang.classfile.MethodModel;
@@ -248,10 +249,30 @@ public boolean write(ClassModel cm) {
248249
if (options.verbose) {
249250
attrWriter.write(classModel.attributes());
250251
}
252+
253+
if (options.verify) {
254+
var vErrors = VERIFIER.verify(classModel);
255+
if (!vErrors.isEmpty()) {
256+
println();
257+
for (var ve : vErrors) {
258+
println(ve.getMessage());
259+
}
260+
errorReported = true;
261+
}
262+
}
251263
return !errorReported;
252264
}
253265
// where
254266

267+
private static final ClassFile VERIFIER = ClassFile.of(ClassFile.ClassHierarchyResolverOption.of(
268+
ClassHierarchyResolver.defaultResolver().orElse(new ClassHierarchyResolver() {
269+
@Override
270+
public ClassHierarchyResolver.ClassHierarchyInfo getClassInfo(ClassDesc classDesc) {
271+
// mark all unresolved classes as interfaces to exclude them from assignability verification
272+
return ClassHierarchyInfo.ofInterface();
273+
}
274+
})));
275+
255276
final SignaturePrinter sigPrinter;
256277

257278
public static record SignaturePrinter(boolean verbose) {

src/jdk.jdeps/share/classes/com/sun/tools/javap/JavapTask.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,13 @@ void process(JavapTask task, String opt, String arg) {
221221
}
222222
},
223223

224+
new Option(false, "-verify") {
225+
@Override
226+
void process(JavapTask task, String opt, String arg) {
227+
task.options.verify = true;
228+
}
229+
},
230+
224231
new Option(false, "-XDdetails") {
225232
@Override
226233
void process(JavapTask task, String opt, String arg) {

src/jdk.jdeps/share/classes/com/sun/tools/javap/Options.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ else if ((showAccess == 0) && (isPrivate))
8686
public boolean showConstants;
8787
public boolean sysInfo;
8888
public boolean showInnerClasses;
89+
public boolean verify;
8990
public int indentWidth = 2; // #spaces per indentWidth level; must be > 0
9091
public int tabColumn = 40; // column number for comments; must be > 0
9192
public String moduleName;

src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ main.opt.sysinfo=\
126126
\ -sysinfo Show system info (path, size, date, SHA-256 hash)\n\
127127
\ of class being processed
128128

129+
main.opt.verify=\
130+
\ -verify Print additional class verification info
131+
129132
main.opt.module=\
130133
\ --module <module> -m <module> Specify module containing classes to be disassembled
131134

src/jdk.jdeps/share/man/javap.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ Prints internal type signatures.
126126
Shows system information (path, size, date, SHA-256 hash) of the class
127127
being processed.
128128
.TP
129+
\f[V]-verify\f[R]
130+
Prints additional class verification info.
131+
.TP
129132
\f[V]-constants\f[R]
130133
Shows \f[V]static final\f[R] constants.
131134
.TP
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8182774
27+
* @enablePreview
28+
* @summary test on class with a verification error
29+
* @modules jdk.jdeps/com.sun.tools.javap
30+
*/
31+
32+
import java.io.*;
33+
import java.lang.classfile.ClassFile;
34+
import java.lang.constant.ClassDesc;
35+
import java.lang.constant.ConstantDescs;
36+
import java.nio.file.Path;
37+
import java.util.*;
38+
39+
public class VerificationTest {
40+
public static void main(String... args) throws Exception {
41+
new VerificationTest().run();
42+
}
43+
44+
void run() throws Exception {
45+
String testClasses = System.getProperty("test.classes");
46+
String invalidClass = "InvalidClass";
47+
ClassFile.of(ClassFile.StackMapsOption.DROP_STACK_MAPS).buildTo(Path.of(testClasses, invalidClass + ".class"), ClassDesc.of(invalidClass), clb ->
48+
clb.withMethodBody("methodWithMissingStackMap", ConstantDescs.MTD_void, 0, cob ->
49+
cob.iconst_0().ifThen(tb -> tb.nop()).return_()));
50+
String out = javap("-verify", "-classpath", testClasses, invalidClass);
51+
if (!out.contains("Expecting a stackmap frame at branch target")) {
52+
throw new Exception("Expected output not found");
53+
}
54+
}
55+
56+
String javap(String... args) throws Exception {
57+
StringWriter sw = new StringWriter();
58+
PrintWriter out = new PrintWriter(sw);
59+
int rc = com.sun.tools.javap.Main.run(args, out);
60+
out.close();
61+
System.out.println(sw.toString());
62+
if (rc < 0)
63+
throw new Exception("javap exited, rc=" + rc);
64+
return sw.toString();
65+
}
66+
}

0 commit comments

Comments
 (0)