<commit_before>package soot.dex;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import soot.Body;
import soot.BodyTransformer;
import soot.Local;
import soot.Type;
import soot.Unit;
import soot.Value;
import soot.jimple.ArrayRef;
import soot.jimple.AssignStmt;
import soot.jimple.CastExpr;
import soot.jimple.FieldRef;
import soot.jimple.IdentityStmt;
import soot.jimple.InvokeExpr;
import soot.jimple.NewArrayExpr;
import soot.jimple.Stmt;
import soot.toolkits.graph.ExceptionalUnitGraph;
import soot.toolkits.scalar.LocalDefs;
import soot.toolkits.scalar.LocalUses;
import soot.toolkits.scalar.SimpleLocalUses;
import soot.toolkits.scalar.SmartLocalDefs;
import soot.toolkits.scalar.UnitValueBoxPair;

public abstract class DexTransformer extends BodyTransformer {

  /**
   * Collect definitions of l in body including the definitions of aliases of l.
   *
   * In this context an alias is a local that propagates its value to l.
   *
   * @param l the local whose definitions are to collect
   * @param localDefs the LocalDefs object
   * @param body the body that contains the local
   */
  protected List<Unit> collectDefinitionsWithAliases(Local l, LocalDefs localDefs, LocalUses localUses, Body body) {
      Set<Local> seenLocals = new HashSet<Local>();
      Stack<Local> newLocals = new Stack<Local>();
      List<Unit> defs = new LinkedList<Unit>();
      newLocals.push(l);

      while (!newLocals.empty()) {
          Local local = newLocals.pop();
          System.out.println("[null local] "+ local);
          if (seenLocals.contains(local))
              continue;
          for (Unit u : collectDefinitions(local, localDefs, body)) {
              if (u instanceof AssignStmt) {
                  Value r = ((AssignStmt) u).getRightOp();
                  if (r instanceof Local && ! seenLocals.contains((Local) r))
                      newLocals.push((Local) r);
              }
              defs.add(u);
              //
              for (UnitValueBoxPair pair : (List<UnitValueBoxPair>) localUses.getUsesOf(u)) {
                Unit unit = pair.getUnit();
                if (unit instanceof AssignStmt) {
                  Value right = ((AssignStmt) unit).getRightOp();
                  Value left = ((AssignStmt) unit).getLeftOp();
                  if (right == local  && left instanceof Local && ! seenLocals.contains((Local) left))
                      newLocals.push((Local) left);
                }
              }
              //
          }
          seenLocals.add(local);
      }
      return defs;
  }

  /**
   * Convenience method that collects all definitions of l.
   *
   * @param l the local whose definitions are to collect
   * @param localDefs the LocalDefs object
   * @param body the body that contains the local
   */
  private List<Unit> collectDefinitions(Local l, LocalDefs localDefs, Body body) {
      List <Unit> defs = new LinkedList<Unit>();
      for (Unit u : body.getUnits()) {
          List<Unit> defsOf = localDefs.getDefsOfAt(l, u);
          if (defsOf != null)
              defs.addAll(defsOf);
      }
      for (Unit u: defs) {
        System.out.println("[add def] "+ u);
      }
      return defs;
  }
  
  protected Type findArrayType(ExceptionalUnitGraph g,
      SmartLocalDefs localDefs, SimpleLocalUses localUses, Stmt arrayStmt) {
    ArrayRef aRef = null;
    if (arrayStmt.containsArrayRef()) {
      aRef = arrayStmt.getArrayRef();
    }
    Local aBase = null;
    
    if (null == aRef) {
      if (arrayStmt instanceof AssignStmt) {
        AssignStmt stmt = (AssignStmt)arrayStmt;
        aBase = (Local)stmt.getRightOp();
      } else {
        System.out.println("ERROR: not an assign statement: "+ arrayStmt);
        System.exit(-1);
      }
    } else {    
      aBase = (Local)aRef.getBase();
    }
    
    List<Unit> defsOfaBaseList = localDefs.getDefsOfAt(aBase, arrayStmt);
    if (defsOfaBaseList == null || defsOfaBaseList.size() == 0) {
      System.out.println("ERROR: no def statement found for array base local "+ arrayStmt);
      System.exit(-1);
    }
    
    // We should find an answer only by processing the first item of the list
    Unit baseDef = defsOfaBaseList.get(0);
    
    // baseDef is either an assignment statement or an identity statement
    if (baseDef instanceof AssignStmt) {
      AssignStmt stmt = (AssignStmt) baseDef;
      Value r = stmt.getRightOp();
      if (r instanceof FieldRef) {
        return ((FieldRef) r).getFieldRef().type();
      } else if (r instanceof ArrayRef) {
        ArrayRef ar = (ArrayRef)r;
        if (ar.getType().equals(".unknown")) {
          return findArrayType (g, localDefs, localUses, stmt); //TODO: which type should be returned? //TODO: /!\ loops
        } else {
          return ar.getType();                         
        }
      } else if (r instanceof NewArrayExpr) {
        NewArrayExpr expr = (NewArrayExpr)r;
        return expr.getBaseType();
      } else if (r instanceof CastExpr) {
        return (((CastExpr)r).getCastType());
      } else if (r instanceof InvokeExpr) {
        return ((InvokeExpr) r).getMethodRef().returnType();
        // introduces alias
      } else if (r instanceof Local) {
        return findArrayType (g, localDefs, localUses, stmt);
      } else {
        System.out.println("ERROR: def statement not possible! "+ stmt);
        System.exit(-1);
      }

    } else if (baseDef instanceof IdentityStmt) {
      IdentityStmt stmt = (IdentityStmt)baseDef;
      return stmt.getRightOp().getType();
    } else {
      System.out.println("ERROR: base local def must be AssignStmt or IdentityStmt! "+ baseDef);
      System.exit(-1);
    }

    
    return null;<commit_msg>Corrected Bug: must return type of array element not type of array. <commit_after>package soot.dex;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import soot.ArrayType;
import soot.Body;
import soot.BodyTransformer;
import soot.Local;
import soot.Type;
import soot.Unit;
import soot.Value;
import soot.jimple.ArrayRef;
import soot.jimple.AssignStmt;
import soot.jimple.CastExpr;
import soot.jimple.FieldRef;
import soot.jimple.IdentityStmt;
import soot.jimple.InvokeExpr;
import soot.jimple.NewArrayExpr;
import soot.jimple.Stmt;
import soot.toolkits.graph.ExceptionalUnitGraph;
import soot.toolkits.scalar.LocalDefs;
import soot.toolkits.scalar.LocalUses;
import soot.toolkits.scalar.SimpleLocalUses;
import soot.toolkits.scalar.SmartLocalDefs;
import soot.toolkits.scalar.UnitValueBoxPair;

public abstract class DexTransformer extends BodyTransformer {

  /**
   * Collect definitions of l in body including the definitions of aliases of l.
   *
   * In this context an alias is a local that propagates its value to l.
   *
   * @param l the local whose definitions are to collect
   * @param localDefs the LocalDefs object
   * @param body the body that contains the local
   */
  protected List<Unit> collectDefinitionsWithAliases(Local l, LocalDefs localDefs, LocalUses localUses, Body body) {
      Set<Local> seenLocals = new HashSet<Local>();
      Stack<Local> newLocals = new Stack<Local>();
      List<Unit> defs = new LinkedList<Unit>();
      newLocals.push(l);

      while (!newLocals.empty()) {
          Local local = newLocals.pop();
          System.out.println("[null local] "+ local);
          if (seenLocals.contains(local))
              continue;
          for (Unit u : collectDefinitions(local, localDefs, body)) {
              if (u instanceof AssignStmt) {
                  Value r = ((AssignStmt) u).getRightOp();
                  if (r instanceof Local && ! seenLocals.contains((Local) r))
                      newLocals.push((Local) r);
              }
              defs.add(u);
              //
              for (UnitValueBoxPair pair : (List<UnitValueBoxPair>) localUses.getUsesOf(u)) {
                Unit unit = pair.getUnit();
                if (unit instanceof AssignStmt) {
                  Value right = ((AssignStmt) unit).getRightOp();
                  Value left = ((AssignStmt) unit).getLeftOp();
                  if (right == local  && left instanceof Local && ! seenLocals.contains((Local) left))
                      newLocals.push((Local) left);
                }
              }
              //
          }
          seenLocals.add(local);
      }
      return defs;
  }

  /**
   * Convenience method that collects all definitions of l.
   *
   * @param l the local whose definitions are to collect
   * @param localDefs the LocalDefs object
   * @param body the body that contains the local
   */
  private List<Unit> collectDefinitions(Local l, LocalDefs localDefs, Body body) {
      List <Unit> defs = new LinkedList<Unit>();
      for (Unit u : body.getUnits()) {
          List<Unit> defsOf = localDefs.getDefsOfAt(l, u);
          if (defsOf != null)
              defs.addAll(defsOf);
      }
      for (Unit u: defs) {
        System.out.println("[add def] "+ u);
      }
      return defs;
  }
  
  protected Type findArrayType(ExceptionalUnitGraph g,
      SmartLocalDefs localDefs, SimpleLocalUses localUses, Stmt arrayStmt) {
    ArrayRef aRef = null;
    if (arrayStmt.containsArrayRef()) {
      aRef = arrayStmt.getArrayRef();
    }
    Local aBase = null;
    
    if (null == aRef) {
      if (arrayStmt instanceof AssignStmt) {
        AssignStmt stmt = (AssignStmt)arrayStmt;
        aBase = (Local)stmt.getRightOp();
      } else {
        System.out.println("ERROR: not an assign statement: "+ arrayStmt);
        System.exit(-1);
      }
    } else {    
      aBase = (Local)aRef.getBase();
    }
    
    List<Unit> defsOfaBaseList = localDefs.getDefsOfAt(aBase, arrayStmt);
    if (defsOfaBaseList == null || defsOfaBaseList.size() == 0) {
      System.out.println("ERROR: no def statement found for array base local "+ arrayStmt);
      System.exit(-1);
    }
    
    // We should find an answer only by processing the first item of the list
    Unit baseDef = defsOfaBaseList.get(0);
    
    // baseDef is either an assignment statement or an identity statement
    if (baseDef instanceof AssignStmt) {
      AssignStmt stmt = (AssignStmt) baseDef;
      Value r = stmt.getRightOp();
      if (r instanceof FieldRef) {
        return ((FieldRef) r).getFieldRef().type();
      } else if (r instanceof ArrayRef) {
        ArrayRef ar = (ArrayRef)r;
        if (ar.getType().equals(".unknown")) {
          return findArrayType (g, localDefs, localUses, stmt); //TODO: which type should be returned? //TODO: /!\ loops
        } else {
          return ar.getType();                         
        }
      } else if (r instanceof NewArrayExpr) {
        NewArrayExpr expr = (NewArrayExpr)r;
        return expr.getBaseType();
      } else if (r instanceof CastExpr) {
        return (((CastExpr)r).getCastType());
      } else if (r instanceof InvokeExpr) {
        return ((InvokeExpr) r).getMethodRef().returnType();
        // introduces alias
      } else if (r instanceof Local) {
        return findArrayType (g, localDefs, localUses, stmt);
      } else {
        System.out.println("ERROR: def statement not possible! "+ stmt);
        System.exit(-1);
      }

    } else if (baseDef instanceof IdentityStmt) {
      IdentityStmt stmt = (IdentityStmt)baseDef;
      ArrayType at = (ArrayType) stmt.getRightOp().getType();
      return at.getArrayElementType();
    } else {
      System.out.println("ERROR: base local def must be AssignStmt or IdentityStmt! "+ baseDef);
      System.exit(-1);
    }

    
    return null;
{'fraction_non_alphanumeric': 0.10907377259874904, 'fraction_numerical': 0.0010281895296032901, 'mean_word_length': 2.456322179449215, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '906755', 'n_tokens_mistral': 3519, 'n_tokens_neox': 3471, 'n_words': 949}