This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-bcel.git
The following commit(s) were added to refs/heads/master by this push: new de50ef79 Revert "Variation on PR "Various bug fixes in the verifier #181"" de50ef79 is described below commit de50ef791c6dc83468cd5f95c81e921e0a6a3483 Author: Gary David Gregory (Code signing key) <ggreg...@apache.org> AuthorDate: Sun Apr 9 16:14:44 2023 -0400 Revert "Variation on PR "Various bug fixes in the verifier #181"" This reverts commit 3e6dfa134dab153bb0f42cd1aef3004f464c48b8. --- .../java/org/apache/bcel/classfile/JavaClass.java | 38 ---------- .../bcel/verifier/statics/Pass3aVerifier.java | 87 ++++++++++++++++++---- .../structurals/InstConstraintVisitor.java | 56 +++++++++++++- .../org/apache/bcel/verifier/VerifierTestCase.java | 27 ------- .../verifier/input/FieldVerifierChildClass.java | 49 ------------ .../verifier/input/FieldVerifierSuperClass.java | 37 --------- .../input/StaticFieldVerifierChildClass.java | 50 ------------- .../input/StaticFieldVerifierSuperClass.java | 38 ---------- 8 files changed, 124 insertions(+), 258 deletions(-) diff --git a/src/main/java/org/apache/bcel/classfile/JavaClass.java b/src/main/java/org/apache/bcel/classfile/JavaClass.java index a91b6513..e5464051 100644 --- a/src/main/java/org/apache/bcel/classfile/JavaClass.java +++ b/src/main/java/org/apache/bcel/classfile/JavaClass.java @@ -394,44 +394,6 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl return bcelComparator.equals(this, obj); } - /** - * Finds a visible field by name and type in this class and its super classes. - * - * @param fieldName the field name to find - * @param fieldType the field type to find - * @return field matching given name and type, null if field is not found or not accessible from this class. - * @throws ClassNotFoundException - * @since 6.8.0 - */ - public Field findField(final String fieldName, final Type fieldType) throws ClassNotFoundException { - for (final Field field : fields) { - if (field.getName().equals(fieldName)) { - final Type fType = Type.getType(field.getSignature()); - // TODO: Check if assignment compatibility is sufficient. What does Sun do? - if (fType.equals(fieldType)) { - return field; - } - } - } - final JavaClass superclass = getSuperClass(); - if (superclass != null && !"java.lang.Object".equals(superclass.getClassName())) { - final Field f = superclass.findField(fieldName, fieldType); - if (f != null && (f.isPublic() || f.isProtected() || !f.isPrivate() && packageName.equals(superclass.getPackageName()))) { - return f; - } - } - JavaClass[] implementedInterfaces = getInterfaces(); - if (implementedInterfaces != null) { - for (JavaClass implementedInterface : implementedInterfaces) { - final Field f = implementedInterface.findField(fieldName, fieldType); - if (f != null) { - return f; - } - } - } - return null; - } - /** * Get all interfaces implemented by this JavaClass (transitively). * diff --git a/src/main/java/org/apache/bcel/verifier/statics/Pass3aVerifier.java b/src/main/java/org/apache/bcel/verifier/statics/Pass3aVerifier.java index 61e555d7..2d8db459 100644 --- a/src/main/java/org/apache/bcel/verifier/statics/Pass3aVerifier.java +++ b/src/main/java/org/apache/bcel/verifier/statics/Pass3aVerifier.java @@ -25,14 +25,12 @@ import org.apache.bcel.classfile.ClassFormatException; import org.apache.bcel.classfile.Code; import org.apache.bcel.classfile.CodeException; import org.apache.bcel.classfile.Constant; -import org.apache.bcel.classfile.ConstantCP; import org.apache.bcel.classfile.ConstantClass; import org.apache.bcel.classfile.ConstantDouble; import org.apache.bcel.classfile.ConstantFieldref; import org.apache.bcel.classfile.ConstantFloat; import org.apache.bcel.classfile.ConstantInteger; import org.apache.bcel.classfile.ConstantInterfaceMethodref; -import org.apache.bcel.classfile.ConstantInvokeDynamic; import org.apache.bcel.classfile.ConstantLong; import org.apache.bcel.classfile.ConstantMethodref; import org.apache.bcel.classfile.ConstantNameAndType; @@ -322,9 +320,59 @@ public final class Pass3aVerifier extends PassVerifier { final String fieldName = o.getFieldName(constantPoolGen); final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName()); - final Field f = jc.findField(fieldName, o.getType(constantPoolGen)); + Field[] fields = jc.getFields(); + Field f = null; + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + final Type fType = Type.getType(field.getSignature()); + final Type oType = o.getType(constantPoolGen); + /* + * TODO: Check if assignment compatibility is sufficient. What does Sun do? + */ + if (fType.equals(oType)) { + f = field; + break; + } + } + } if (f == null) { - constraintViolated(o, "Referenced field '" + fieldName + "' does not exist in class '" + jc.getClassName() + "'."); + final JavaClass[] superclasses = jc.getSuperClasses(); + outer: for (final JavaClass superclass : superclasses) { + fields = superclass.getFields(); + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + final Type fType = Type.getType(field.getSignature()); + final Type oType = o.getType(constantPoolGen); + if (fType.equals(oType)) { + f = field; + if ((f.getAccessFlags() & (Const.ACC_PUBLIC | Const.ACC_PROTECTED)) == 0) { + f = null; + } + break outer; + } + } + } + } + if (f == null) { + constraintViolated(o, "Referenced field '" + fieldName + "' does not exist in class '" + jc.getClassName() + "'."); + } + } else { + /* + * TODO: Check if assignment compatibility is sufficient. What does Sun do? + */ + Type.getType(f.getSignature()); + o.getType(constantPoolGen); +// Type f_type = Type.getType(f.getSignature()); +// Type o_type = o.getType(cpg); + + // Argh. Sun's implementation allows us to have multiple fields of + // the same name but with a different signature. + // if (! f_type.equals(o_type)) { + // constraintViolated(o, + // "Referenced field '"+field_name+"' has type '"+f_type+"' instead of '"+o_type+"' as expected."); + // } + + /* TODO: Check for access modifiers here. */ } } catch (final ClassNotFoundException e) { // FIXME: maybe not the best way to handle this @@ -366,7 +414,14 @@ public final class Pass3aVerifier extends PassVerifier { try { final String fieldName = o.getFieldName(constantPoolGen); final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName()); - final Field f = jc.findField(fieldName, o.getType(constantPoolGen)); + final Field[] fields = jc.getFields(); + Field f = null; + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + f = field; + break; + } + } if (f == null) { throw new AssertionViolatedException("Field '" + fieldName + "' not found in " + jc.getClassName()); } @@ -446,8 +501,8 @@ public final class Pass3aVerifier extends PassVerifier { } } else { final Constant c = constantPoolGen.getConstant(o.getIndex()); - if (!(c instanceof ConstantInterfaceMethodref) && !(c instanceof ConstantInvokeDynamic)) { - constraintViolated(o, "Indexing a constant that's not a CONSTANT_InterfaceMethodref/InvokeDynamic but a '" + tostring(c) + "'."); + if (!(c instanceof ConstantInterfaceMethodref)) { + constraintViolated(o, "Indexing a constant that's not a CONSTANT_InterfaceMethodref but a '" + tostring(c) + "'."); } // TODO: From time to time check if BCEL allows to detect if the // 'count' operand is consistent with the information in the @@ -455,7 +510,7 @@ public final class Pass3aVerifier extends PassVerifier { // By now, BCEL hides those two operands because they're superfluous. // Invoked method must not be <init> or <clinit> - final ConstantNameAndType cnat = (ConstantNameAndType) constantPoolGen.getConstant(((ConstantCP) c).getNameAndTypeIndex()); + final ConstantNameAndType cnat = (ConstantNameAndType) constantPoolGen.getConstant(((ConstantInterfaceMethodref) c).getNameAndTypeIndex()); final String name = ((ConstantUtf8) constantPoolGen.getConstant(cnat.getNameIndex())).getBytes(); if (name.equals(Const.CONSTRUCTOR_NAME)) { constraintViolated(o, "Method to invoke must not be '" + Const.CONSTRUCTOR_NAME + "'."); @@ -607,12 +662,7 @@ public final class Pass3aVerifier extends PassVerifier { // INVOKEVIRTUAL is an InvokeInstruction, the argument and return types are resolved/verified, // too. So are the allowed method names. final String className = o.getClassName(constantPoolGen); - JavaClass jc; - if (className.charAt(0) == '[') { // array type, e.g. invoke can be someArray.clone() - jc = Repository.lookupClass("java.lang.Object"); - } else { - jc = Repository.lookupClass(className); - } + final JavaClass jc = Repository.lookupClass(className); final Method m = getMethodRecursive(jc, o); if (m == null) { constraintViolated(o, "Referenced method '" + o.getMethodName(constantPoolGen) + "' with expected signature '" @@ -807,7 +857,14 @@ public final class Pass3aVerifier extends PassVerifier { try { final String fieldName = o.getFieldName(constantPoolGen); final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName()); - final Field f = jc.findField(fieldName, o.getType(constantPoolGen)); + final Field[] fields = jc.getFields(); + Field f = null; + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + f = field; + break; + } + } if (f == null) { throw new AssertionViolatedException("Field '" + fieldName + "' not found in " + jc.getClassName()); } diff --git a/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java b/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java index ec6d6743..1c92576d 100644 --- a/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java +++ b/src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java @@ -918,7 +918,21 @@ public class InstConstraintVisitor extends EmptyVisitor { private Field visitFieldInstructionInternals(final FieldInstruction o) throws ClassNotFoundException { final String fieldName = o.getFieldName(cpg); final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName()); - final Field f = jc.findField(fieldName, o.getType(cpg)); + final Field[] fields = jc.getFields(); + Field f = null; + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + final Type fType = Type.getType(field.getSignature()); + final Type oType = o.getType(cpg); + /* + * TODO: Check if assignment compatibility is sufficient. What does Sun do? + */ + if (fType.equals(oType)) { + f = field; + break; + } + } + } if (f == null) { throw new AssertionViolatedException("Field '" + fieldName + "' not found in " + jc.getClassName()); } @@ -1040,9 +1054,43 @@ public class InstConstraintVisitor extends EmptyVisitor { final String fieldName = o.getFieldName(cpg); final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName()); - final Field f = jc.findField(fieldName, o.getType(cpg)); + Field[] fields = jc.getFields(); + Field f = null; + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + final Type fType = Type.getType(field.getSignature()); + final Type oType = o.getType(cpg); + /* + * TODO: Check if assignment compatibility is sufficient. What does Sun do? + */ + if (fType.equals(oType)) { + f = field; + break; + } + } + } + if (f == null) { - throw new AssertionViolatedException("Field '" + fieldName + "' not found in " + jc.getClassName()); + final JavaClass[] superclasses = jc.getSuperClasses(); + outer: for (final JavaClass superclass : superclasses) { + fields = superclass.getFields(); + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + final Type fType = Type.getType(field.getSignature()); + final Type oType = o.getType(cpg); + if (fType.equals(oType)) { + f = field; + if ((f.getAccessFlags() & (Const.ACC_PUBLIC | Const.ACC_PROTECTED)) == 0) { + f = null; + } + break outer; + } + } + } + } + if (f == null) { + throw new AssertionViolatedException("Field '" + fieldName + "' not found in " + jc.getClassName()); + } } if (f.isProtected()) { @@ -1770,7 +1818,7 @@ public class InstConstraintVisitor extends EmptyVisitor { final String theClass = o.getClassName(cpg); - if (objref != GENERIC_ARRAY && !Repository.instanceOf(objRefClassName, theClass)) { + if (!Repository.instanceOf(objRefClassName, theClass)) { constraintViolated(o, "The 'objref' item '" + objref + "' does not implement '" + theClass + "' as expected."); } } catch (final ClassNotFoundException e) { diff --git a/src/test/java/org/apache/bcel/verifier/VerifierTestCase.java b/src/test/java/org/apache/bcel/verifier/VerifierTestCase.java index b17105a0..ec04b9ec 100644 --- a/src/test/java/org/apache/bcel/verifier/VerifierTestCase.java +++ b/src/test/java/org/apache/bcel/verifier/VerifierTestCase.java @@ -20,7 +20,6 @@ package org.apache.bcel.verifier; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrowsExactly; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; @@ -34,14 +33,10 @@ import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.NestHost; import org.apache.bcel.classfile.Utility; import org.apache.bcel.verifier.exc.AssertionViolatedException; -import org.apache.bcel.verifier.input.FieldVerifierChildClass; -import org.apache.bcel.verifier.input.StaticFieldVerifierChildClass; import org.apache.bcel.verifier.statics.StringRepresentation; import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledForJreRange; -import org.junit.jupiter.api.condition.JRE; public class VerifierTestCase { @@ -111,16 +106,6 @@ public class VerifierTestCase { VerifierFactory.clear(); } - @Test - public void testPackagePrivateField() throws ClassNotFoundException { - testDefaultMethodValidation(FieldVerifierChildClass.class.getName()); - } - - @Test - public void testPackagePrivateStaticField() throws ClassNotFoundException { - testDefaultMethodValidation(StaticFieldVerifierChildClass.class.getName()); - } - @Test public void testArrayUtils() throws ClassNotFoundException { testNestHostWithJavaVersion("org.apache.commons.lang.ArrayUtils"); @@ -141,18 +126,6 @@ public class VerifierTestCase { testNestHostWithJavaVersion("com.ibm.wsdl.DefinitionImpl"); } - @Test - @DisabledForJreRange(min = JRE.JAVA_9) - public void testObjectInputStreamJDK8() { - assertThrowsExactly(UnsupportedOperationException.class, () -> testNestHostWithJavaVersion("java.io.ObjectInputStream")); - } - - @Test - @DisabledForJreRange(max = JRE.JAVA_8) - public void testObjectInputStream() throws ClassNotFoundException { - testNestHostWithJavaVersion("java.io.ObjectInputStream"); - } - @Test public void testJvmOpCodes() throws ClassNotFoundException { testDefaultMethodValidation("org.apache.bcel.verifier.tests.JvmOpCodes"); diff --git a/src/test/java/org/apache/bcel/verifier/input/FieldVerifierChildClass.java b/src/test/java/org/apache/bcel/verifier/input/FieldVerifierChildClass.java deleted file mode 100644 index 99c020ce..00000000 --- a/src/test/java/org/apache/bcel/verifier/input/FieldVerifierChildClass.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.bcel.verifier.input; - -public class FieldVerifierChildClass extends FieldVerifierSuperClass { - - public FieldVerifierChildClass(final FieldVerifierChildClass c) { - super(c.publicField, c.getPrivateField(), c.protectedField, c.packagePrivateField); - } - - public int getPublicField() { - return publicField; - } - - public void setPublicField(final int publicField) { - this.publicField = publicField; - } - - public int getProtectedField() { - return protectedField; - } - - public void setProtectedField(final int protectedField) { - this.protectedField = protectedField; - } - - public int getPackagePrivateField() { - return packagePrivateField; - } - - public void setPackagePrivateField(final int packagePrivateField) { - this.packagePrivateField = packagePrivateField; - } -} diff --git a/src/test/java/org/apache/bcel/verifier/input/FieldVerifierSuperClass.java b/src/test/java/org/apache/bcel/verifier/input/FieldVerifierSuperClass.java deleted file mode 100644 index be336897..00000000 --- a/src/test/java/org/apache/bcel/verifier/input/FieldVerifierSuperClass.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.bcel.verifier.input; - -public class FieldVerifierSuperClass { - - public int publicField; - private final int privateField; - protected int protectedField; - int packagePrivateField; - - public FieldVerifierSuperClass(final int publicField, final int privateField, final int protectedField, final int packagePrivateField) { - this.publicField = publicField; - this.privateField = privateField; - this.protectedField = protectedField; - this.packagePrivateField = packagePrivateField; - } - - public int getPrivateField() { - return privateField; - } -} diff --git a/src/test/java/org/apache/bcel/verifier/input/StaticFieldVerifierChildClass.java b/src/test/java/org/apache/bcel/verifier/input/StaticFieldVerifierChildClass.java deleted file mode 100644 index 6c804f08..00000000 --- a/src/test/java/org/apache/bcel/verifier/input/StaticFieldVerifierChildClass.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.bcel.verifier.input; - -public class StaticFieldVerifierChildClass extends StaticFieldVerifierSuperClass { - - @SuppressWarnings("static-access") - public StaticFieldVerifierChildClass(final StaticFieldVerifierChildClass c) { - super(c.publicField, c.getPrivateField(), c.protectedField, c.packagePrivateField); - } - - public static int getPublicField() { - return publicField; - } - - public static void setPublicField(final int publicField) { - StaticFieldVerifierChildClass.publicField = publicField; - } - - public static int getProtectedField() { - return protectedField; - } - - public static void setProtectedField(final int protectedField) { - StaticFieldVerifierChildClass.protectedField = protectedField; - } - - public static int getPackagePrivateField() { - return packagePrivateField; - } - - public static void setPackagePrivateField(final int packagePrivateField) { - StaticFieldVerifierChildClass.packagePrivateField = packagePrivateField; - } -} diff --git a/src/test/java/org/apache/bcel/verifier/input/StaticFieldVerifierSuperClass.java b/src/test/java/org/apache/bcel/verifier/input/StaticFieldVerifierSuperClass.java deleted file mode 100644 index 88eb7839..00000000 --- a/src/test/java/org/apache/bcel/verifier/input/StaticFieldVerifierSuperClass.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.bcel.verifier.input; - -public class StaticFieldVerifierSuperClass { - - public static int publicField; - private static int privateField; - protected static int protectedField; - static int packagePrivateField; - - @SuppressWarnings("static-access") - public StaticFieldVerifierSuperClass(final int publicField, final int privateField, final int protectedField, final int packagePrivateField) { - this.publicField = publicField; - this.privateField = privateField; - this.protectedField = protectedField; - this.packagePrivateField = packagePrivateField; - } - - public int getPrivateField() { - return privateField; - } -}