cz.afri.smg.objects.sll.SMGSingleLinkedListConcretisation.java Source code

Java tutorial

Introduction

Here is the source code for cz.afri.smg.objects.sll.SMGSingleLinkedListConcretisation.java

Source

/*
 *  This file is part of SMG, a symbolic memory graph Java library
 *
 *  Copyright (C) 2015 Viktor Malk
 *  All rights reserved.
 *
 *  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 cz.afri.smg.objects.sll;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

import cz.afri.smg.abstraction.SMGConcretisation;
import cz.afri.smg.graphs.ReadableSMG;
import cz.afri.smg.graphs.SMGEdgeHasValue;
import cz.afri.smg.graphs.SMGEdgeHasValueFilter;
import cz.afri.smg.graphs.SMGEdgePointsTo;
import cz.afri.smg.graphs.SMGFactory;
import cz.afri.smg.graphs.SMGValueFactory;
import cz.afri.smg.graphs.WritableSMG;
import cz.afri.smg.objects.SMGRegion;
import cz.afri.smg.types.CPointerType;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

class SMGSingleLinkedListConcretisation implements SMGConcretisation {

    private final SMGSingleLinkedList sll;

    public SMGSingleLinkedListConcretisation(final SMGSingleLinkedList pSll) {
        sll = pSll;
    }

    @SuppressFBWarnings(value = "WMI_WRONG_MAP_ITERATOR", justification = "We need to iterate over keys here")
    @Override
    public final Set<ReadableSMG> execute(final ReadableSMG pSMG) {
        Set<ReadableSMG> resultSet = new HashSet<>();

        WritableSMG newSMG = SMGFactory.createWritableCopy(pSMG);

        // Create new concrete object
        SMGRegion region = new SMGRegion(sll.getSize(), sll.getLabel() + "_element");
        newSMG.addHeapObject(region);

        // Replace all edges pointing to SLL with ones pointing to new region
        Map<SMGEdgePointsTo, SMGEdgePointsTo> toReplace = new HashMap<>();
        for (SMGEdgePointsTo pt : newSMG.getPTEdges()) {
            if (pt.getObject().equals(sll)) {
                SMGEdgePointsTo newPt = new SMGEdgePointsTo(pt.getValue(), region, sll.getOffset());
                toReplace.put(pt, newPt);
            }
        }

        for (SMGEdgePointsTo pt : toReplace.keySet()) {
            newSMG.removePointsToEdge(pt.getValue());
            newSMG.addPointsToEdge(toReplace.get(pt));
        }

        // Create new connection between new region and SLL
        Integer newValue = SMGValueFactory.getNewValue();
        newSMG.addValue(newValue);
        SMGEdgeHasValue newValueHv = new SMGEdgeHasValue(new CPointerType(), sll.getOffset(), region, newValue);
        newSMG.addHasValueEdge(newValueHv);
        SMGEdgePointsTo newValuePt = new SMGEdgePointsTo(newValue, sll, sll.getOffset());
        newSMG.addPointsToEdge(newValuePt);

        if (sll.getLength() > 0) {
            // Shorten SLL
            sll.addLength(-1);
        } else {
            // For SLL of length 0+, there is a case, when it had length 0 and can be
            // removed though
            WritableSMG newSMGWithoutSll = SMGFactory.createWritableCopy(pSMG);

            Integer value;
            if (Iterables.isEmpty(newSMGWithoutSll.getHVEdges(SMGEdgeHasValueFilter.objectFilter(sll)
                    .filterAtOffset(sll.getOffset()).filterByType(CPointerType.getVoidPointer())))) {
                // Create new value
                value = SMGValueFactory.getNewValue();
                newSMGWithoutSll.addValue(value);
            } else {
                // Get outbound edge at binding offset (next pointer of last list item)
                value = newSMGWithoutSll.getUniqueHV(SMGEdgeHasValueFilter.objectFilter(sll)
                        .filterAtOffset(sll.getOffset()).filterByType(CPointerType.getVoidPointer()), false)
                        .getValue();
            }

            for (SMGEdgePointsTo pt : newSMGWithoutSll.getPTEdges()) {
                if (pt.getObject().equals(sll)) {
                    SMGEdgeHasValueFilter filter = new SMGEdgeHasValueFilter().filterHavingValue(pt.getValue());
                    SMGEdgeHasValue oldHv = newSMGWithoutSll.getUniqueHV(filter, false);
                    SMGEdgeHasValue newHv = new SMGEdgeHasValue(CPointerType.getVoidPointer(), sll.getOffset(),
                            oldHv.getObject(), value);
                    newSMGWithoutSll.addHasValueEdge(newHv);
                    newSMGWithoutSll.removeHasValueEdge(oldHv);
                    newSMGWithoutSll.removePointsToEdge(oldHv.getValue());
                    newSMGWithoutSll.removeValue(oldHv.getValue());
                }
            }

            // Remove SLL and all appropriate edges
            SMGEdgeHasValueFilter filter = SMGEdgeHasValueFilter.objectFilter(sll);
            Set<SMGEdgeHasValue> toRemove = Sets.newHashSet(newSMGWithoutSll.getHVEdges(filter));
            for (SMGEdgeHasValue hv : toRemove) {
                newSMGWithoutSll.removeHasValueEdge(hv);
            }
            newSMGWithoutSll.removeHeapObject(sll);

            resultSet.add(newSMGWithoutSll);
        }

        resultSet.add(newSMG);

        return resultSet;
    }

    public final SMGSingleLinkedList getSll() {
        return sll;
    }
}