This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-bcel.git
The following commit(s) were added to refs/heads/master by this push:
new d5d17bd9 Use exclusive live-range end in
LocalVariableTable.getLocalVariable (#517)
d5d17bd9 is described below
commit d5d17bd9c28590cf44469bc1898c263ecd4d05fd
Author: Dexter.k <[email protected]>
AuthorDate: Mon Jul 6 19:20:21 2026 +0000
Use exclusive live-range end in LocalVariableTable.getLocalVariable (#517)
* Use exclusive live-range end in LocalVariableTable.getLocalVariable
JVMS 4.7.13 defines a local variable's live range as the half-open interval
[start_pc, start_pc + length), so a lookup at start_pc + length must not match.
Change the upper comparison from pc <= endPc to pc < endPc.
* use valid constant pool entries in LocalVariableTableTest
Point the test variable at real Utf8 name and signature entries so a
failed assertion stringifies the LocalVariable instead of throwing
ClassFormatException. Also link the JVMS se25 spec in the javadoc.
---
.../apache/bcel/classfile/LocalVariableTable.java | 2 +-
.../bcel/classfile/LocalVariableTableTest.java | 48 ++++++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/apache/bcel/classfile/LocalVariableTable.java
b/src/main/java/org/apache/bcel/classfile/LocalVariableTable.java
index 2fec2a8a..4a988c8e 100644
--- a/src/main/java/org/apache/bcel/classfile/LocalVariableTable.java
+++ b/src/main/java/org/apache/bcel/classfile/LocalVariableTable.java
@@ -150,7 +150,7 @@ public class LocalVariableTable extends Attribute
implements Iterable<LocalVaria
if (variable.getIndex() == index) {
final int startPc = variable.getStartPC();
final int endPc = startPc + variable.getLength();
- if (pc >= startPc && pc <= endPc) {
+ if (pc >= startPc && pc < endPc) {
return variable;
}
}
diff --git
a/src/test/java/org/apache/bcel/classfile/LocalVariableTableTest.java
b/src/test/java/org/apache/bcel/classfile/LocalVariableTableTest.java
new file mode 100644
index 00000000..13a3a536
--- /dev/null
+++ b/src/test/java/org/apache/bcel/classfile/LocalVariableTableTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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
+ *
+ * https://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 org.apache.bcel.classfile;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link LocalVariableTable#getLocalVariable(int, int)}.
+ */
+class LocalVariableTableTest {
+
+ /**
+ * The live range of a local variable is the half-open interval {@code
[start_pc, start_pc + length)} per
+ * <a
href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.7.13">JVMS
4.7.13</a>, so a pc equal to
+ * {@code start_pc + length} is out of scope and must not match.
+ */
+ @Test
+ void testGetLocalVariableLiveRangeEndIsExclusive() {
+ final ConstantPool constantPool = new ConstantPool(new Constant[]
{null, new ConstantUtf8("i"), new ConstantUtf8("I")});
+ // Variable in slot 1, live at pcs 2, 3, 4 (start 2, length 3), with
valid name and signature indices.
+ final LocalVariable variable = new LocalVariable(2, 3, 1, 2, 1,
constantPool);
+ final LocalVariableTable table = new LocalVariableTable(0, 0, new
LocalVariable[] {variable}, constantPool);
+ assertNull(table.getLocalVariable(1, 1), "pc before start");
+ assertSame(variable, table.getLocalVariable(1, 2), "pc at start");
+ assertSame(variable, table.getLocalVariable(1, 4), "pc at last valid
position");
+ assertNull(table.getLocalVariable(1, 5), "pc at start + length is out
of scope");
+ }
+}