Esempio n. 1
0
    /// <summary>
    /// Refines the given state according to the knowledge stored in the egraph about sv
    /// 
    /// In addition, the state can be null when the knowledge is inconsistent.
    /// </summary>
    /// <param name="cv">symbolic value we assume to be null (false)</param>
    private static void AssumeFalse(ISymValue cv, ref NonNullState state) {
      if (state == null) return;

      if (state.IsNonNull(cv)) {
        // infeasible
        // but we still want to go on analyzing this branch.

        state = null;
        return;
      }

      if (state.IsNull(cv)) return;

      foreach(EGraphTerm t in state.egraph.EqTerms(cv)) {
        if (t.Function == NonNullState.EqNullId) {
          // EqNull(op) == false, therefore op != null
          ISymValue op = t.Args[0];
          AssumeTrue(op, ref state);
        }
        if (t.Function == NonNullState.NeNullId) {
          // NeNull(op) == false, therefore op == null
          ISymValue op = t.Args[0];
          AssumeFalse(op, ref state);
        }
        if (t.Function == NonNullState.LogicalNegId) {
          // Not(op) == false, therefore op == true
          ISymValue op = t.Args[0];
          AssumeTrue(op, ref state);
        }
        if (t.Function == NonNullState.IsInstId) {
          // IsInst(op) == null, cannot deduce anything about op
        }
      }
      // needs to be after we check EqTerms, as they verify mapping is current.
      if (state != null) state.AssumeNull(cv);
    }
Esempio n. 2
0
    /// <summary>
    /// Refines the given state according to the knowledge stored in the egraph about sv
    /// 
    /// In addition, the state can be null when the knowledge is inconsistent.
    /// </summary>
    /// <param name="cv">symbolic value we assume to be non-null (true)</param>
    /// <param name="state">state if sv is non-null (true)</param>
    private static void AssumeTrue(ISymValue cv, ref NonNullState state) {

      if (state == null) return;

      if (state.IsNull(cv)) {
        // infeasible
        state = null;
        return;
      }

      if (state.IsNonNull(cv)) return;

      state.egraph[cv] = Lattice.AVal.NonNull;

      foreach(EGraphTerm t in state.egraph.EqTerms(cv)) {
        if (t.Function == NonNullState.EqNullId) {
          ISymValue op = t.Args[0];
          AssumeFalse(op, ref state);
        }
        if (t.Function == NonNullState.NeNullId) {
          ISymValue op = t.Args[0];
          AssumeTrue(op, ref state);
        }
        if (t.Function == NonNullState.LogicalNegId) {
          ISymValue op = t.Args[0];
          AssumeFalse(op, ref state);
        }
        if (t.Function == NonNullState.IsInstId) {
          ISymValue op = t.Args[0];
          AssumeTrue(op, ref state);
        }
      }
    }
Esempio n. 3
0
    /// <summary>
    /// Returns null, if result of Join is the same as atMerge.
    /// </summary>
    public static NonNullState Join(NonNullState atMerge, NonNullState incoming, CfgBlock joinPoint) {

      bool unchanged;
      IEGraph merged = atMerge.egraph.Join(incoming.egraph, joinPoint, out unchanged);

      TypeNode currentException = (atMerge.currentException != null)?
        ((incoming.currentException != null)? CciHelper.LeastCommonAncestor(atMerge.currentException, incoming.currentException) : null) : null;

      if (atMerge.currentException != currentException || !unchanged) {
        return new NonNullState(merged, currentException, atMerge.typeSystem);
      }
      return null;
    }
Esempio n. 4
0
    public void RefineBranchInformation(Variable cond, out NonNullState trueState, out NonNullState falseState) {

      ISymValue cv = Value(cond);

      trueState = new NonNullState(this);
      falseState = new NonNullState(this);

      AssumeTrue(cv, ref trueState);
      AssumeFalse(cv, ref falseState);
    }
Esempio n. 5
0
 public NonNullState(NonNullState old){
   this.typeSystem = old.typeSystem;
   this.egraph = (IEGraph)old.egraph.Clone();  
   this.currentException = old.currentException;
   // this.existDelayInfo = old.ExistDelayInfo;
 }
Esempio n. 6
0
      /// <summary>
      /// Enforcement of once attributes: Check if the field is written more than one
      /// and also allow to write it if it was null before
      /// If required a to register the field mutated at the class level (FieldUsage in Analyzer)
      /// </summary>
      /// <param name="dest"></param>
      /// <param name="field"></param>
      /// <param name="stat"></param>
      /// <param name="nn"></param>
    private void CheckFieldOnceness(Variable dest, Field field, Statement stat, NonNullState nn)
    {
      IMutableSet fieldUsage = this.NNChecker.analyzer.FieldUsage;
      if (field.IsOnce && fieldUsage != null) {
        if (!fieldUsage.Contains(field)) {
          fieldUsage.Add(field);

          if (!nn.IsFieldNull(this.NNChecker, dest, field) && !this.ts.IsNullableType(field.Type)) { //hack
            // Need to add a new type of error
            HandleError(stat, stat, Error.GenericWarning, "[Once] fields can be written only if null");
          }
        }
        else {
          // Need to add a new type of error
          HandleError(stat, stat, Error.GenericWarning, "[Once] fields can be written only once.");
        }

      }
    }
Esempio n. 7
0
 private NonNullState PushNullException(NonNullState nn) {
   NonNullState exnState = nn;
   nn = new NonNullState(nn);
   exnState.currentException=SystemTypes.NullReferenceException;
   NNChecker.PushExceptionState(NNChecker.currBlock, exnState);
   return nn;
 }
Esempio n. 8
0
    protected override object VisitCall(Variable dest, Variable receiver, Method callee, ExpressionList arguments, bool virtcall, Statement stat, object arg) {
      NonNullState nn=(NonNullState)arg;

      bool resultIsNonNull = false;

      // Check for Receiver
      if (!callee.IsStatic)
        CheckReceiver(stat,receiver,nn);


      // Check for parameter matching.
      if (arguments!=null && callee.Parameters != null){
        for(int i=0;i<callee.Parameters.Count;i++){
          Variable actual = (Variable)arguments[i];
          if (ts.IsNonNullType(callee.GetParameterTypes()[i])) {
            if(nn.IsNull(actual)) {
              HandleError(stat, actual, Error.CannotCoerceNullToNonNullType);
            }
            else if(!nn.IsNonNull(actual)) {
              //System.Console.WriteLine("visit call, argument: {0}", actual);
              HandleError(stat, actual, Error.CoercionToNonNullTypeMightFail, callee.GetParameterTypes()[i]);
            }
          }
          nn.HavocIndirect(actual, callee.Parameters[i].Type as Reference);
        }
      }

      // special case some methods
      if (this.IsAssertionMethodThatDoesNotReturn(callee)) {
        // we assume that all assertion methods are called with false.
        return null;
      }
      else if (this.NNChecker.IsAssertNotNullImplicitMethod(callee)) {
        if (arguments.Count == 1){
          Variable source = (Variable)arguments[0]; // guaranteed by CodeFlattener
          // compiler inserts this test throughout, so let's warn here.
          if (nn.IsNonNull(source)) {
            // opportunity to optimize away check.
            RecordUnnecessaryCheck(stat);
            // Console.WriteLine("Could optimize IsNonNull check at line {0}", stat.SourceContext.StartLine);
          }
          else {
            RecordNecessaryCheck(stat);
            if (nn.IsNull(source)) {
              HandleError(stat, source, Error.CannotCoerceNullToNonNullType);
              // do not explore this path further, except for exceptional path
              PushNullException(nn);
              return null;
            }
            else {
              //System.Console.WriteLine("visit call and callee is assertnotnullimplicitmethod");
              HandleError(stat, source, Error.CoercionToNonNullTypeMightFail, 
                OptionalModifier.For(SystemTypes.NonNullType, source.Type));
            }
          }
          nn = PushNullException(nn);
          nn.AssumeNonNull(source);
        }
      }
      else if (NNChecker.IsAssertNotNullMethod(callee)) {
        if (arguments.Count == 1){
          Variable source = (Variable)arguments[0]; // guaranteed by CodeFlattener
          // User inserted cast, so let's warn if it is unnecessary.
          if (nn.IsNonNull(source)) {
            // Let user know his check is useless here.
            RecordUnnecessaryCheck(stat);
            // Console.WriteLine("Could optimize IsNonNull check at line {0}", stat.SourceContext.StartLine);
          }
          else {
            RecordNecessaryCheck(stat);
            if (nn.IsNull(source)) {
              // Error already emitted at checker time. HandleError(stat, source, Error.CannotCoerceNullToNonNullType);
              // do not explore this path further except for exceptional path
              PushNullException(nn);
              return null;
            }
          }

          nn = PushNullException(nn);
          nn.AssumeNonNull(source);
        }
      }
      else if ( callee.Name.Name == "GetEnumerator" ) {
        // special case assume result is non-null because it is in generated code and confuses.
        if (dest != null) {
          nn.AssignNonNull(dest);
          dest = null; // avoid setting dest again below.
        }
      }
      else if (callee == GetTypeFromHandleMethod) {
        // special case that should be handled by annotating mscorlib
        if (dest != null) {
          nn.AssignNonNull(dest);
          dest = null; // avoid setting dest again below
        }
      }
      else {
        Property pget = IsPropertyGetter(callee);
        if (pget != null) {
          resultIsNonNull = nn.LoadProperty(receiver, pget, dest);
          dest = null; // prevent remaining code to overwrite dest
        }
        else {
          Property pset = IsPropertySetter(callee);
          if (pset != null) {
            nn.StoreProperty(receiver, pset, (Variable)arguments[0]);
          }
          else if (!callee.IsPure) {
            // Non-pure method: assume it destroy all heap patterns.
            nn.HavocHeap();
          }
        }
      }

      // Push possible exceptions to handlers.
      if (callee.Contract != null) {
        for (int i = 0; i < callee.Contract.Ensures.Count; i++) {
          EnsuresExceptional e = callee.Contract.Ensures[i] as EnsuresExceptional;
          if (e != null) {
            NonNullState exnState = nn;
            nn = new NonNullState(nn);
            exnState.currentException = e.Type;
            NNChecker.PushExceptionState(NNChecker.currBlock, exnState);
          }
        }
      }


      // Return type matching.
      if(dest!=null){
        if (nn.IsNonNullType(dest.Type) && ! (resultIsNonNull || nn.IsNonNullType(callee.ReturnType))) {
          if (!(callee.DeclaringMember is Property))
            HandleError(stat, stat, Error.CoercionToNonNullTypeMightFail,dest.Type);
          nn.AssignNonNull(dest);
        }
        else {
            nn.AssignAccordingToType(dest, callee.ReturnType);
        }
      }
      return nn;
    }
Esempio n. 9
0
    /// <summary>
    /// Note: casts don't require a non-null argument. null value casts always succeed.
    /// </summary>
    protected override object VisitCastClass(Variable dest, TypeNode type, Variable source, Statement stat, object arg) {
      NonNullState nn = (NonNullState)arg;

      if ( ! nn.IsNull(source)) {
        NonNullState exnState = nn;
        nn = new NonNullState(nn); // make copy of current state to continue modify
        exnState.currentException=SystemTypes.InvalidCastException;
        NNChecker.PushExceptionState(NNChecker.currBlock, exnState);
      }

      // acts like a copy retaining null status
      nn.CopyVariable(source, dest);

      if(nn.IsNonNullType(dest.Type) && ! nn.IsNonNull(source)) {
        if(nn.IsNull(source))
          HandleError(stat, source, Error.CannotCoerceNullToNonNullType);
        else {
          //System.Console.WriteLine("visit cast class: dest:{0}, source:{1}", dest, source);
          HandleError(stat, source, Error.CoercionToNonNullTypeMightFail,dest.Type);
        };
        // mask future errors
        nn.AssignNonNull(dest);
      }
      return nn;
    }
Esempio n. 10
0
    private void CheckPointerUse(Statement stat, Variable v, NonNullState nn, string purpose)
    {
      if (v == null) return;

      if(nn.IsNull(v))
      {
        HandleError(stat, v, Error.UseOfNullPointer, purpose);
        nn.AssignNonNull(v);
      }
      else if(!nn.IsNonNull(v))
      {
        HandleError(stat, v, Error.UseOfPossiblyNullPointer, purpose);
        nn.AssumeNonNull(v);
      }
    }
Esempio n. 11
0
    private void CheckReceiver(Statement stat, Variable v, NonNullState nn, Node node)
    {
      Node offendingNode = v;
      if (v == null) return;
      if (v.Type.IsValueType) return;

      // Create a better source context for receiver null errors.
      offendingNode = new Statement(NodeType.Nop);
      offendingNode.SourceContext = v.SourceContext;
 //     offendingNode.SourceContext.StartPos = offendingNode.SourceContext.EndPos;
 //     offendingNode.SourceContext.EndPos++;

      if(nn.IsNull(v))
      {
        HandleError(stat, offendingNode, Error.ReceiverCannotBeNull, this.ts.GetTypeName(v.Type));
        nn.AssignNonNull(v);
      }
      else if(!nn.IsNonNull(v))
      {
        HandleError(stat, offendingNode, Error.ReceiverMightBeNull, this.ts.GetTypeName(v.Type));
        nn.AssumeNonNull(v);
      }
    }
Esempio n. 12
0
    /// <summary>
    /// It split exceptions for current handler and the next chained handler.
    /// 
    /// It will:
    /// 
    ///   If the exception is completely intercepted by current handler, the
    ///   exception will be consumed.
    ///   
    ///   If the exception caught but not completely, both current handler and 
    ///   the next handler will take the states.
    ///   
    ///   If the exception is irrelevant to current caught, the next handler 
    ///   will take over the state. Current handler is then bypassed.
    /// </summary>
    /// <param name="handler"></param>
    /// <param name="currentHandlerState"></param>
    /// <param name="nextHandlerState"></param>
    protected override void SplitExceptions(CfgBlock handler, ref IDataFlowState currentHandlerState, out IDataFlowState nextHandlerState) {

      Debug.Assert(currentHandlerState!=null,"Internal error in NonNull Analysis");

      NonNullState state = (NonNullState)currentHandlerState;

      if(handler==null || handler.Length==0){
        nextHandlerState=null;
        return;
      }

      if(handler[0] is Unwind){
        nextHandlerState=null;
        currentHandlerState=null;
        return;
      }

      Debug.Assert(handler[0] is Catch, "Exception Handler does not starts with Catch");
      
      Debug.Assert(state.currentException!=null,"No current exception to handle");
      
      Catch c=(Catch)handler[0];

      if(handler.ExceptionHandler!=null && 
        !state.currentException.IsAssignableTo(c.Type)) {
        nextHandlerState = state;;
      }
      else {
        nextHandlerState=null;
      }

      // Compute what trickles through to the next handler
      //  and what sticks to this handler.
      if(state.currentException.IsAssignableTo(c.Type)) {
        // everything sticks 
        nextHandlerState = null;
      }
      else if (c.Type.IsAssignableTo(state.currentException)) {
        // c sticks, rest goes to next handler
        nextHandlerState = state;

        // copy state to modify the currentException
        state = new NonNullState(state);
        state.currentException = c.Type;
        currentHandlerState = state;
      }else {
        // nothing stick all goes to next handler
        nextHandlerState = state;
        currentHandlerState = null;
      }
      return;
    }
Esempio n. 13
0
    /// <summary>
    /// Implementation of visit Block. It is called from run.
    /// 
    /// It calls VisitStatement.
    /// </summary>
    /// <param name="block"></param>
    /// <param name="stateOnEntry"></param>
    /// <returns></returns>
    protected override IDataFlowState VisitBlock(CfgBlock block, IDataFlowState stateOnEntry) {
      Debug.Assert(block!=null);

      currBlock=block;

      Analyzer.Write("---------block: "+block.UniqueId+";");
      Analyzer.Write("   Exit:");
      foreach (CfgBlock b in block.NormalSuccessors)
        Analyzer.Write(b.UniqueId+";");
      if (block.UniqueSuccessor!=null)
        Analyzer.Write("   FallThrough: "+block.UniqueSuccessor+";");
      if (block.ExceptionHandler!=null)
        Analyzer.Write("   ExHandler: "+block.ExceptionHandler.UniqueId+";");
      Analyzer.WriteLine("");

      NonNullState newState; 
      if(stateOnEntry==null)
        newState=new NonNullState(typeSystem,null);
      else
        newState=new NonNullState((NonNullState)stateOnEntry);

      return base.VisitBlock (block, newState);
    }