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

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

commit a6b2d6524c728e6e49e5a81f22cf5c9811ad7f7a
Author: Eric Milles <[email protected]>
AuthorDate: Fri Oct 15 15:24:31 2021 -0500

    GROOVY-10303: non-indy: ensure declared variable end label is non-null
---
 .../codehaus/groovy/classgen/asm/CompileStack.java | 31 ++++++++-------
 src/test/groovy/bugs/Groovy10303.groovy            | 45 ++++++++++++++++++++++
 2 files changed, 60 insertions(+), 16 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/CompileStack.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/CompileStack.java
index 5cf6685..5d8d056 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/CompileStack.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/CompileStack.java
@@ -355,15 +355,11 @@ public class CompileStack implements Opcodes {
             if (thisEndLabel == null) setEndLabels();
 
             if (!scope.isInStaticContext()) {
-                // write "this"
                 mv.visitLocalVariable("this", className, null, thisStartLabel, 
thisEndLabel, 0);
             }
-
             for (BytecodeVariable v : usedVariables) {
                 String type = BytecodeHelper.getTypeDescription(v.isHolder() ? 
ClassHelper.REFERENCE_TYPE : v.getType());
-                Label start = v.getStartLabel();
-                Label end = v.getEndLabel();
-                mv.visitLocalVariable(v.getName(), type, null, start, end, 
v.getIndex());
+                mv.visitLocalVariable(v.getName(), type, null, 
v.getStartLabel(), v.getEndLabel(), v.getIndex());
             }
         }
 
@@ -593,9 +589,9 @@ public class CompileStack implements Opcodes {
                     controller.getOperandStack().load(type, 
currentVariableIndex);
                     controller.getOperandStack().box();
 
-                    // GROOVY-4237, the original variable should always appear
+                    // GROOVY-4237: the original variable should always appear
                     // in the variable index, otherwise some programs get into
-                    // trouble. So we define a dummy variable for the packaging
+                    // trouble; so define a dummy variable for the packaging
                     // phase and let it end right away before the normal
                     // reference will be used
                     Label newStart = new Label();
@@ -656,15 +652,18 @@ public class CompileStack implements Opcodes {
 
     public BytecodeVariable defineVariable(final Variable v, final ClassNode 
variableType, final boolean initFromStack) {
         String name = v.getName();
-        BytecodeVariable answer = defineVar(name, variableType, 
v.isClosureSharedVariable(), v.isClosureSharedVariable());
-        stackVariables.put(name, answer);
-
         MethodVisitor mv = controller.getMethodVisitor();
-        Label startLabel  = new Label();
-        answer.setStartLabel(startLabel);
-        ClassNode type = answer.getType().redirect();
         OperandStack operandStack = controller.getOperandStack();
 
+        BytecodeVariable answer = defineVar(name, variableType, 
v.isClosureSharedVariable(), v.isClosureSharedVariable());
+        BytecodeVariable before = stackVariables.put(name, answer);
+        Label startLabel = new Label();
+        answer.setStartLabel(startLabel);
+        if (before != null) {//GROOVY-10303
+            before.setEndLabel(startLabel);
+        }
+
+        ClassNode type = answer.getType();
         if (!initFromStack) {
             if (ClassHelper.isPrimitiveType(v.getOriginType()) && 
ClassHelper.getWrapper(v.getOriginType()) == variableType) {
                 pushInitValue(v.getOriginType(), mv);
@@ -672,11 +671,11 @@ public class CompileStack implements Opcodes {
                 operandStack.box();
                 operandStack.remove(1);
             } else {
-                pushInitValue(type, mv);
+                pushInitValue(type.redirect(), mv);
             }
         }
-        operandStack.push(answer.getType());
-        if (answer.isHolder())  {
+        operandStack.push(type);
+        if (answer.isHolder()) {
             operandStack.box();
             operandStack.remove(1);
             createReference(answer);
diff --git a/src/test/groovy/bugs/Groovy10303.groovy 
b/src/test/groovy/bugs/Groovy10303.groovy
new file mode 100644
index 0000000..ca3bbfa
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy10303.groovy
@@ -0,0 +1,45 @@
+/*
+ *  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 org.codehaus.groovy.control.CompilerConfiguration
+import org.junit.Test
+
+final class Groovy10303 {
+    @Test
+    void testCompileStackClearNPE() {
+        CompilerConfiguration config = new CompilerConfiguration()
+        config.optimizationOptions.put('indy', false)
+        config.optimizationOptions.put('int', true)
+        new GroovyShell(config).evaluate '''
+            abstract class A {
+                def foo(int a, int b) {
+                    if (a == 1 && b == 2) // has to have && or ||, cannot be a 
single truth check
+                        def c = add(a,b)
+                    def d = 3 // this has to be here after the if or any 
command before end block
+                }
+                Integer add(a,b) {
+                    return a+b
+                }
+            }
+
+            null
+        '''
+    }
+}

Reply via email to