All Downloads are FREE. Search and download functionalities are using the official Maven repository.

proguard.analysis.cpa.jvm.state.JvmAbstractState Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.7
Show newest version
/*
 * ProGuardCORE -- library to process Java bytecode.
 *
 * Copyright (c) 2002-2022 Guardsquare NV
 *
 * Licensed 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 proguard.analysis.cpa.jvm.state;

import java.util.List;
import java.util.Objects;
import proguard.classfile.MethodSignature;
import proguard.analysis.cpa.defaults.LatticeAbstractState;
import proguard.analysis.cpa.defaults.MapAbstractState;
import proguard.analysis.cpa.interfaces.ProgramLocationDependent;
import proguard.analysis.cpa.jvm.cfa.edges.JvmCfaEdge;
import proguard.analysis.cpa.jvm.cfa.nodes.JvmCfaNode;
import proguard.analysis.cpa.jvm.state.heap.JvmHeapAbstractState;

/**
 * The {@link JvmAbstractState} consists of the method frame {@link JvmFrameAbstractState} and the heap {@link JvmHeapAbstractState}.
 *
 * @author Dmitry Ivanov
 */
public class JvmAbstractState>
    implements LatticeAbstractState>,
               ProgramLocationDependent
{

    protected final        JvmFrameAbstractState    frame;
    protected final        JvmHeapAbstractState     heap;
    protected final        MapAbstractState staticFields;
    protected              JvmCfaNode                       programLocation;
    protected static final JvmCfaNode                       topLocation = new JvmCfaNode(null, -1, null);

    /**
     * Create a JVM abstract state.
     *
     * @param programLocation a CFA node
     * @param frame           a frame abstract state
     * @param heap            a heap abstract state
     * @param staticFields    a static field table
     */
    public JvmAbstractState(JvmCfaNode programLocation,
                            JvmFrameAbstractState frame,
                            JvmHeapAbstractState heap,
                            MapAbstractState staticFields)
    {
        this.programLocation = programLocation;
        this.frame = frame;
        this.heap = heap;
        this.staticFields = staticFields;
    }

    // implementations for LatticeAbstractState

    @Override
    public JvmAbstractState join(JvmAbstractState abstractState)
    {
        JvmAbstractState answer = new JvmAbstractState<>(programLocation.equals(abstractState.programLocation) ? programLocation : topLocation,
                                                                 frame.join(abstractState.frame),
                                                                 heap.join(abstractState.heap),
                                                                 staticFields.join(abstractState.staticFields));
        return equals(answer) ? this : answer;
    }

    @Override
    public boolean isLessOrEqual(JvmAbstractState abstractState)
    {
        return (programLocation.equals(abstractState.programLocation)
                || abstractState.programLocation.equals(topLocation))
               && frame.isLessOrEqual(abstractState.frame)
               && heap.isLessOrEqual(abstractState.heap)
               && staticFields.isLessOrEqual(abstractState.staticFields);
    }

    // implementations for ProgramLocationDependent

    @Override
    public JvmCfaNode getProgramLocation()
    {
        return programLocation;
    }

    @Override
    public void setProgramLocation(JvmCfaNode programLocation)
    {
        this.programLocation = programLocation;
    }

    // implementations for AbstractState

    @Override
    public JvmAbstractState copy()
    {
        return new JvmAbstractState<>(programLocation, frame.copy(), heap.copy(), staticFields.copy());
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
        {
            return true;
        }
        if (!(obj instanceof JvmAbstractState))
        {
            return false;
        }
        JvmAbstractState other = (JvmAbstractState) obj;
        return programLocation.equals(other.programLocation) && frame.equals(other.frame) && heap.equals(other.heap) && staticFields.equals(other.staticFields);
    }

    @Override
    public int hashCode()
    {
        return Objects.hash(frame, heap, staticFields, programLocation);
    }

    /**
     * Returns the top element of the operand stack.
     */
    public StateT peek()
    {
        return peek(0);
    }

    /**
     * Returns the {@code index}th element from the top of the operand stack.
     */
    public StateT peek(int index)
    {
        return frame.peek(index);
    }

    /**
     * Returns the top element of the operand stack or returns {@code defaultState} if the stack is empty.
     */

    public StateT peekOrDefault(StateT defaultState)
    {
        return peekOrDefault(0, defaultState);
    }

    /**
     * Returns the {@code index}th element from the top of the operand stack or returns {@code defaultState} if the stack does not have enough elements.
     */
    public StateT peekOrDefault(int index, StateT defaultState)
    {
        return frame.peekOrDefault(index, defaultState);
    }

    /**
     * Removes the top element of the operand stack end returns it.
     */
    public StateT pop()
    {
        return frame.pop();
    }

    /**
     * Removes the top element of the operand stack end returns it. Returns {@code defaultState} if the stack is empty.
     */
    public StateT popOrDefault(StateT defaultState)
    {
        return frame.popOrDefault(defaultState);
    }

    /**
     * Inserts {@code state} to the top of the operand stack and returns it.
     */
    public StateT push(StateT state)
    {
        return frame.push(state);
    }

    /**
     * Consequentially inserts elements of {@code states} to the top of the operand stack and returns {@code states}.
     */
    public List pushAll(List states)
    {
        states.forEach(frame::push);
        return states;
    }

    /**
     * Empties the operand stack.
     */
    public void clearOperandStack()
    {
        frame.getOperandStack().clear();
    }

    /**
     * Returns an abstract state at the {@code index}th position of the variable array or {@code defaultState} if there is no entry.
     */
    public StateT getVariableOrDefault(int index, StateT defaultState)
    {
        return frame.getVariableOrDefault(index, defaultState);
    }

    /**
     * Sets the {@code index}th position of the variable array to {@code state} and returns {@code state}.
     * If the array has to be extended, the added cells are padded with {@code defaultState}.
     */
    public StateT setVariable(int index, StateT state, StateT defaultState)
    {
        return frame.setVariable(index, state, defaultState);
    }

    /**
     * Returns an abstract state representing the static field {@code fqn} or {@code defaultState} if there is no entry.
     */
    public StateT getStaticOrDefault(String fqn, StateT defaultState)
    {
        return staticFields.getOrDefault(fqn, defaultState);
    }

    /**
     * Sets the static field {@code fqn} to {@code value}.
     */
    public void setStatic(String fqn, StateT value)
    {
        staticFields.put(fqn, value);
    }

    /**
     * Returns an abstract state representing the field {@code descriptor} of the {@code object} or {@code defaultState} if there is no entry.
     */
    public StateT getFieldOrDefault(StateT object, String descriptor, StateT defaultValue)
    {
        return heap.getField(object, descriptor, defaultValue);
    }

    /**
     * Sets the field {@code descriptor}of the {@code object} to {@code value}.
     */
    public void setField(StateT object, String descriptor, StateT value)
    {
        heap.setField(object, descriptor, value);
    }

    /**
     * Returns the frame abstract state.
     */
    public JvmFrameAbstractState getFrame()
    {
        return this.frame;
    }

    /**
     * Returns the static field table abstract state.
     */
    public MapAbstractState getStaticFields()
    {
        return staticFields;
    }

    /**
     * Returns the heap abstract state.
     */
    public JvmHeapAbstractState getHeap()
    {
        return heap;
    }

    /**
     * Returns an abstract state for a new array for the given {@code type} and {@code dimentions}.
     */
    public StateT newArray(String type, List dimensions)
    {
        return heap.newArray(type, dimensions, programLocation);
    }

    /**
     * Returns an abstract state for a new object of the given {@code className}.
     */
    public StateT newObject(String className)
    {
        return heap.newObject(className, programLocation);
    }

    /**
     * Returns an abstract state for the {@code array} element at the given {@code index} or the {@code abstractDefault} if there is no information available.
     */
    public StateT getArrayElementOrDefault(StateT array, StateT index, StateT abstractDefault)
    {
        return heap.getArrayElementOrDefault(array, index, abstractDefault);
    }

    /**
     * Sets the {@code array} element at the given {@code index} to the {@code value}.
     */
    public void setArrayElement(StateT array, StateT index, StateT value)
    {
        heap.setArrayElement(array, index, value);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy