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");
+    }
+}

Reply via email to