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 2021/10/21 14:18:54 UTC
[groovy] 01/02: GROOVY-10303: non-indy: ensure declared variable
end label is non-null
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 <er...@thomsonreuters.com>
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
+ '''
+ }
+}