From 5de7f4ec05ccaa3f9ac3d5b25d846c1cb8b3051f Mon Sep 17 00:00:00 2001 From: Uwe Schindler Date: Mon, 6 Nov 2023 21:35:57 +0100 Subject: [PATCH] For static method calls and field accesses do not look into superclasses. This fixes #237 --- .../thetaphi/forbiddenapis/ClassScanner.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/thetaphi/forbiddenapis/ClassScanner.java b/src/main/java/de/thetaphi/forbiddenapis/ClassScanner.java index 33b55f0..dd3d0af 100644 --- a/src/main/java/de/thetaphi/forbiddenapis/ClassScanner.java +++ b/src/main/java/de/thetaphi/forbiddenapis/ClassScanner.java @@ -379,7 +379,7 @@ public MethodVisitor visitMethod(final int access, final String name, final Stri } } - private String checkMethodAccess(String owner, final Method method) { + private String checkMethodAccess(String owner, final Method method, final boolean callIsVirtual) { if (CLASS_CONSTRUCTOR_METHOD_NAME.equals(method.getName())) { // we don't check for violations on class constructors return null; @@ -393,8 +393,8 @@ private String checkMethodAccess(String owner, final Method method) { if (violation != null) { return violation; } - if (CONSTRUCTOR_METHOD_NAME.equals(method.getName())) { - return null; // don't look into superclasses or interfaces to find constructors! + if (!callIsVirtual) { + return null; // don't look into superclasses or interfaces for static or special calls (like ctors) } final ClassMetadata c = lookup.lookupRelatedClass(owner, owner); if (c == null) { @@ -432,7 +432,7 @@ public String visit(ClassMetadata c, String origName, boolean isInterfaceOfAnces }, true, false /* JVM spec says: interfaces after superclasses */); } - private String checkFieldAccess(String owner, final String field) { + private String checkFieldAccess(String owner, final String field, final boolean callIsVirtual) { String violation = checkClassUse(owner, "class/interface", owner); if (violation != null) { return violation; @@ -442,6 +442,9 @@ private String checkFieldAccess(String owner, final String field) { if (violation != null) { return violation; } + if (!callIsVirtual) { + return null; // don't look into superclasses or interfaces for static field lookups + } final ClassMetadata c = lookup.lookupRelatedClass(owner, owner); if (c == null) { return null; @@ -477,9 +480,10 @@ private String checkHandle(Handle handle, boolean checkLambdaHandle) { switch (handle.getTag()) { case Opcodes.H_GETFIELD: case Opcodes.H_PUTFIELD: + return checkFieldAccess(handle.getOwner(), handle.getName(), true); case Opcodes.H_GETSTATIC: case Opcodes.H_PUTSTATIC: - return checkFieldAccess(handle.getOwner(), handle.getName()); + return checkFieldAccess(handle.getOwner(), handle.getName(), false); case Opcodes.H_INVOKEVIRTUAL: case Opcodes.H_INVOKESTATIC: case Opcodes.H_INVOKESPECIAL: @@ -492,7 +496,8 @@ private String checkHandle(Handle handle, boolean checkLambdaHandle) { // so we can assign the called lambda with the same groupId like *this* method: lambdas.put(m, currentGroupId); } - return checkMethodAccess(handle.getOwner(), m); + final boolean callIsVirtual = (handle.getTag() == Opcodes.H_INVOKEVIRTUAL) || (handle.getTag() == Opcodes.H_INVOKEINTERFACE); + return checkMethodAccess(handle.getOwner(), m, callIsVirtual); } return null; } @@ -550,12 +555,14 @@ public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - reportMethodViolation(checkMethodAccess(owner, new Method(name, desc)), "method body"); + final boolean callIsVirtual = (opcode == Opcodes.INVOKEVIRTUAL) || (opcode == Opcodes.INVOKEINTERFACE); + reportMethodViolation(checkMethodAccess(owner, new Method(name, desc), callIsVirtual), "method body"); } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { - reportMethodViolation(checkFieldAccess(owner, name), "method body"); + final boolean callIsVirtual = (opcode == Opcodes.GETFIELD) || (opcode == Opcodes.PUTFIELD); + reportMethodViolation(checkFieldAccess(owner, name, callIsVirtual), "method body"); } @Override