This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 65323180504cba18d50e5474f6496a810641ba66
Author: Eric Milles <[email protected]>
AuthorDate: Fri Oct 23 20:53:03 2020 -0500

    GROOVY-9093: SC: add compile-time error for inaccessible field or getter 
(port to 2_5_X)
---
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java | 35 +++++---
 src/test/groovy/bugs/Groovy7165.groovy             | 97 ++++++++++++++++++++++
 2 files changed, 121 insertions(+), 11 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index 575a365..ac6862c 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -81,6 +81,9 @@ import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
 import static org.codehaus.groovy.ast.ClassHelper.int_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
 import static org.codehaus.groovy.ast.ClassHelper.make;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
 import static org.codehaus.groovy.classgen.AsmClassGenerator.samePackages;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.chooseBestMethod;
 import static 
org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDGMMethodsByNameAndArguments;
@@ -451,13 +454,13 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter implements Opcodes
             receiverType = classNode;
         }
         
-        String property = methodName;
+        String propertyName = methodName;
         if (implicitThis) {
             if (controller.getInvocationWriter() instanceof 
StaticInvocationWriter) {
                 MethodCallExpression currentCall = ((StaticInvocationWriter) 
controller.getInvocationWriter()).getCurrentCall();
                 if (currentCall != null && 
currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER) != null) {
-                    property = 
currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
-                    String[] props = property.split("\\.");
+                    propertyName = 
currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
+                    String[] props = propertyName.split("\\.");
                     BytecodeExpression thisLoader = new BytecodeExpression() {
                         @Override
                         public void visit(final MethodVisitor mv) {
@@ -477,15 +480,16 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter implements Opcodes
             }
         }
 
-        if (makeGetPropertyWithGetter(receiver, receiverType, property, safe, 
implicitThis)) return;
-        if (makeGetPrivateFieldWithBridgeMethod(receiver, receiverType, 
property, safe, implicitThis)) return;
-        if (makeGetField(receiver, receiverType, property, safe, 
implicitThis)) return;
+        if (makeGetPropertyWithGetter(receiver, receiverType, propertyName, 
safe, implicitThis)) return;
+        if (makeGetPrivateFieldWithBridgeMethod(receiver, receiverType, 
propertyName, safe, implicitThis)) return;
+        if (makeGetField(receiver, receiverType, propertyName, safe, 
implicitThis)) return;
 
-        MethodCallExpression call = new MethodCallExpression(
-                receiver,
-                "getProperty",
-                new ArgumentListExpression(new ConstantExpression(property))
-        );
+        boolean isScriptVariable = (receiverType.isScript() && receiver 
instanceof VariableExpression && ((VariableExpression) 
receiver).getAccessedVariable() == null);
+        if (!isScriptVariable && controller.getClassNode().getOuterClass() == 
null) { // inner class still needs dynamic property sequence
+            addPropertyAccessError(receiver, propertyName, receiverType);
+        }
+
+        MethodCallExpression call = callX(receiver, "getProperty", 
args(constX(propertyName)));
         call.setImplicitThis(implicitThis);
         call.setSafe(safe);
         call.setMethodTarget(GROOVYOBJECT_GETPROPERTY_METHOD);
@@ -939,5 +943,14 @@ public class StaticTypesCallSiteWriter extends 
CallSiteWriter implements Opcodes
             return true;
         }
         return false;
+<<<<<<< HEAD
+=======
+    }*/
+
+    private void addPropertyAccessError(final Expression receiver, final 
String propertyName, final ClassNode receiverType) {
+        String receiverName = (receiver instanceof ClassExpression ? 
receiver.getType() : receiverType).toString(false);
+        String message = "Access to " + receiverName + "#" + propertyName + " 
is forbidden";
+        controller.getSourceUnit().addError(new SyntaxException(message, 
receiver));
+>>>>>>> c27b2c3e51... GROOVY-9093: SC: add compile-time error for inaccessible 
field or getter (port to 3_0_X)
     }
 }
diff --git a/src/test/groovy/bugs/Groovy7165.groovy 
b/src/test/groovy/bugs/Groovy7165.groovy
new file mode 100644
index 0000000..5880057
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7165.groovy
@@ -0,0 +1,97 @@
+/*
+ *  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 groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy7165 {
+
+    @Test
+    void testPrivateStaticSuperField1() {
+        assertScript '''
+            import java.util.function.Function
+
+            @groovy.transform.CompileStatic
+            class Bug {
+                private static List<String> staticfield = []
+
+                def test() {
+                    List<Function<List<String>, String>> runners = []
+                    runners.add(new Called())
+                    List<String> results = ['hello']
+                    runners.each {
+                        results.addAll(it.apply(staticfield))
+                    }
+                    return results.join(' ')
+                }
+
+                static class Called implements Function<List<String>, String> {
+                    @Override
+                    String apply(List<String> args) {
+                        'world'
+                    }
+                }
+            }
+
+            def out = new Bug().test()
+            assert out == 'hello world'
+        '''
+    }
+
+    @Test
+    void testPrivateStaticSuperField2() {
+        def err = shouldFail '''
+            class A {
+                private static final String CONST = 'value'
+            }
+            class B extends A {
+                @groovy.transform.CompileStatic
+                def test() {
+                    return CONST // search excludes private members from supers
+                }
+            }
+            new B().test()
+        '''
+
+        assert err =~ /Access to B#CONST is forbidden/
+    }
+
+    @Test
+    void testPrivateStaticSuperField3() {
+        def err = shouldFail '''
+            class A {
+                private static final String CONST = 'value'
+            }
+            class B extends A {
+                @groovy.transform.CompileStatic
+                def test() {
+                    return A.CONST
+                }
+            }
+            assert false : 'compilation should fail'
+        '''
+
+        assert err =~ /Access to A#CONST is forbidden/
+    }
+}

Reply via email to