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

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-bcel.git

commit 64b1e7b761dc2ae69e1af905f39f275a6efbcbc2
Author: Gary Gregory <[email protected]>
AuthorDate: Wed Mar 20 21:33:27 2019 -0400

    [BCEL-267] Race conditions on static fields in BranchHandle and (#23).
    
    Do not break binary compatibility.
---
 .../org/apache/bcel/generic/InstructionHandle.java | 622 +++++++++++----------
 1 file changed, 316 insertions(+), 306 deletions(-)

diff --git a/src/main/java/org/apache/bcel/generic/InstructionHandle.java 
b/src/main/java/org/apache/bcel/generic/InstructionHandle.java
index f91b025..e2e6a46 100644
--- a/src/main/java/org/apache/bcel/generic/InstructionHandle.java
+++ b/src/main/java/org/apache/bcel/generic/InstructionHandle.java
@@ -1,306 +1,316 @@
-/*
- * 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 org.apache.bcel.generic;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.bcel.classfile.Utility;
-
-/**
- * Instances of this class give users a handle to the instructions contained in
- * an InstructionList. Instruction objects may be used more than once within a
- * list, this is useful because it saves memory and may be much faster.
- *
- * Within an InstructionList an InstructionHandle object is wrapped
- * around all instructions, i.e., it implements a cell in a
- * doubly-linked list. From the outside only the next and the
- * previous instruction (handle) are accessible. One
- * can traverse the list via an Enumeration returned by
- * InstructionList.elements().
- *
- * @version $Id$
- * @see Instruction
- * @see BranchHandle
- * @see InstructionList
- */
-public class InstructionHandle {
-
-    private InstructionHandle next;
-    private InstructionHandle prev;
-    private Instruction instruction;
-
-    /**
-     * @deprecated (since 6.0) will be made private; do not access directly, 
use getter/setter
-     */
-    @Deprecated
-    protected int i_position = -1; // byte code offset of instruction
-
-    private Set<InstructionTargeter> targeters;
-    private Map<Object, Object> attributes;
-
-
-    public final InstructionHandle getNext() {
-        return next;
-    }
-
-
-    public final InstructionHandle getPrev() {
-        return prev;
-    }
-
-
-    public final Instruction getInstruction() {
-        return instruction;
-    }
-
-
-    /**
-     * Replace current instruction contained in this handle.
-     * Old instruction is disposed using Instruction.dispose().
-     */
-    public void setInstruction( final Instruction i ) { // Overridden in 
BranchHandle TODO could be package-protected?
-        if (i == null) {
-            throw new ClassGenException("Assigning null to handle");
-        }
-        if ((this.getClass() != BranchHandle.class) && (i instanceof 
BranchInstruction)) {
-            throw new ClassGenException("Assigning branch instruction " + i + 
" to plain handle");
-        }
-        if (instruction != null) {
-            instruction.dispose();
-        }
-        instruction = i;
-    }
-
-
-    /**
-     * Temporarily swap the current instruction, without disturbing
-     * anything. Meant to be used by a debugger, implementing
-     * breakpoints. Current instruction is returned.
-     * <p>
-     * Warning: if this is used on a BranchHandle then some methods such as
-     * getPosition() will still refer to the original cached instruction, 
whereas
-     * other BH methods may affect the cache and the replacement instruction.
-     */
-    // See BCEL-273
-    // TODO remove this method in any redesign of BCEL
-    public Instruction swapInstruction( final Instruction i ) {
-        final Instruction oldInstruction = instruction;
-        instruction = i;
-        return oldInstruction;
-    }
-
-
-    /*private*/protected InstructionHandle(final Instruction i) {
-        setInstruction(i);
-    }
-
-    /** Factory method.
-     */
-    static InstructionHandle getInstructionHandle( final Instruction i ) {
-       return new InstructionHandle(i);
-    }
-
-
-    /**
-     * Called by InstructionList.setPositions when setting the position for 
every
-     * instruction. In the presence of variable length instructions 
`setPositions()'
-     * performs multiple passes over the instruction list to calculate the
-     * correct (byte) positions and offsets by calling this function.
-     *
-     * @param offset additional offset caused by preceding (variable length) 
instructions
-     * @param max_offset the maximum offset that may be caused by these 
instructions
-     * @return additional offset caused by possible change of this 
instruction's length
-     */
-    protected int updatePosition( final int offset, final int max_offset ) {
-        i_position += offset;
-        return 0;
-    }
-
-
-    /** @return the position, i.e., the byte code offset of the contained
-     * instruction. This is accurate only after
-     * InstructionList.setPositions() has been called.
-     */
-    public int getPosition() {
-        return i_position;
-    }
-
-
-    /** Set the position, i.e., the byte code offset of the contained
-     * instruction.
-     */
-    void setPosition( final int pos ) {
-        i_position = pos;
-    }
-
-
-    /**
-     * Delete contents, i.e., remove user access.
-     */
-    void dispose() {
-        next = prev = null;
-        instruction.dispose();
-        instruction = null;
-        i_position = -1;
-        attributes = null;
-        removeAllTargeters();
-    }
-
-
-    /** Remove all targeters, if any.
-     */
-    public void removeAllTargeters() {
-        if (targeters != null) {
-            targeters.clear();
-        }
-    }
-
-
-    /**
-     * Denote this handle isn't referenced anymore by t.
-     */
-    public void removeTargeter( final InstructionTargeter t ) {
-        if (targeters != null) {
-            targeters.remove(t);
-        }
-    }
-
-
-    /**
-     * Denote this handle is being referenced by t.
-     */
-    public void addTargeter( final InstructionTargeter t ) {
-        if (targeters == null) {
-            targeters = new HashSet<>();
-        }
-        //if(!targeters.contains(t))
-        targeters.add(t);
-    }
-
-
-    public boolean hasTargeters() {
-        return (targeters != null) && (targeters.size() > 0);
-    }
-
-
-    /**
-     * @return null, if there are no targeters
-     */
-    public InstructionTargeter[] getTargeters() {
-        if (!hasTargeters()) {
-            return new InstructionTargeter[0];
-        }
-        final InstructionTargeter[] t = new 
InstructionTargeter[targeters.size()];
-        targeters.toArray(t);
-        return t;
-    }
-
-
-    /** @return a (verbose) string representation of the contained instruction.
-     */
-    public String toString( final boolean verbose ) {
-        return Utility.format(i_position, 4, false, ' ') + ": " + 
instruction.toString(verbose);
-    }
-
-
-    /** @return a string representation of the contained instruction.
-     */
-    @Override
-    public String toString() {
-        return toString(true);
-    }
-
-
-    /** Add an attribute to an instruction handle.
-     *
-     * @param key the key object to store/retrieve the attribute
-     * @param attr the attribute to associate with this handle
-     */
-    public void addAttribute( final Object key, final Object attr ) {
-        if (attributes == null) {
-            attributes = new HashMap<>(3);
-        }
-        attributes.put(key, attr);
-    }
-
-
-    /** Delete an attribute of an instruction handle.
-     *
-     * @param key the key object to retrieve the attribute
-     */
-    public void removeAttribute( final Object key ) {
-        if (attributes != null) {
-            attributes.remove(key);
-        }
-    }
-
-
-    /** Get attribute of an instruction handle.
-     *
-     * @param key the key object to store/retrieve the attribute
-     */
-    public Object getAttribute( final Object key ) {
-        if (attributes != null) {
-            return attributes.get(key);
-        }
-        return null;
-    }
-
-
-    /** @return all attributes associated with this handle
-     */
-    public Collection<Object> getAttributes() {
-        if (attributes == null) {
-            attributes = new HashMap<>(3);
-        }
-        return attributes.values();
-    }
-
-
-    /** Convenience method, simply calls accept() on the contained instruction.
-     *
-     * @param v Visitor object
-     */
-    public void accept( final Visitor v ) {
-        instruction.accept(v);
-    }
-
-
-    /**
-     * @param next the next to set
-     * @ since 6.0
-     */
-    final InstructionHandle setNext(final InstructionHandle next) {
-        this.next = next;
-        return next;
-    }
-
-
-    /**
-     * @param prev the prev to set
-     * @ since 6.0
-     */
-    final InstructionHandle setPrev(final InstructionHandle prev) {
-        this.prev = prev;
-        return prev;
-    }
-}
+/*
+ * 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 org.apache.bcel.generic;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.bcel.classfile.Utility;
+
+/**
+ * Instances of this class give users a handle to the instructions contained in
+ * an InstructionList. Instruction objects may be used more than once within a
+ * list, this is useful because it saves memory and may be much faster.
+ *
+ * Within an InstructionList an InstructionHandle object is wrapped
+ * around all instructions, i.e., it implements a cell in a
+ * doubly-linked list. From the outside only the next and the
+ * previous instruction (handle) are accessible. One
+ * can traverse the list via an Enumeration returned by
+ * InstructionList.elements().
+ *
+ * @version $Id$
+ * @see Instruction
+ * @see BranchHandle
+ * @see InstructionList
+ */
+public class InstructionHandle {
+
+    private InstructionHandle next;
+    private InstructionHandle prev;
+    private Instruction instruction;
+
+    /**
+     * @deprecated (since 6.0) will be made private; do not access directly, 
use getter/setter
+     */
+    @Deprecated
+    protected int i_position = -1; // byte code offset of instruction
+
+    private Set<InstructionTargeter> targeters;
+    private Map<Object, Object> attributes;
+
+
+    /**
+     * Does nothing.
+     * 
+     * @deprecated Does nothing as of 6.3.1.
+     */
+    @Deprecated
+    protected void addHandle() {
+        // noop
+    }
+    
+    public final InstructionHandle getNext() {
+        return next;
+    }
+
+
+    public final InstructionHandle getPrev() {
+        return prev;
+    }
+
+
+    public final Instruction getInstruction() {
+        return instruction;
+    }
+
+
+    /**
+     * Replace current instruction contained in this handle.
+     * Old instruction is disposed using Instruction.dispose().
+     */
+    public void setInstruction( final Instruction i ) { // Overridden in 
BranchHandle TODO could be package-protected?
+        if (i == null) {
+            throw new ClassGenException("Assigning null to handle");
+        }
+        if ((this.getClass() != BranchHandle.class) && (i instanceof 
BranchInstruction)) {
+            throw new ClassGenException("Assigning branch instruction " + i + 
" to plain handle");
+        }
+        if (instruction != null) {
+            instruction.dispose();
+        }
+        instruction = i;
+    }
+
+
+    /**
+     * Temporarily swap the current instruction, without disturbing
+     * anything. Meant to be used by a debugger, implementing
+     * breakpoints. Current instruction is returned.
+     * <p>
+     * Warning: if this is used on a BranchHandle then some methods such as
+     * getPosition() will still refer to the original cached instruction, 
whereas
+     * other BH methods may affect the cache and the replacement instruction.
+     */
+    // See BCEL-273
+    // TODO remove this method in any redesign of BCEL
+    public Instruction swapInstruction( final Instruction i ) {
+        final Instruction oldInstruction = instruction;
+        instruction = i;
+        return oldInstruction;
+    }
+
+
+    /*private*/protected InstructionHandle(final Instruction i) {
+        setInstruction(i);
+    }
+
+    /** Factory method.
+     */
+    static InstructionHandle getInstructionHandle( final Instruction i ) {
+       return new InstructionHandle(i);
+    }
+
+
+    /**
+     * Called by InstructionList.setPositions when setting the position for 
every
+     * instruction. In the presence of variable length instructions 
`setPositions()'
+     * performs multiple passes over the instruction list to calculate the
+     * correct (byte) positions and offsets by calling this function.
+     *
+     * @param offset additional offset caused by preceding (variable length) 
instructions
+     * @param max_offset the maximum offset that may be caused by these 
instructions
+     * @return additional offset caused by possible change of this 
instruction's length
+     */
+    protected int updatePosition( final int offset, final int max_offset ) {
+        i_position += offset;
+        return 0;
+    }
+
+
+    /** @return the position, i.e., the byte code offset of the contained
+     * instruction. This is accurate only after
+     * InstructionList.setPositions() has been called.
+     */
+    public int getPosition() {
+        return i_position;
+    }
+
+
+    /** Set the position, i.e., the byte code offset of the contained
+     * instruction.
+     */
+    void setPosition( final int pos ) {
+        i_position = pos;
+    }
+
+
+    /**
+     * Delete contents, i.e., remove user access.
+     */
+    void dispose() {
+        next = prev = null;
+        instruction.dispose();
+        instruction = null;
+        i_position = -1;
+        attributes = null;
+        removeAllTargeters();
+    }
+
+
+    /** Remove all targeters, if any.
+     */
+    public void removeAllTargeters() {
+        if (targeters != null) {
+            targeters.clear();
+        }
+    }
+
+
+    /**
+     * Denote this handle isn't referenced anymore by t.
+     */
+    public void removeTargeter( final InstructionTargeter t ) {
+        if (targeters != null) {
+            targeters.remove(t);
+        }
+    }
+
+
+    /**
+     * Denote this handle is being referenced by t.
+     */
+    public void addTargeter( final InstructionTargeter t ) {
+        if (targeters == null) {
+            targeters = new HashSet<>();
+        }
+        //if(!targeters.contains(t))
+        targeters.add(t);
+    }
+
+
+    public boolean hasTargeters() {
+        return (targeters != null) && (targeters.size() > 0);
+    }
+
+
+    /**
+     * @return null, if there are no targeters
+     */
+    public InstructionTargeter[] getTargeters() {
+        if (!hasTargeters()) {
+            return new InstructionTargeter[0];
+        }
+        final InstructionTargeter[] t = new 
InstructionTargeter[targeters.size()];
+        targeters.toArray(t);
+        return t;
+    }
+
+
+    /** @return a (verbose) string representation of the contained instruction.
+     */
+    public String toString( final boolean verbose ) {
+        return Utility.format(i_position, 4, false, ' ') + ": " + 
instruction.toString(verbose);
+    }
+
+
+    /** @return a string representation of the contained instruction.
+     */
+    @Override
+    public String toString() {
+        return toString(true);
+    }
+
+
+    /** Add an attribute to an instruction handle.
+     *
+     * @param key the key object to store/retrieve the attribute
+     * @param attr the attribute to associate with this handle
+     */
+    public void addAttribute( final Object key, final Object attr ) {
+        if (attributes == null) {
+            attributes = new HashMap<>(3);
+        }
+        attributes.put(key, attr);
+    }
+
+
+    /** Delete an attribute of an instruction handle.
+     *
+     * @param key the key object to retrieve the attribute
+     */
+    public void removeAttribute( final Object key ) {
+        if (attributes != null) {
+            attributes.remove(key);
+        }
+    }
+
+
+    /** Get attribute of an instruction handle.
+     *
+     * @param key the key object to store/retrieve the attribute
+     */
+    public Object getAttribute( final Object key ) {
+        if (attributes != null) {
+            return attributes.get(key);
+        }
+        return null;
+    }
+
+
+    /** @return all attributes associated with this handle
+     */
+    public Collection<Object> getAttributes() {
+        if (attributes == null) {
+            attributes = new HashMap<>(3);
+        }
+        return attributes.values();
+    }
+
+
+    /** Convenience method, simply calls accept() on the contained instruction.
+     *
+     * @param v Visitor object
+     */
+    public void accept( final Visitor v ) {
+        instruction.accept(v);
+    }
+
+
+    /**
+     * @param next the next to set
+     * @ since 6.0
+     */
+    final InstructionHandle setNext(final InstructionHandle next) {
+        this.next = next;
+        return next;
+    }
+
+
+    /**
+     * @param prev the prev to set
+     * @ since 6.0
+     */
+    final InstructionHandle setPrev(final InstructionHandle prev) {
+        this.prev = prev;
+        return prev;
+    }
+}

Reply via email to