1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.bcel.verifier;
20
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.apache.commons.lang3.ArrayUtils;
25
26 /**
27 * A PassVerifier actually verifies a class file; it is instantiated by a Verifier. The verification should conform with
28 * a certain pass as described in The Java Virtual Machine Specification, 2nd edition. This book describes four passes.
29 * Pass one means loading the class and verifying a few static constraints. Pass two actually verifies some other
30 * constraints that could enforce loading in referenced class files. Pass three is the first pass that actually checks
31 * constraints in the code array of a method in the class file; it has two parts with the first verifying static
32 * constraints and the second part verifying structural constraints (where a data flow analysis is used for). The fourth
33 * pass, finally, performs checks that can only be done at run-time. JustIce does not have a run-time pass, but certain
34 * constraints that are usually delayed until run-time for performance reasons are also checked during the second part
35 * of pass three. PassVerifier instances perform caching. That means, if you really want a new verification run of a
36 * certain pass you must use a new instance of a given PassVerifier.
37 *
38 * @see Verifier
39 * @see #verify()
40 */
41 public abstract class PassVerifier {
42
43 /** The (warning) messages. */
44 private final List<String> messages = new ArrayList<>();
45
46 /** The VerificationResult cache. */
47 private VerificationResult verificationResult;
48
49 /**
50 * Constructs a PassVerifier.
51 */
52 public PassVerifier() {
53 // Default constructor for subclasses
54 }
55
56 /**
57 * This method adds a (warning) message to the message pool of this PassVerifier. This method is normally only
58 * internally used by BCEL's class file verifier "JustIce" and should not be used from the outside.
59 *
60 * @param message message to be appended to the message list.
61 * @see #getMessages()
62 */
63 public void addMessage(final String message) {
64 messages.add(message);
65 }
66
67 /**
68 * Verifies, not cached.
69 *
70 * @return The VerificationResult.
71 */
72 public abstract VerificationResult do_verify();
73
74 /**
75 * Returns the (warning) messages that this PassVerifier accumulated during its do_verify()ing work.
76 *
77 * @return The (warning) messages.
78 * @see #addMessage(String)
79 * @see #do_verify()
80 */
81 public String[] getMessages() {
82 return getMessagesList().toArray(ArrayUtils.EMPTY_STRING_ARRAY);
83 }
84
85 /**
86 * Returns the (warning) messages that this PassVerifier accumulated during its do_verify()ing work.
87 *
88 * @return The list of messages.
89 * @see #addMessage(String)
90 * @see #do_verify()
91 */
92 public List<String> getMessagesList() {
93 verify(); // create messages if not already done (cached!)
94 return messages;
95 }
96
97 /**
98 * This method runs a verification pass conforming to the Java Virtual Machine Specification, 2nd edition, on a class
99 * file. PassVerifier instances perform caching; for example if the verify() method once determined a VerificationResult, then
100 * this result may be returned after every invocation of this method instead of running the verification pass anew;
101 * likewise with the result of getMessages().
102 *
103 * @return A VerificationResult.
104 * @see #getMessages()
105 * @see #addMessage(String)
106 */
107 public VerificationResult verify() {
108 if (verificationResult == null) {
109 verificationResult = do_verify();
110 }
111 return verificationResult;
112 }
113 }