You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2024/05/09 18:48:34 UTC
(groovy) branch GROOVY_4_0_X updated: GROOVY-11373: SC: cross-package direct target of package-private method
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
new 0456e0e775 GROOVY-11373: SC: cross-package direct target of package-private method
0456e0e775 is described below
commit 0456e0e77567770dfdc68ca1def46c294357b99b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu May 9 11:43:32 2024 -0500
GROOVY-11373: SC: cross-package direct target of package-private method
4_0_X backport
---
.../classgen/asm/sc/StaticInvocationWriter.java | 44 +++++++++++---------
.../sc/FieldsAndPropertiesStaticCompileTest.groovy | 9 ++---
.../classgen/asm/sc/bugs/Groovy7325Bug.groovy | 47 ++++++++++------------
3 files changed, 50 insertions(+), 50 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
index 9734b1b380..2e3710c5e1 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
@@ -69,9 +69,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.formatTypeName;
import static org.apache.groovy.ast.tools.ClassNodeUtils.samePackageName;
import static org.apache.groovy.ast.tools.ExpressionUtils.isNullConstant;
import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression;
@@ -346,16 +348,17 @@ public class StaticInvocationWriter extends InvocationWriter {
return true;
}
- Expression fixedReceiver = receiver;
- boolean fixedImplicitThis = implicitThis;
- if (target.isProtected()) {
- ClassNode node = receiver == null ? ClassHelper.OBJECT_TYPE : controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
+ Expression fixedReceiver = receiver;
+ boolean fixedImplicitThis = implicitThis;
+ if (target.isPackageScope()) { // GROOVY-11373
+ if (!samePackageName(target.getDeclaringClass(), classNode)) {
+ writeMethodAccessError(target, receiver != null ? receiver : args);
+ }
+ } else if (target.isProtected()) {
+ ClassNode node = receiver == null ? ClassHelper.OBJECT_TYPE : controller.getTypeChooser().resolveType(receiver, classNode);
if (!implicitThis && !isThisOrSuper(receiver) && !samePackageName(node, classNode)
- && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node,target.getDeclaringClass())) {
- controller.getSourceUnit().addError(new SyntaxException(
- "Method " + target.getName() + " is protected in " + target.getDeclaringClass().toString(false),
- receiver != null ? receiver : args
- ));
+ && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node, target.getDeclaringClass())) {
+ writeMethodAccessError(target, receiver != null ? receiver : args);
} else if (!node.isDerivedFrom(target.getDeclaringClass()) && tryBridgeMethod(target, receiver, implicitThis, args, classNode)) {
return true;
}
@@ -388,6 +391,16 @@ public class StaticInvocationWriter extends InvocationWriter {
return super.writeDirectMethodCall(target, implicitThis, receiver, args);
}
+ private void writeMethodAccessError(final MethodNode target, final Expression origin) {
+ StringJoiner descriptor = new StringJoiner(", ", target.getName() + "(", ")");
+ for (Parameter parameter : target.getParameters()) {
+ descriptor.add(formatTypeName(parameter.getOriginType()));
+ }
+ String message = "Cannot access method: " + descriptor + " of class: " + formatTypeName(target.getDeclaringClass());
+
+ controller.getSourceUnit().addError(new SyntaxException(message, origin));
+ }
+
private boolean tryPrivateMethod(final MethodNode target, final boolean implicitThis, final Expression receiver, final TupleExpression args, final ClassNode classNode) {
ClassNode declaringClass = target.getDeclaringClass();
if ((isPrivateBridgeMethodsCallAllowed(declaringClass, classNode) || isPrivateBridgeMethodsCallAllowed(classNode, declaringClass))
@@ -395,21 +408,12 @@ public class StaticInvocationWriter extends InvocationWriter {
&& !declaringClass.equals(classNode)) {
if (tryBridgeMethod(target, receiver, implicitThis, args, classNode)) {
return true;
- } else {
- checkAndAddCannotCallPrivateMethodError(target, receiver, classNode, declaringClass);
}
}
- checkAndAddCannotCallPrivateMethodError(target, receiver, classNode, declaringClass);
- return false;
- }
-
- private void checkAndAddCannotCallPrivateMethodError(final MethodNode target, final Expression receiver, final ClassNode classNode, final ClassNode declaringClass) {
if (declaringClass != classNode) {
- controller.getSourceUnit().addError(new SyntaxException(
- "Cannot call private method " + (target.isStatic() ? "static " : "") + declaringClass.toString(false) + "#" + target.getName() + " from class " + classNode.toString(false),
- receiver
- ));
+ writeMethodAccessError(target, receiver);
}
+ return false;
}
protected static boolean isPrivateBridgeMethodsCallAllowed(final ClassNode receiver, final ClassNode caller) {
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
index 22964e632e..0cd7e9ba50 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
@@ -866,7 +866,7 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
super.testPublicFieldVersusPrivateGetter()
}
- // GROOVY-11223
+ // GROOVY-11223, GROOVY-11373
@Override
void testMapPropertyAccess10() {
assertScript """
@@ -879,13 +879,12 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
def map = new ${MapType.name}()
map.bar = 22 // protected setter
""",
- "Method setBar is protected in ${MapType.name}"
- /*
+ "Cannot access method: setBar(java.lang.Object) of class: ${MapType.name}"
+
shouldFailWithMessages """
def map = new ${MapType.name}()
map.baz = 33 // package-private setter
""",
- "Method setBaz is package-private in ${MapType.name}"
- */
+ "Cannot access method: setBaz(java.lang.Object) of class: ${MapType.name}"
}
}
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7325Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7325Bug.groovy
index 49ea6ed365..49ab84ac65 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7325Bug.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7325Bug.groovy
@@ -16,43 +16,40 @@
* specific language governing permissions and limitations
* under the License.
*/
-
-
package org.codehaus.groovy.classgen.asm.sc.bugs
import groovy.transform.stc.StaticTypeCheckingTestCase
import org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport
-class Groovy7325Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+final class Groovy7325Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
void testGenericIdentityWithClosure() {
assertScript '''
-public static <T> T identity(T self) { self }
-
-@ASTTest(phase=INSTRUCTION_SELECTION,value={
- assert node.rightExpression.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
-})
-Integer i = identity(2)
-
-@ASTTest(phase=INSTRUCTION_SELECTION,value={
- assert node.rightExpression.getNodeMetaData(INFERRED_TYPE) == CLOSURE_TYPE
-})
-Closure c = identity {'foo'}
-'''
+ static <T> T itself(T self) { self }
+
+ @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ assert node.rightExpression.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
+ })
+ Integer i = itself(2)
+
+ @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ assert node.rightExpression.getNodeMetaData(INFERRED_TYPE) == CLOSURE_TYPE
+ })
+ Closure c = itself {'foo'}
+ '''
}
void testShouldNotThrowIllegalAccessToProtectedData() {
- shouldFailWithMessages('''
- class Test {
- final Set<String> HISTORY = [] as HashSet
-
- Set<String> getHistory() {
- return HISTORY.clone() as HashSet<String>
- }
+ shouldFailWithMessages '''
+ class C {
+ private final Set<String> history = []
+ Set<String> getHistory() {
+ (Set<String>) history.clone()
+ }
}
- Test test = new Test()
- println test.history
- ''', 'Method clone is protected in java.lang.Object')
+ def set = new C().history
+ ''',
+ 'Cannot access method: clone() of class: java.lang.Object'
}
}