Exemple #1
0
bool printDataflowInfoPass::transfer(const Function& func, const DataflowNode& n, NodeState& state, const vector<Lattice*>& dfInfo)
{
        Dbg::dbg << "-----#############################--------\n";
        Dbg::dbg << "Node: ["<<Dbg::escape(n.getNode()->unparseToString())<<" | "<< n.getNode()->class_name()<<"]\n";
        // print out all the dataflow facts associated with analysis at this node
        
        const /*map <int, NodeFact*>*/vector<NodeFact*> facts = state.getFacts(analysis);
        int i=0;
        for(/*map <int, NodeFact*>*/vector<NodeFact*>::const_iterator it = facts.begin(); it!=facts.end(); it++, i++)
        {
                //Dbg::dbg << "Fact "<<it->first<<": \n    "<<it->second->str("        ")<<endl;
                Dbg::dbg << "Fact "<<i<<": \n    "<<(*it)->str("        ")<<endl;
        }
        
        const vector<Lattice*> dfInfoAbove  = state.getLatticeAbove((Analysis*)analysis);
        const vector<Lattice*> dfInfoBelow  = state.getLatticeBelow((Analysis*)analysis);
        
        vector<Lattice*>::const_iterator itA, itB;
        for(itA = dfInfoAbove.begin(), itB = dfInfoBelow.begin();
            itA != dfInfoAbove.end() && itB != dfInfoBelow.end(); 
            itA++, itB++)
        {
                Dbg::dbg << "    Lattice Above "<<*itA<<": \n    "<<(*itA)->str("        ")<<endl;
                Dbg::dbg << "    Lattice Below "<<*itB<<": \n    "<<(*itB)->str("        ")<<endl;
        }
        
        return dynamic_cast<BoolAndLattice*>(dfInfo[0])->set(true);
}
// advances this iterator in the given direction. Forwards if fwDir=true and backwards if fwDir=false.
// if pushAllChildren=true, all of the current node's unvisited children (predecessors or successors, 
//    depending on fwDir) are pushed onto remainingNodes
void iterator::advance(bool fwDir, bool pushAllChildren)
{
        ROSE_ASSERT(initialized);
        /*printf("   iterator::advance(%d) remainingNodes.size()=%d\n", fwDir, remainingNodes.size());
        cout<<"        visited=\n";
        for(set<DataflowNode>::iterator it=visited.begin(); it!=visited.end(); it++)
                cout << "            <"<<it->getNode()->class_name()<<" | "<<it->getNode()<<" | "<<it->getNode()->unparseToString()<<">\n";*/
        if(remainingNodes.size()>0)
        {
                // pop the next CFG node from the front of the list
                DataflowNode cur = remainingNodes.front();
                remainingNodes.pop_front();
                
                if(pushAllChildren)
                {
                        // find its followers (either successors or predecessors, depending on value of fwDir), push back 
                        // those that have not yet been visited
                        vector<DataflowEdge> nextE;
                        if(fwDir)
                                nextE = cur.outEdges();
                        else
                                nextE = cur.inEdges();
                        for(vector<DataflowEdge>::iterator it=nextE.begin(); it!=nextE.end(); it++)
                        {
                                DataflowNode nextN((*it).target()/* need to put something here because DataflowNodes don't have a default constructor*/);

                                if(fwDir) nextN = (*it).target();
                                else nextN = (*it).source();
                                        
                                /*cout << "      iterator::advance "<<(fwDir?"descendant":"predecessor")<<": "<<
                                                   "<"<<nextN.getNode()->class_name()<<" | "<<nextN.getNode()<<" | "<<nextN.getNode()->unparseToString()<<">, "<<
                                                   "visited="<<(visited.find(nextN) != visited.end())<<
                                                   " remaining="<<isRemaining(nextN)<<"\n";*/
                                
                                // if we haven't yet visited this node and don't yet have it on the remainingNodes list
                                if(visited.find(nextN) == visited.end() &&
                                        !isRemaining(nextN))
                                {
                                        //printf("   pushing back node <%s: 0x%x: %s> visited=%d\n", nextN.getNode()->class_name().c_str(), nextN.getNode(), nextN.getNode()->unparseToString().c_str(), visited.find(nextN)!=visited.end());
                                        remainingNodes.push_back(nextN);
                                }
                        }
                }
                
                // if we still have any nodes left remaining
                if(remainingNodes.size()>0)
                {
                        // take the next node from the front of the list and mark it as visited
                        //visited[remainingNodes.front()] = true;
                        visited.insert(remainingNodes.front());
                }
        }
}
Exemple #3
0
void
TaintAnalysis::genInitState(const Function& func, const DataflowNode& node, const NodeState& state,
                            std::vector<Lattice*>& initLattices, std::vector<NodeFact*>& initFacts) {
    if (debug) {
        *debug <<"TaintAnalysis::genInitState(func=" <<func.get_name() <<",\n"
               <<"                            node={" <<StringUtility::makeOneLine(node.toString()) <<"},\n"
               <<"                            state={" <<StringUtility::makeOneLine(state.str(this, "")) <<"},\n"
               <<"                            initLattice[" <<initLattices.size() <<"]={...},\n"
               <<"                            initFacts[" <<initFacts.size() <<"]={...})\n";
    }
    map<varID, Lattice*> emptyM;
    FiniteVarsExprsProductLattice *prodLat = new FiniteVarsExprsProductLattice(new TaintLattice, emptyM, (Lattice*)NULL,
                                                                                   ldv_analysis, node, state);
    assert(prodLat!=NULL);
    magic_tainted(node.getNode(), prodLat); // certain names are considered to be always tainted
    initLattices.push_back(prodLat);
}
 bool transfer(const Function& func, const DataflowNode& n, NodeState& state, const vector<Lattice*>& dfInfo)
 {
         printf("saveAllDataflow: node=<%s | %s>\n", n.getNode()->class_name().c_str(), n.getNode()->unparseToString().c_str());
         printf("   isSgAddOp(n.getNode()=%p\n", isSgAddOp(n.getNode()));
         bool modified = false;
         if(isSgAddOp(n.getNode()))
         {
                 modified = dynamic_cast<BoolAndLattice*>(dfInfo.at(0))->set(true);
                 modified = dynamic_cast<IntMaxLattice*>(dfInfo.at(1))->incr(1) || modified;
         }
         else
         {
                 //modified = dynamic_cast<BoolAndLattice*>(dfInfo.at(0))->set(false);
                 modified = dynamic_cast<IntMaxLattice*>(dfInfo.at(1))->maximum(0) || modified;
         }
         return modified;
 }
 // This will be visited only once? Not sure, better check
   void
 analysisStatesToDOT::visit(const Function& func, const DataflowNode& n, NodeState& state)
 { 
   std::string state_str = state.str( lda, " ");
   printNode(n, state_str);
   std::vector < DataflowEdge> outEdges = n.outEdges();
   for (unsigned int i = 0; i < outEdges.size(); ++i)
   {
     printEdge(outEdges[i]);
   }
 }
Exemple #6
0
void FindAllFunctionCalls::visit(const Function& func, const DataflowNode& n, NodeState& state)
{
        SgNode* sgn = n.getNode();
        if(analysisDebugLevel>=2){
                Dbg::dbg << "FindAllFunctionCalls::visit() sgn="<<sgn<<"["<<sgn->class_name()<<" | "<<Dbg::escape(sgn->unparseToString())<<"]"<<endl;
        }
        
        // If this is a function call, find the function that is being called and if it is 
        // in funcsToFind, record the call in funcCalls
        if(isSgFunctionCallExp(sgn)) {
                for(set<Function>::const_iterator func=funcsToFind.begin(); func!=funcsToFind.end(); func++) {
                        if((*func).get_declaration() == isSgFunctionCallExp(sgn)->getAssociatedFunctionDeclaration()) {
                                funcCalls[*func].insert(n);
                                break;
                        }
                }
        }
}
Exemple #7
0
void
evaluateAnalysisStates::visit(const Function& func, const DataflowNode& n, NodeState& state)
   {
     SgFunctionCallExp *fnCall = isSgFunctionCallExp(n.getNode());
     if (!fnCall)
          return;

     if (!fnCall->getAssociatedFunctionSymbol()) 
          return;

     string funcName = fnCall->getAssociatedFunctionSymbol()->get_name().getString();
     if (funcName.find("testFunc") == string::npos)
          return;

     FiniteVarsExprsProductLattice *lat = dynamic_cast<FiniteVarsExprsProductLattice *>(state.getLatticeAbove(div)[0]);
     cout << indent << "Lattice before call to " << funcName << ": " << lat->str() << endl;

     set<varID> allVars = lat->getAllVars();
     for (set<varID>::iterator i = allVars.begin(); i != allVars.end(); ++i)
        {
          string name = i->str();
          cout << "Variable " << name << " ";

          if (expectations[funcName].find(name) == expectations[funcName].end())
             {
               cout << "unspecified" << endl;
               continue;
             }

          Lattice *got = lat->getVarLattice(*i);
          ROSE_ASSERT(got);
          if (expectations[funcName][name] != got)
             {
               cout << "mismatched: " << got->str() << " was not the expected " << expectations[funcName][name].str();
               numFails++;
             }
            else
             {
               cout << "matched";
               numPass++;
             }
          cout << endl;
        }
   }
Exemple #8
0
void InitDataflowState::visit(const Function& func, const DataflowNode& n, NodeState& state)
{
        SgNode* sgn = n.getNode();
        if(analysisDebugLevel>=2)
                Dbg::dbg << "InitDataflowState::visit() sgn="<<sgn<<"["<<sgn->class_name()<<" | "<<Dbg::escape(sgn->unparseToString())<<"], dfAnalysis="<<dfAnalysis<<endl;
        
        // generate a new initial state for this node
        vector<Lattice*>  initLats;
        vector<NodeFact*> initFacts;
        dfAnalysis->genInitState(func, n, state, initLats, initFacts);
        
        /*if(analysisDebugLevel>=2){
                int i=0;
                for(vector<Lattice*>::iterator l=initLats.begin(); l!=initLats.end(); l++, i++)
                        Dbg::dbg << "Lattice "<<i<<": "<<(*l)->str("            ")<<endl;
                
                i=0;
                for(vector<NodeFact*>::iterator f=initFacts.begin(); f!=initFacts.end(); f++, i++)
                        Dbg::dbg << "Lattice "<<i<<": "<<(*f)->str("            ")<<endl;
        }*/
                                                    
        //Dbg::dbg << "InitDataflowState::visit() calling state.setLattices()"<<endl;
        state.setLattices((Analysis*)dfAnalysis, initLats);
        state.setFacts((Analysis*)dfAnalysis, initFacts);
        
        if(analysisDebugLevel>=2){
                Dbg::dbg << "    state="<<state.str((Analysis*)dfAnalysis, "    ")<<endl;
        }
        
        /*vector<Lattice*> initState = dfAnalysis->genInitState(func, n, state);
        Dbg::dbg << "InitDataflowState::visit() 1"<<endl;
                        
        for(int i=0; i<initState.size(); i++)
        {
                Dbg::dbg << "                         i="<<i<<", initState[i]="<<initState[i]->str("")<<endl;
                state.addLattice((Analysis*)dfAnalysis, i, initState[i]);
                Dbg::dbg << "                         state->getLatticeAbove((Analysis*)dfAnalysis).size()="<<state.getLatticeAbove((Analysis*)dfAnalysis).size()<<endl, );
                //Dbg::dbg << printf("                         state->getLatticeBelow((Analysis*)dfAnalysis).size()="<<state.getLatticeBelow((Analysis*)dfAnalysis).size()<<endl;
        }*/
        
        //const vector<Lattice*>& masterLatBel = state.getLatticeBelow((Analysis*)dfAnalysis);
        //printf("    creator=%p, state=%p, masterLatBel.size()=%d\n", (Analysis*)dfAnalysis, &state, masterLatBel.size());
}
 void analysisStatesToDOT::printNode(const DataflowNode& n, std::string state_string)
 {
   std::string id = n.id();  // node id
   std::string nodeColor = "black";
 
   if (isSgStatement(n.getNode()))
     nodeColor = "blue";
   else if (isSgExpression(n.getNode()))
     nodeColor = "green";
   else if (isSgInitializedName(n.getNode()))
     nodeColor = "red";
 
   // node_id [label="", color="", style=""]
   (*ostr) << id << " [label=\""  << escapeString(n.toString()) <<"\\n" << escapeString (state_string) << "\", color=\"" << nodeColor <<
     "\", style=\"" << (n.isInteresting()? "solid" : "dotted") << "\"];\n";
 }
Exemple #10
0
void MergeAllReturnStates::visit(const Function& func, const DataflowNode& n, NodeState& state)
{
        SgNode* sgn = n.getNode();
        if(analysisDebugLevel>=1) Dbg::dbg << "MergeAllReturnStates::visit() func="<<func.get_name().getString()<<"() sgn="<<sgn<<"["<<Dbg::escape(sgn->unparseToString())<<" | "<<sgn->class_name()<<"]\n";
        //Dbg::dbg << "visit {{{: modified="<<modified<<endl;
        
        // If this is an explicit return statement
        if(isSgReturnStmt(sgn)) {
                if(analysisDebugLevel>=1)
                        Dbg::dbg << "MergeAllReturnStates::visit() isSgReturnStmt(sgn)->get_expression()="<<isSgReturnStmt(sgn)->get_expression()<<"["<<Dbg::escape(isSgReturnStmt(sgn)->get_expression()->unparseToString())<<" | "<<isSgReturnStmt(sgn)->get_expression()->class_name()<<"]\n";

                ROSE_ASSERT(NodeState::getNodeStates(n).size()==1);
                NodeState* state = *(NodeState::getNodeStates(n).begin());

                // Incorporate the entire dataflow state at the return statement
                if(analysisDebugLevel>=1) Dbg::dbg << "    Merging dataflow state at return statement\n";
                modified = mergeLats(mergedLatsRetStmt, state->getLatticeAbove(analysis)) || modified;

                // Incorporate just the portion of the dataflow state that corresponds to the value being returned,
                // assuming that any information is available
                vector<Lattice*> exprLats;
                for(vector<Lattice*>::const_iterator l=state->getLatticeAbove(analysis).begin(); l!=state->getLatticeAbove(analysis).end(); l++)
                        exprLats.push_back((*l)->project(isSgReturnStmt(sgn)->get_expression()));
                if(analysisDebugLevel>=1) Dbg::dbg << "    Merging dataflow state of return value\n";
                modified = mergeLats(mergedLatsRetVal, exprLats) || modified; 
        }
        // If this is the end of a function, which is an implicit return that has no return value
        else if(isSgFunctionDefinition(sgn)) {
                if(analysisDebugLevel>=1)
                        Dbg::dbg << "MergeAllReturnStates::visit() isSgFunctionDefinition\n";
                
                ROSE_ASSERT(NodeState::getNodeStates(n).size()==1);
                NodeState* state = *(NodeState::getNodeStates(n).begin());
                
                // Incorporate the entire dataflow state at the implicit return statement
                modified = mergeLats(mergedLatsRetStmt, state->getLatticeAbove(analysis)) || modified;
        }
        //Dbg::dbg << "visit >>>: modified="<<modified<<endl;
}
 void visit(const Function& func, const DataflowNode& n, NodeState& state)
 {
         printf("checkAllDataflow: node=<%s | %s>\n", n.getNode()->class_name().c_str(), n.getNode()->unparseToString().c_str());
         /*stringWrapper* s0 = (stringWrapper*)state.getFact(creator, 0);
         stringWrapper* s1 = (stringWrapper*)state.getFact(creator, 1);
         printf("                     fact=<%p | %p>\n", s0, s1);
         printf("                     fact=<%s | %s>\n", s0->myStr.c_str(), s1->myStr.c_str());* /
         if(n.getNode()->class_name() != s0->myStr.c_str())
         {
                 printf("ERROR in checkAllDataflow: Expected class name \"%s\" but the saved class name is \"%s\"\n", n.getNode()->class_name().c_str(), s0->myStr.c_str());
                 numFails++;
         }
         
         if(n.getNode()->unparseToString() != s1->myStr.c_str())
         {
                 printf("ERROR in checkAllDataflow: Expected class name \"%s\" but the saved class name is \"%s\"\n", n.getNode()->unparseToString().c_str(), s0->myStr.c_str());
                 numFails++;
         }*/
         
         printf("                     lattice0 = %s\n", state.getLatticeBelow(creator, 0)->str().c_str());
         printf("                     lattice1 = %s\n", state.getLatticeBelow(creator, 1)->str().c_str());
 }
Exemple #12
0
// Splits the given dataflow analysis partition into several partitions, one for each given checkpoint.
// The partition origA will be assigned the last checkpoint in partitionChkpts.
// If newSplit==true, this split operation creates a new split within origA's current split and place
//    the newly-generated partitions into this split.
// If newSplit==false, the newly-generated partitions will be added to origA's current split.
// If newPartActive==true, the newly-generated partitions will be made initially active. If not,
//    they will start out in joined status.
// Returns the set of newly-created partitions.
set<IntraPartitionDataflow*> PartitionedAnalysis::split(IntraPartitionDataflow* origA,
        vector<IntraPartitionDataflowCheckpoint*> partitionChkpts,
        const Function& func, NodeState* fState,
        bool newSplit, bool newPartActive)
{
    /*printf("PartitionedAnalysis::split() origA=%p\n", origA);

    for(vector<IntraPartitionDataflowCheckpoint*>::iterator it = partitionChkpts.begin();
        it!=partitionChkpts.end(); it++)
    { printf("    chkpt=%s\n", (*it)->str("    ").c_str()); }*/

    ROSE_ASSERT(partitionChkpts.size()>0);
    if(analysisDebugLevel>=1)
    {
        printf("@ SPLIT @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
        printf("PartitionedAnalysis::split() before: activeParts.size()=%d\n", activeParts.size());
    }

    // Only partitions that are either active or joined may call split. Joined partitions may do so during the joining process,
    // which can result in the creation of new partitions.
    ROSE_ASSERT(activeParts.find(origA) != activeParts.end() ||
                joinParts.find(origA) != joinParts.end());

    if(analysisDebugLevel>=1)
        if(origA->partitionCond != NULL)
            cout << "origA->partitionCond = "<<origA->partitionCond->str()<<"\n";
    partSplit* split=NULL;
    if(newSplit)
        split = new partSplit(origA);
    else
        split = *(parts2splits[origA].rbegin());

    if(analysisDebugLevel>=1)
        cout << "split = "<<split->str()<<", partitionChkpts.size()="<<partitionChkpts.size()<<"\n";
    fflush(stdout);

    set<IntraPartitionDataflow*> newParts;

    // Generate the new analysis partitions. The last checkpoint goes to the master
    // partition and we create fresh partitions for the other checkpoints
    for(vector<IntraPartitionDataflowCheckpoint*>::iterator it = partitionChkpts.begin();
            it!=partitionChkpts.end(); )
    {
        IntraPartitionDataflowCheckpoint* chkpt = *it;
        IntraPartitionDataflow* curPartA;

        if(analysisDebugLevel>=1) {
            cout << "    chkpt->partitionCond="<<chkpt->partitionCond<<"\n";
            fflush(stdout);
        }

        it++;

        if(it != partitionChkpts.end())
        {
            curPartA = origA->copy();
            split->addChild(curPartA);
            newParts.insert(curPartA);

            parts2chkpts[curPartA] = chkpt;
            // Create a splits list for this newly-created partition
            // The splits list only contains the split (which may be newly-created or a copy of parts2splits[origA])
            // since it will cease to exist after the next successful join of split
            list<partSplit*> splitsList;
            splitsList.push_back(split);
            parts2splits[curPartA] = splitsList;

            // Set the current partition's logical condition (can't AND it because the variables involved in
            // the condition may have changed between the two split points)
            curPartA->partitionCond = chkpt->partitionCond;
            /*if(origA->partitionCond != NULL)
                    curPartA->partitionCond->andUpd(*(origA->partitionCond));*/
            if(analysisDebugLevel>=1)
                //{ printf("        Creating analysis partition %p (master = %p), condition = %s\n", curPartA, origA, curPartA->partitionCond->str("").c_str()); }
            {
                printf("        Creating analysis partition %p (master = %p)\n", curPartA, origA);
            }

            // create a copy of the original partition's dataflow state for the new partition
            partitionDFAnalysisState pdfas(origA, curPartA);
            pdfas.runAnalysis(func, fState);

            // add the newly-created partition to the list of active partitions
            if(newPartActive)
                activeParts.insert(curPartA);
            else
                joinParts.insert(curPartA);
        }
        else
        {
            //// AND this the first partition's new logical condition to the original partition's condition
            // set the first partition's logical condition (can't AND it because the variables involved in the condition
            // may have changed between the two split points)
            /*printf("origA->partitionCond=%p\n", origA->partitionCond);
            printf("    partitionChkpts[0]=%s\n", partitionChkpts[0]->str("    ").c_str());*/
            //if(parts2chkpts[origA] != NULL)
            /*if(origA->partitionCond != NULL)
            {
                    //parts2chkpts[origA]->partitionCond->andUpd(*(partitionChkpts[0]->partitionCond));
                    origA->partitionCond->andUpd(*(partitionChkpts[0]->partitionCond));

                    if(parts2chkpts[origA])
                            delete parts2chkpts[origA];

                    parts2chkpts[origA] = partitionChkpts[0];

                    // we already have a checkpoint object for the origA partition, so we can delete this new checkpoint
                    // and its internals (i.e. the partitionCond object)
                    //delete partitionChkpts[0];
            }
            else
            {*/
            origA->partitionCond = chkpt->partitionCond;

            // Delete the previous checkpoint, assuming that one exists AND we're not reusing the
            // old checkpoint as the new checkpoint
            if(parts2chkpts[origA] && parts2chkpts[origA]!=chkpt)
                delete parts2chkpts[origA];

            parts2chkpts[origA] = chkpt;

            curPartA = origA;
            //}
            /*if(analysisDebugLevel>=1)
            { printf("        Master partition %p, condition = %s\n", origA, origA->partitionCond->str("").c_str()); }*/
        }

        if(analysisDebugLevel>=1)
        {
            cout << "Updating current partition's dataflow state, parts2chkpts[curPartA]->joinNodes.size()="<<parts2chkpts[curPartA]->joinNodes.size()<<"\n";
            cout << "    curPartA->partitionCond="<<curPartA->partitionCond<<"\n";
            fflush(stdout);
        }
        // -----------------------------------------------------------------------------------------------
        // Update the current partition's current dataflow state (state at the nodes in its joinNodes set)
        // with its new partition condition

        // joinNodes
        /*              cout << "parts2chkpts[curPartA]->joinNodes.size()=" << parts2chkpts[curPartA]->joinNodes.size() << "\n";
                        for(set<DataflowNode>::iterator itJN=parts2chkpts[curPartA]->joinNodes.begin();
                            itJN!=parts2chkpts[curPartA]->joinNodes.end(); itJN++)
                                cout << "    itJN = "<<(*itJN).getNode()->unparseToString()<<"\n";*/

        for(set<DataflowNode>::iterator itJN=parts2chkpts[curPartA]->joinNodes.begin();
                itJN!=parts2chkpts[curPartA]->joinNodes.end(); )
        {
            DataflowNode n = *itJN;

            if(analysisDebugLevel>=1)
            {
                cout << "    joinNode "<<n.getNode()->unparseToString()<<"\n";
                fflush(stdout);
            }
            const vector<NodeState*> nodeStates = NodeState::getNodeStates(n);
            //for(vector<NodeState*>::const_iterator itS = nodeStates.begin(); itS!=nodeStates.end(); )
            vector<NodeState*>::const_iterator itS = nodeStates.begin();
            {
                NodeState* state = *itS;
                Analysis* a = curPartA;
                curPartA->initDFfromPartCond(func, n, *state, state->getLatticeBelow(a), state->getFacts(a), curPartA->partitionCond);
            }
            itJN++;
        }

        // Current Node
        if(parts2chkpts[curPartA]->curNode)
        {
            DataflowNode n = *(parts2chkpts[curPartA]->curNode);
            if(analysisDebugLevel>=1) cout << "    curNode "<<n.getNode()->unparseToString()<<"\n";
            const vector<NodeState*> nodeStates = NodeState::getNodeStates(n);
            //for(vector<NodeState*>::const_iterator itS = nodeStates.begin(); itS!=nodeStates.end(); )
            vector<NodeState*>::const_iterator itS = nodeStates.begin();
            {
                NodeState* state = *itS;
                Analysis* a = curPartA;

                /*ConstrGraph* cg = dynamic_cast<ConstrGraph*>(state->getLatticeBelow(a).front());
                cout << "Pre-initDFfromPartCond CG="<<cg->str()<<"\n";*/

                curPartA->initDFfromPartCond(func, n, *state, state->getLatticeBelow(a), state->getFacts(a), curPartA->partitionCond);
            }
        }
    }

//printf("    partitionChkpts[0]=%s\n", partitionChkpts[0]->str("    ").c_str());
//printf("    parts2chkpts[origA]=%s\n", parts2chkpts[origA]->str("    ").c_str());

    // add the new split to the original partition's list of splits
    if(newSplit)
        parts2splits[origA].push_back(split);

    /*for(set<IntraPartitionDataflow*>::iterator it=split->splitSet.begin();
             it!=split->splitSet.end(); it++)
            printf("        partition %p, partitionCond=%p\n", *it, parts2chkpts[*it]->partitionCond);*/

    if(analysisDebugLevel>=1)
    {
        printf("PartitionedAnalysis::split() after: activeParts.size()=%d\n", activeParts.size());
        printf("@ SPLIT @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
    }

    if(analysisDebugLevel>=1) cout << "newParts.size()=="<<newParts.size()<<"\n";
    return newParts;
}
Exemple #13
0
bool
TaintAnalysis::transfer(const Function& func, const DataflowNode& node_, NodeState& state, const std::vector<Lattice*>& dfInfo) {
    static size_t ncalls = 0;
    if (debug) {
        *debug <<"TaintAnalysis::transfer-" <<++ncalls <<"(func=" <<func.get_name() <<",\n"
               <<"                        node={" <<StringUtility::makeOneLine(node_.toString()) <<"},\n"
               <<"                        state={" <<state.str(this, "                            ") <<",\n"
               <<"                        dfInfo[" <<dfInfo.size() <<"]={...})\n";
    }

    SgNode *node = node_.getNode();
    assert(!dfInfo.empty());
    FiniteVarsExprsProductLattice *prodLat = dynamic_cast<FiniteVarsExprsProductLattice*>(dfInfo.front());
    bool modified = magic_tainted(node, prodLat); // some values are automatically tainted based on their name

    // Process AST nodes that transfer taintedness.  Most of these operations have one or more inputs from which a result
    // is always calculated the same way.  So we just gather up the inputs and do the calculation at the very end of this
    // function.  The other operations are handled individually within their "if" bodies.
    TaintLattice *result = NULL;                    // result pointer into the taint lattice
    std::vector<TaintLattice*> inputs;              // input pointers into the taint lattice
    if (isSgAssignInitializer(node)) {
        // as in "int a = b"
        SgAssignInitializer *xop = isSgAssignInitializer(node);
        TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(SgExpr2Var(xop->get_operand())));
        inputs.push_back(in1);

    } else if (isSgAggregateInitializer(node)) {
        // as in "int a[1] = {b}"
        SgAggregateInitializer *xop = isSgAggregateInitializer(node);
        const SgExpressionPtrList &exprs = xop->get_initializers()->get_expressions();
        for (size_t i=0; i<exprs.size(); ++i) {
            varID in_id = SgExpr2Var(exprs[i]);
            TaintLattice *in = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in_id));
            inputs.push_back(in);
        }

    } else if (isSgInitializedName(node)) {
        SgInitializedName *xop = isSgInitializedName(node);
        if (xop->get_initializer()) {
            varID in1_id = SgExpr2Var(xop->get_initializer());
            TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in1_id));
            inputs.push_back(in1);
        }

    } else if (isSgValueExp(node)) {
        // numeric and character constants
        SgValueExp *xop = isSgValueExp(node);
        result = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(SgExpr2Var(xop)));
        if (result)
            modified = result->set_vertex(TaintLattice::VERTEX_UNTAINTED);
        
    } else if (isSgAddressOfOp(node)) {
        // as in "&x".  The result taintedness has nothing to do with the value in x.
        /*void*/

    } else if (isSgBinaryOp(node)) {
        // as in "a + b"
        SgBinaryOp *xop = isSgBinaryOp(node);
        varID in1_id = SgExpr2Var(isSgExpression(xop->get_lhs_operand()));
        TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in1_id));
        inputs.push_back(in1);
        varID in2_id = SgExpr2Var(isSgExpression(xop->get_rhs_operand()));
        TaintLattice *in2 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in2_id));
        inputs.push_back(in2);

        if (isSgAssignOp(node)) { // copy the rhs lattice to the lhs lattice (as well as the entire '=' expression result)
            assert(in1 && in2);
            modified = in1->meetUpdate(in2);
        }

    } else if (isSgUnaryOp(node)) {
        // as in "-a"
        SgUnaryOp *xop = isSgUnaryOp(node);
        varID in1_id = SgExpr2Var(xop->get_operand());
        TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in1_id));
        inputs.push_back(in1);

    } else if (isSgReturnStmt(node)) {
        // as in "return a".  The result will always be dead, so we're just doing this to get some debugging output.  Most
        // of our test inputs are functions, and the test examines the function's returned taintedness.
        SgReturnStmt *xop = isSgReturnStmt(node);
        varID in1_id = SgExpr2Var(xop->get_expression());
        TaintLattice *in1 = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(in1_id));
        inputs.push_back(in1);

    }


    // Update the result lattice (unless dead) with the inputs (unless dead) by using the meedUpdate() method.  All this
    // means is that the new result will be the maximum of the old result and all inputs, where "maximum" is defined such
    // that "tainted" is greater than "untainted" (and both of them are greater than bottom/unknown).
    for (size_t i=0; i<inputs.size(); ++i)
        if (debug)
            *debug <<"TaintAnalysis::transfer: input " <<(i+1) <<" is " <<lattice_info(inputs[i]) <<"\n";
    if (!result && varID::isValidVarExp(node)) {
        varID result_id(node); // NOTE: constructor doesn't handle all SgExpression nodes, thus the next "if"
        result = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(result_id));
    }
    if (!result && isSgExpression(node)) {
        varID result_id = SgExpr2Var(isSgExpression(node));
        result = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(result_id));
    }
    if (result) {
        for (size_t i=0; i<inputs.size(); ++i) {
            if (inputs[i])
                modified = result->meetUpdate(inputs[i]) || modified;
        }
    }
    if (debug)
        *debug <<"TaintAnalysis::transfer: result is " <<lattice_info(result) <<(modified?" (modified)":" (not modified)") <<"\n";

    return modified;
}
Exemple #14
0
// The transfer function that is applied to SgFunctionCallExp nodes to perform the appropriate state transfers
// fw - =true if this is a forward analysis and =false if this is a backward analysis
// n - the dataflow node that is being processed
// state - The NodeState object that describes the dataflow state immediately before (if fw=true) or immediately after 
//         (if fw=false) the SgFunctionCallExp node, as established by earlier analysis passes
// dfInfo - The Lattices that this transfer function operates on. The function propagates them 
//          to the calling function and overwrites them with the dataflow result of calling this function.
// retState - Pointer reference to a Lattice* vector that will be assigned to point to the lattices of
//          the function call's return value. The callee may not modify these lattices.
// Returns true if any of the input lattices changed as a result of the transfer function and
//    false otherwise.  
bool ContextInsensitiveInterProceduralDataflow::transfer(
                             const Function& func, const DataflowNode& n, NodeState& state, 
                             const vector<Lattice*>& dfInfo, vector<Lattice*>** retState, bool fw)
{
        bool modified = false;
        SgFunctionCallExp* call = isSgFunctionCallExp(n.getNode());
        Function callee(call);
        ROSE_ASSERT(call);
        
        if(analysisDebugLevel > 0)
                Dbg::dbg << "ContextInsensitiveInterProceduralDataflow::transfer "<<func.get_name().getString()<<"()=>"<<callee.get_name().getString()<<"()\n";
        if(callee.get_definition())
        {
                FunctionState* funcS = FunctionState::getDefinedFuncState(callee);
                // The lattices before the function (forward: before=above, after=below; backward: before=below, after=above)
                const vector<Lattice*>* funcLatticesBefore;
                if(fw) funcLatticesBefore = &(funcS->state.getLatticeAbove((Analysis*)intraAnalysis));
                else   funcLatticesBefore = &(funcS->state.getLatticeBelow((Analysis*)intraAnalysis));
                        
                //if(analysisDebugLevel > 0)
                //      printf("        dfInfo.size()=%d, funcLatticesBefore->size()=%d, this=%p\n", dfInfo.size(), funcLatticesBefore->size(), this);
                
                // Update the function's entry/exit state       with the caller's state at the call site
                vector<Lattice*>::const_iterator itCalleeBefore, itCallerBefore;
                for(itCallerBefore = dfInfo.begin(), itCalleeBefore = funcLatticesBefore->begin(); 
                    itCallerBefore!=dfInfo.end() && itCalleeBefore!=funcLatticesBefore->end(); 
                    itCallerBefore++, itCalleeBefore++)
                {
                        Lattice* calleeL = *itCalleeBefore;
                        Lattice* callerL = *itCallerBefore;
                        
                        if(analysisDebugLevel>=1) {
                                Dbg::dbg << "      callerL=["<<calleeL<<"] "<<callerL->str("        ")<<endl;
                                Dbg::dbg << "      Before calleeL=["<<calleeL<<"] "<<calleeL->str("        ")<<endl;
                        }
                        // Create a copy of the current lattice, remapped for the called function's variables
                        Lattice* remappedL = callerL->copy();
                        map<varID, varID> argParamMap;
                        FunctionState::setArgParamMap(call, argParamMap);
                        /*Dbg::dbg << "#argParamMap="<<argParamMap.size()<<endl;
                        for(map<varID, varID>::iterator it = argParamMap.begin(); it!=argParamMap.end(); it++)
                        { printf("argParamMap[%s] = %s \n", it->first.str().c_str(), it->second.str().c_str()); }*/
                        remappedL->remapVars(argParamMap, callee);
                
                        Dbg::dbg << "      remappedL=["<<calleeL<<"] "<<remappedL->str("        ")<<endl;
                        
                        // update the callee's Lattice with the new information at the call site
                        modified = calleeL->meetUpdate(remappedL) || modified;
                        
                        if(analysisDebugLevel>=1)
                                Dbg::dbg << "      After modified = "<<modified << "calleeL=["<<calleeL<<"] "<<calleeL->str("        ")<<endl;
                                        
//!!!           delete remappedL;
                }
                
                // If this resulted in the dataflow information before the callee changing, add it to the remaining list.
                if(modified) {
                        if(analysisDebugLevel > 0)
                                Dbg::dbg << "ContextInsensitiveInterProceduralDataflow::transfer Incoming Dataflow info modified\n";
                        // Record that the callee function needs to be re-analyzed because of new information from the caller
                        TraverseCallGraphDataflow::addToRemaining(getFunc(callee));
                        remainingDueToCallers.insert(getFunc(callee));
                }
                
                // The lattices after the function (forward: before=above, after=below; backward: before=below, after=above).
                const vector<Lattice*>* funcLatticesAfter;
                if(fw) funcLatticesAfter = &(funcS->state.getLatticeBelow((Analysis*)intraAnalysis));
                else   funcLatticesAfter = &(funcS->state.getLatticeAbove((Analysis*)intraAnalysis));
                        
                //Dbg::dbg << "        funcLatticesAfter->size()="<<funcLatticesAfter->size()<<endl;
                if(analysisDebugLevel>=1)
                                Dbg::dbg << "      ----%%%%%%%%%%%%%%%%%%%%---------\n";
                
                // Transfer the result of the function call into the dfInfo Lattices.
                vector<Lattice*>::const_iterator itCalleeAfter, itCallerAfter;
                for(itCallerAfter = dfInfo.begin(), itCalleeAfter = funcLatticesAfter->begin(); 
                    itCallerAfter!=dfInfo.end() && itCalleeAfter!=funcLatticesAfter->end(); 
                    itCallerAfter++, itCalleeAfter++)
                {
                        Lattice* callerL = *itCallerAfter;
                        Lattice* calleeL = *itCalleeAfter;
                        //Dbg::dbg << "      calleeL-after=["<<calleeL<<"] "<<calleeL->str("        ")<<endl;
                        
                        // Create a copy of the current lattice, remapped for the callee function's variables
                        Lattice* remappedL = calleeL->copy();
                        if(analysisDebugLevel>=1)
                                Dbg::dbg << "      remappedL-after=["<<remappedL<<"] "<<calleeL->str("        ")<<endl << remappedL->str(" ")<<endl;
                        map<varID, varID> paramArgByRefMap;
                        FunctionState::setParamArgByRefMap(call, paramArgByRefMap);
                        /*Dbg::dbg << "#paramArgByRefMap="<<paramArgByRefMap.size()<<endl;
                        for(map<varID, varID>::iterator it = paramArgByRefMap.begin(); it!=paramArgByRefMap.end(); it++)
                        { Dbg::dbg << "paramArgByRefMap["<<it->first.str()<<"] = "<<it->second.str()<<endl; */
                        remappedL->remapVars(paramArgByRefMap, func);
                        
                        //Dbg::dbg << "      callerL-after=["<<callerL<<"] "<<callerL->str("        ")<<endl;
                        Dbg::dbg << "      +remappedL-after=["<<remappedL<<"] "<<remappedL->str("        ")<<endl;
                        
                        // update the caller's Lattice with the new information at the call site
                        callerL->incorporateVars(remappedL);
                        
                        if(analysisDebugLevel>=1)
                                Dbg::dbg << "      ==> callerL-after=["<<callerL<<"] "<<callerL->str("        ")<<endl;
                        //Dbg::dbg << "      calleeL-after=["<<calleeL<<"] "<<calleeL->str("        ")<<endl;
                        modified = true;
        //!!!           delete remappedL;
                }
                
                // Point retState to the lattices of the function's return values
                *retState = &(funcS->retState.getLatticeBelowMod((Analysis*)intraAnalysis));
                
                /*Dbg::dbg << "      retState="<<retState<<endl;
                for(vector<Lattice*>::iterator l=(*retState)->begin(); l!=(*retState)->end(); l++)
                        Dbg::dbg << "          "<<(*l)->str("            ")<<endl;*/
        }
        // Don't do anything for functions with no definitions
        else
        {
                
        }
        
        return modified;
}
Exemple #15
0
// Propagates the dataflow info from the current node's NodeState (curNodeState) to the next node's 
//     NodeState (nextNodeState).
// Returns true if the next node's meet state is modified and false otherwise.
bool IntraUniDirectionalDataflow::propagateStateToNextNode(
                      const vector<Lattice*>& curNodeState, DataflowNode curNode, int curNodeIndex,
                      const vector<Lattice*>& nextNodeState, DataflowNode nextNode)
{
        bool modified = false;
        vector<Lattice*>::const_iterator itC, itN;
        if(analysisDebugLevel>=1){
                Dbg::dbg << "\n        Propagating to Next Node: "<<nextNode.getNode()<<"["<<nextNode.getNode()->class_name()<<" | "<<Dbg::escape(nextNode.getNode()->unparseToString())<<"]"<<endl;
                int j;
                for(j=0, itC = curNodeState.begin(); itC != curNodeState.end(); itC++, j++)
                        Dbg::dbg << "        Current node: Lattice "<<j<<": \n            "<<(*itC)->str("            ")<<endl;
                for(j=0, itN = nextNodeState.begin(); itN != nextNodeState.end(); itN++, j++)
                        Dbg::dbg << "        Next/Descendant node: Lattice before propagation "<<j<<": \n            "<<(*itN)->str("            ")<<endl;
        }

        // Update forward info above nextNode from the forward info below curNode.
        
        // Compute the meet of the dataflow information along the curNode->nextNode edge with the 
        // next node's current state one Lattice at a time and save the result above the next node.
        for(itC = curNodeState.begin(), itN = nextNodeState.begin();
            itC != curNodeState.end() && itN != nextNodeState.end(); 
            itC++, itN++)
        {
                // Finite Lattices can use the regular meet operator, while infinite Lattices
                // must also perform widening to ensure convergence.
                if((*itN)->finiteLattice())
                {
                        if(analysisDebugLevel>=1)
                           Dbg::dbg << "        Finite lattice: using regular meetUpdate from current'lattic into next node's lattice... "<<endl;
                        modified = (*itN)->meetUpdate(*itC) || modified;
                }
                else
                {
                        //InfiniteLattice* meetResult = (InfiniteLattice*)itN->second->meet(itC->second);
                        InfiniteLattice* meetResult = dynamic_cast<InfiniteLattice*>((*itN)->copy());
                        Dbg::dbg << "        *itN: " << dynamic_cast<InfiniteLattice*>(*itN)->str("            ") << endl;
                        Dbg::dbg << "        *itC: " << dynamic_cast<InfiniteLattice*>(*itC)->str("            ") << endl;
                        meetResult->meetUpdate(*itC);
                        Dbg::dbg << "        meetResult: " << meetResult->str("            ") << endl;
                
                        // Widen the resulting meet
                        modified =  dynamic_cast<InfiniteLattice*>(*itN)->widenUpdate(meetResult);
                        delete meetResult;
                }
        }
        
        if(analysisDebugLevel>=1) {
                if(modified)
                {
                        Dbg::dbg << "        Next node's lattice *modified* by the propagation. "<<endl;
                        int j=0;
                        for(itN = nextNodeState.begin(); itN != nextNodeState.end(); itN++, j++)
                        {
                                Dbg::dbg << "        Modified lattice "<<j<<": \n            "<<(*itN)->str("            ")<<endl;
                        }
                }
                else
                        Dbg::dbg << "        Next node's lattice is *unchanged* by the propagation. "<<endl;
        }

        return modified;
}