View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.bcel.verifier.statics;
18  
19  import static org.assertj.core.api.Assertions.assertThat;
20  import static org.mockito.Mockito.doReturn;
21  import static org.mockito.Mockito.mock;
22  import static org.mockito.Mockito.spy;
23  import static org.mockito.Mockito.when;
24  
25  import java.util.stream.Stream;
26  
27  import org.apache.bcel.Const;
28  import org.apache.bcel.Repository;
29  import org.apache.bcel.classfile.Attribute;
30  import org.apache.bcel.classfile.Code;
31  import org.apache.bcel.classfile.CodeException;
32  import org.apache.bcel.classfile.Constant;
33  import org.apache.bcel.classfile.ConstantDouble;
34  import org.apache.bcel.classfile.ConstantFieldref;
35  import org.apache.bcel.classfile.ConstantInterfaceMethodref;
36  import org.apache.bcel.classfile.ConstantInvokeDynamic;
37  import org.apache.bcel.classfile.ConstantLong;
38  import org.apache.bcel.classfile.ConstantMethodHandle;
39  import org.apache.bcel.classfile.ConstantMethodType;
40  import org.apache.bcel.classfile.ConstantModule;
41  import org.apache.bcel.classfile.ConstantNameAndType;
42  import org.apache.bcel.classfile.ConstantPackage;
43  import org.apache.bcel.classfile.ConstantPool;
44  import org.apache.bcel.classfile.ConstantUtf8;
45  import org.apache.bcel.classfile.JavaClass;
46  import org.apache.bcel.classfile.Method;
47  import org.apache.bcel.util.SyntheticRepository;
48  import org.apache.bcel.verifier.VerificationResult;
49  import org.apache.bcel.verifier.Verifier;
50  import org.apache.bcel.verifier.VerifierFactory;
51  import org.junit.jupiter.api.AfterAll;
52  import org.junit.jupiter.api.BeforeEach;
53  import org.junit.jupiter.params.ParameterizedTest;
54  import org.junit.jupiter.params.provider.MethodSource;
55  
56  class Pass3aVerifierTestCase {
57      public static Stream<Constant> constantsNotSupportedByLdc() {
58          return Stream.of(
59                 new ConstantFieldref(0, 0),
60                 new ConstantInterfaceMethodref(0, 0),
61                 new ConstantInvokeDynamic(0, 0),
62                 new ConstantMethodHandle(0, 0),
63                 new ConstantDouble(0D),
64                 new ConstantLong(0L),
65                 new ConstantMethodHandle(0, 0),
66                 new ConstantMethodType(0),
67                 new ConstantModule(0),
68                 new ConstantNameAndType(0, 0),
69                 new ConstantPackage(0),
70                 new ConstantUtf8("constant")
71                  );
72      }
73      @AfterAll
74      public static void restoreRepository() {
75          // We have set our mock repository, revert the change
76          Repository.setRepository(SyntheticRepository.getInstance());
77      }
78      private Verifier verifier;
79      private org.apache.bcel.util.Repository repository;
80  
81      private ConstantPool cp;
82  
83      private JavaClass javaClass;
84  
85      @ParameterizedTest
86      @MethodSource("constantsNotSupportedByLdc")
87      public void rejectLdcConstant(final Constant constant) {
88          // LDC the constant 0 and then return
89          final byte[] methodCode = {
90                  Const.LDC,
91                  0,
92                  0,
93                  (byte) Const.RETURN,
94          };
95  
96          final Code code = new Code(0, 0, 0, 0, methodCode, new CodeException[0], new Attribute[0], cp);
97  
98          when(cp.getConstantPool()).thenReturn(new Constant[] {constant});
99  
100         final Attribute[] attributes = {code};
101         final Method method = new Method(0, 0, 0, attributes, cp);
102 
103         when(javaClass.getMethods()).thenReturn(new Method[] {method});
104 
105         final Pass3aVerifier pass3aVerifier = new Pass3aVerifier(verifier, 0);
106         final VerificationResult verificationResult = pass3aVerifier.do_verify();
107 
108         assertThat(verificationResult.getStatus()).isEqualTo(VerificationResult.VERIFIED_REJECTED);
109         assertThat(verificationResult.getMessage()).startsWith("Instruction ldc[18](2) 0 constraint violated: Operand of LDC");
110     }
111 
112     @BeforeEach
113     void setup() throws ClassNotFoundException {
114         final String className = "org.apache.bcel.verifier.statics.Pass3aVerifierTestCase.foo";
115 
116         verifier = spy(VerifierFactory.getVerifier(className));
117         repository = mock(org.apache.bcel.util.Repository.class);
118         cp = mock(ConstantPool.class);
119         javaClass = mock(JavaClass.class);
120 
121         // Mock the verifier
122         doReturn(VerificationResult.VR_OK).when(verifier).doPass2();
123 
124         // Mock the repository
125         Repository.setRepository(repository);
126         when(repository.loadClass(className)).thenReturn(javaClass);
127 
128         // Mock the constant pool
129         when(cp.getConstantPool()).thenReturn(new Constant[] {new ConstantModule(0)});
130 
131         // Mock the java class
132         when(javaClass.getConstantPool()).thenReturn(cp);
133     }
134 }
135