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 + ''' + } +}
