예제 #1
0
 public PhoneMethodInliningMetadataTraverser(PhoneCodeHelper phoneHelper)
 {
     methodsToInline     = new HashSet <IMethodDefinition>();
     iterMethodsToInline = new HashSet <IMethodDefinition>();
     this.phoneHelper    = phoneHelper;
     TotalMethodsCount   = 0;
 }
예제 #2
0
 // TODO same here. Are there specific methods (and ways to identfy those) that can perform navigation?
 public override void TraverseChildren(IMethodDefinition method)
 {
     if (PhoneCodeHelper.instance().isBackKeyPressOverride(method))
     {
         PhoneCodeHelper.instance().KnownBackKeyHandlers.Add(method);
         PhoneCodeHelper.instance().OnBackKeyPressOverriden = true;
     }
     base.TraverseChildren(method);
 }
예제 #3
0
        private bool isCancelOnBackKeyPressHandler(IMethodCall call)
        {
            if (!PhoneCodeHelper.instance().isBackKeyPressOverride(methodTraversed.ResolvedMethod))
            {
                return(false);
            }

            return(isEventCancellationMethodCall(call));
        }
        public static PhoneCodeHelper instance()
        {
            if (_instance == null)
            {
                _instance = new PhoneCodeHelper(host);
            }

            return(_instance);
        }
예제 #5
0
 /// <summary>
 /// Check if the type being defined is a PhoneApplicationPage, uninteresting otherwise
 /// </summary>
 ///
 public override void TraverseChildren(ITypeDefinition typeDefinition)
 {
     if (typeDefinition.isPhoneApplicationClass(host))
     {
         PhoneCodeHelper.instance().setMainAppTypeReference(typeDefinition);
     }
     else if (typeDefinition.isPhoneApplicationPageClass(host))
     {
         base.TraverseChildren(typeDefinition);
     }
 }
예제 #6
0
 public override void TraverseChildren(IMethodDefinition method)
 {
     this.methodTraversed = method;
     if (method.IsConstructor && PhoneTypeHelper.isPhoneApplicationClass(typeTraversed, host))
     {
         navigationCallers.Add(method);
         string           mainPageUri = PhoneCodeHelper.instance().PhonePlugin.getMainPageXAML();
         SourceMethodBody sourceBody  = method.Body as SourceMethodBody;
         if (sourceBody != null)
         {
             BlockStatement bodyBlock = sourceBody.Block as BlockStatement;
             if (bodyBlock != null)
             {
                 Assignment uriInitAssign = new Assignment()
                 {
                     Source = new CompileTimeConstant()
                     {
                         Type  = host.PlatformType.SystemString,
                         Value = UriHelper.getURIBase(mainPageUri),
                     },
                     Type   = host.PlatformType.SystemString,
                     Target = new TargetExpression()
                     {
                         Type = host.PlatformType.SystemString,
                         // TODO unify code for current uri fieldreference
                         Definition = new FieldReference()
                         {
                             ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(),
                             IsStatic       = true,
                             Type           = host.PlatformType.SystemString,
                             Name           = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
                             InternFactory  = host.InternFactory,
                         },
                     },
                 };
                 Statement uriInitStmt = new ExpressionStatement()
                 {
                     Expression = uriInitAssign,
                 };
                 bodyBlock.Statements.Insert(0, uriInitStmt);
             }
         }
     }
     base.TraverseChildren(method);
 }
        public override void TraverseChildren(IMethodCall methodCall)
        {
            if (PhoneCodeHelper.instance().PhoneFeedbackToggled)
            {
                // check for handlers we do not wish to add feedback checks to
                if (methodCall.MethodToCall.Name.Value.StartsWith("add_"))
                {
                    string eventName = methodCall.MethodToCall.Name.Value.Remove(0, "add_".Length);
                    if (PhoneCodeHelper.IgnoredEvents.Contains(eventName))
                    {
                        IMethodReference eventHandler = null;
                        foreach (IExpression arg in methodCall.Arguments)
                        {
                            ICreateDelegateInstance createDelegate = arg as ICreateDelegateInstance;
                            if (createDelegate == null)
                            {
                                continue;
                            }

                            ITypeReference typeRef = createDelegate.Type;
                            if (!typeRef.isRoutedEventHandlerClass(host))
                            {
                                continue;
                            }

                            eventHandler = createDelegate.MethodToCallViaDelegate;
                            break;
                        }

                        if (eventHandler != null)
                        {
                            INamespaceTypeReference namedType = eventHandler.ContainingType.ResolvedType as INamespaceTypeReference;
                            if (namedType != null)
                            {
                                INamespaceTypeDefinition namedTypeDef = namedType.ResolvedType;
                                if (namedTypeDef != null)
                                {
                                    PhoneCodeHelper.instance().ignoreEventHandler(namedTypeDef.ContainingUnitNamespace.Name + "." + namedTypeDef.Name + "." + eventHandler.Name);
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #8
0
        private void injectPhoneInitializationCode(BlockStatement block, Statement statementAfter)
        {
            // TODO check page name against container name
            IEnumerable <ControlInfoStructure> controls           = PhoneCodeHelper.instance().PhonePlugin.getControlsForPage(methodBeingTraversed.Container.ToString());
            IEnumerable <IStatement>           injectedStatements = new List <IStatement>();

            if (controls != null)
            {
                foreach (ControlInfoStructure controlInfo in controls)
                {
                    injectedStatements = injectedStatements.Concat(getCodeForSettingEnabledness(controlInfo));
                    injectedStatements = injectedStatements.Concat(getCodeForSettingCheckedState(controlInfo));
                    injectedStatements = injectedStatements.Concat(getCodeForSettingVisibility(controlInfo));
                }

                int stmtPos = block.Statements.IndexOf(statementAfter);
                block.Statements.InsertRange(stmtPos + 1, injectedStatements);
            }
        }
        public IMethodReference getUriHavocerMethod(Sink sink)
        {
            if (uriHavocMethod == null)
            {
                MethodBody       body     = new MethodBody();
                MethodDefinition havocDef = new MethodDefinition()
                {
                    InternFactory            = host.InternFactory,
                    ContainingTypeDefinition = PhoneCodeHelper.instance().getMainAppTypeReference().ResolvedType,
                    IsStatic = true,
                    Name     = sink.host.NameTable.GetNameFor(PhoneCodeHelper.BOOGIE_DO_HAVOC_CURRENTURI),
                    Type     = sink.host.PlatformType.SystemVoid,
                    Body     = body,
                };
                body.MethodDefinition = havocDef;
                uriHavocMethod        = havocDef;
            }

            return(uriHavocMethod);
        }
예제 #10
0
        private bool isNavigationOnBackKeyPressHandler(IMethodCall call, out string target)
        {
            target = null;
            if (!PhoneCodeHelper.instance().isBackKeyPressOverride(methodTraversed.ResolvedMethod))
            {
                return(false);
            }

            if (!call.MethodToCall.ContainingType.isNavigationServiceClass(host))
            {
                return(false);
            }

            if (!PhoneCodeHelper.NAV_CALLS.Contains(call.MethodToCall.Name.Value) || call.MethodToCall.Name.Value == "GoBack") // back is actually ok
            {
                return(false);
            }

            if (call.MethodToCall.Name.Value == "Navigate")
            {
                try {
                    IExpression expr     = call.Arguments.First();
                    bool        isStatic = UriHelper.isArgumentURILocallyCreatedStatic(expr, host, out target) ||
                                           UriHelper.isArgumentURILocallyCreatedStaticRoot(expr, host, out target);
                    if (!isStatic)
                    {
                        target = "--Other non inferrable target--";
                    }
                    else
                    {
                        target = UriHelper.getURIBase(target);
                    }
                } catch (InvalidOperationException) {
                }
            }

            return(true);
        }
예제 #11
0
        private void injectNavigationUpdateCode(IBlockStatement block, IEnumerable <Tuple <IStatement, StaticURIMode, string> > staticStmts, IEnumerable <IStatement> nonStaticStmts)
        {
            // TODO Here there is the STRONG assumption that a given method will only navigate at most once per method call
            // TODO (or at most will re-navigate to the same page). Quick "page flipping" on the same method
            // TODO would not be captured correctly
            Microsoft.Cci.MutableCodeModel.BlockStatement mutableBlock = block as Microsoft.Cci.MutableCodeModel.BlockStatement;

            foreach (IStatement stmt in nonStaticStmts)
            {
                int ndx = mutableBlock.Statements.ToList().IndexOf(stmt);
                if (ndx == -1)
                {
                    // can't be
                    throw new IndexOutOfRangeException("Statement must exist in original block");
                }

                Assignment currentURIAssign = new Assignment()
                {
                    Source = new CompileTimeConstant()
                    {
                        Type  = host.PlatformType.SystemString,
                        Value = PhoneCodeHelper.BOOGIE_DO_HAVOC_CURRENTURI,
                    },
                    Type   = host.PlatformType.SystemString,
                    Target = new TargetExpression()
                    {
                        Type = host.PlatformType.SystemString,
                        // TODO unify code for current uri fieldreference
                        Definition = new FieldReference()
                        {
                            ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(),
                            IsStatic       = true,
                            Type           = host.PlatformType.SystemString,
                            Name           = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
                            InternFactory  = host.InternFactory,
                        },
                    },
                };
                Statement uriInitStmt = new ExpressionStatement()
                {
                    Expression = currentURIAssign,
                };
                mutableBlock.Statements.Insert(ndx + 1, uriInitStmt);
            }


            foreach (Tuple <IStatement, StaticURIMode, string> entry in staticStmts)
            {
                int ndx = mutableBlock.Statements.ToList().IndexOf(entry.Item1);
                if (ndx == -1)
                {
                    // can't be
                    throw new IndexOutOfRangeException("Statement must exist in original block");
                }

                Assignment currentURIAssign = new Assignment()
                {
                    Source = new CompileTimeConstant()
                    {
                        Type  = host.PlatformType.SystemString,
                        Value = UriHelper.getURIBase(entry.Item3).ToLower(),
                    },
                    Type   = host.PlatformType.SystemString,
                    Target = new TargetExpression()
                    {
                        Type = host.PlatformType.SystemString,
                        // TODO unify code for current uri fieldreference
                        Definition = new FieldReference()
                        {
                            ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(),
                            IsStatic       = true,
                            Type           = host.PlatformType.SystemString,
                            Name           = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
                            InternFactory  = host.InternFactory,
                        },
                    },
                };
                Statement uriInitStmt = new ExpressionStatement()
                {
                    Expression = currentURIAssign,
                };
                mutableBlock.Statements.Insert(ndx + 1, uriInitStmt);
            }
        }
예제 #12
0
        public override void TraverseChildren(IMethodCall methodCall)
        {
            string target;

            if (isNavigationOnBackKeyPressHandler(methodCall, out target))
            {
                ICollection <Tuple <IMethodReference, string> > targets;
                try {
                    targets = PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed];
                } catch (KeyNotFoundException) {
                    targets = new HashSet <Tuple <IMethodReference, string> >();
                }
                targets.Add(Tuple.Create <IMethodReference, string>(methodTraversed, "\"" + target + "\""));
                PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed] = targets;
            }
            else if (isCancelOnBackKeyPressHandler(methodCall))
            {
                PhoneCodeHelper.instance().BackKeyCancellingOffenders.Add(Tuple.Create <ITypeReference, string>(typeTraversed, ""));
            }

            // re-check whether it is an event cancellation call
            if (isEventCancellationMethodCall(methodCall))
            {
                PhoneCodeHelper.instance().KnownEventCancellingMethods.Add(methodTraversed);
            }

            // check whether it is a NavigationService call
            IMethodReference methodToCall = methodCall.MethodToCall;
            ITypeReference   callType     = methodToCall.ContainingType;

            if (!callType.ResolvedType.Equals(navigationSvcType.ResolvedType))
            {
                return;
            }

            string methodToCallName = methodToCall.Name.Value;

            if (!PhoneCodeHelper.NAV_CALLS.Contains(methodToCallName))
            {
                return;
            }

            navCallFound = true;
            // TODO check what to do with these
            if (methodToCallName == "GoForward" || methodToCallName == "StopLoading")
            {
                // TODO forward navigation is not supported by the phone
                // TODO StopLoading is very async, I don't think we may verify this behaviour
                // TODO possibly log
                return;
            }
            else
            {
                currentStaticMode = StaticURIMode.NOT_STATIC;
                if (methodToCallName == "GoBack")
                {
                    navCallIsStatic = false;
                    navCallIsBack   = true;
                }
                else // Navigate()
                {
                    navCallIsBack = false;

                    // check for different static patterns that we may be able to verify
                    IExpression uriArg = methodCall.Arguments.First();
                    if (UriHelper.isArgumentURILocallyCreatedStatic(uriArg, host, out unpurifiedFoundURI))
                    {
                        navCallIsStatic   = true;
                        currentStaticMode = StaticURIMode.STATIC_URI_CREATION_ONSITE;
                    }
                    else if (UriHelper.isArgumentURILocallyCreatedStaticRoot(uriArg, host, out unpurifiedFoundURI))
                    {
                        navCallIsStatic   = true;
                        currentStaticMode = StaticURIMode.STATIC_URI_ROOT_CREATION_ONSITE;
                    }
                    else
                    {
                        // get reason
                        //ICreateObjectInstance creationSite = methodCall.Arguments.First() as ICreateObjectInstance;
                        //if (creationSite == null)
                        //  notStaticReason = "URI not created at call site";
                        //else
                        //  notStaticReason = "URI not initialized as a static string";
                    }
                }

                if (navCallFound && !navCallIsBack)
                {
                    // check this method as a navigation method
                    PhoneCodeHelper.instance().KnownNavigatingMethods.Add(methodTraversed);
                }

                //Console.Write("Page navigation event found. Target is static? " + (isStatic ? "YES" : "NO"));
                //if (!isStatic) {
                //  Console.WriteLine(" -- Reason: " + notStaticReason);
                //} else {
                //  Console.WriteLine("");
                //}
            }
        }
        public override void TraverseChildren(IMethodCall methodCall)
        {
            if (methodCall.MethodToCall.ResolvedMethod.IsSpecialName && methodCall.MethodToCall.Name.Value == "add_BackKeyPress")
            {
                // check if it is a back key handler and if it is...
                // NAVIGATION TODO this only catches really locally delegate expressions. If it is created before, we see it as a BoundExpression
                // NAVIGATION TODO and need (again) data flow analysis
                bool delegateIsIdentified = false;
                bool delegateIsAnonymous  = false;
                PhoneCodeHelper.instance().OnBackKeyPressOverriden = true;
                IBlockStatement   delegateBody      = null;
                IMethodDefinition delegateMethodRef = null;
                if (methodCall.Arguments.Count() == 1)
                {
                    IExpression             delegateArg   = methodCall.Arguments.First();
                    ICreateDelegateInstance localDelegate = delegateArg as ICreateDelegateInstance;
                    if (localDelegate != null)
                    {
                        delegateIsIdentified = true;
                        delegateMethodRef    = localDelegate.MethodToCallViaDelegate.ResolvedMethod;
                        SourceMethodBody body = delegateMethodRef.Body as SourceMethodBody;
                        if (body != null)
                        {
                            delegateBody = body.Block;
                        }

                        PhoneCodeHelper.instance().KnownBackKeyHandlers.Add(delegateMethodRef);
                    }

                    AnonymousDelegate anonDelegate = delegateArg as AnonymousDelegate;
                    if (anonDelegate != null)
                    {
                        delegateIsIdentified = true;
                        delegateIsAnonymous  = true;
                        delegateBody         = anonDelegate.Body;
                    }

                    // NAVIGATION TODO what if it has no body?
                    if (delegateBody != null)
                    {
                        bool navigates = false, cancelsNav = false;
                        ICollection <string> navTargets;
                        parseBlockForNavigation(delegateBody, out navigates, out navTargets);
                        if (navigates)
                        {
                            ICollection <Tuple <IMethodReference, string> > targets = null;
                            if (!PhoneCodeHelper.instance().BackKeyNavigatingOffenders.TryGetValue(typeBeingTraversed, out targets))
                            {
                                targets = new HashSet <Tuple <IMethodReference, string> >();
                            }

                            foreach (string tgt in navTargets)
                            {
                                IMethodReference dummyRef = null;
                                if (delegateIsAnonymous)
                                {
                                    dummyRef = new Microsoft.Cci.MutableCodeModel.MethodReference();
                                    (dummyRef as Microsoft.Cci.MutableCodeModel.MethodReference).ContainingType = typeBeingTraversed;
                                    (dummyRef as Microsoft.Cci.MutableCodeModel.MethodReference).Name           = Dummy.Name;
                                }
                                targets.Add(Tuple.Create <IMethodReference, string>((delegateIsAnonymous ? dummyRef : delegateMethodRef), "\"" + tgt + "\""));
                            }

                            PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeBeingTraversed] = targets;
                        }

                        parseBlockForEventCancellation(delegateBody, out cancelsNav);
                        if (cancelsNav)
                        {
                            string reason = "(via delegate ";
                            if (delegateIsIdentified)
                            {
                                reason += delegateMethodRef.ContainingType.ToString() + "." + delegateMethodRef.Name.Value;
                            }
                            else
                            {
                                reason += "anonymous";
                            }
                            reason += ")";
                            PhoneCodeHelper.instance().BackKeyCancellingOffenders.Add(Tuple.Create <ITypeReference, string>(typeBeingTraversed, reason));
                        }
                    }
                }

                if (!delegateIsIdentified)
                {
                    PhoneCodeHelper.instance().BackKeyHandlerOverridenByUnknownDelegate = true;
                    PhoneCodeHelper.instance().BackKeyUnknownDelegateOffenders.Add(typeBeingTraversed);
                }
            }
            base.TraverseChildren(methodCall);
        }
        public Bpl.Procedure addHandlerStubCaller(Sink sink, IMethodDefinition def)
        {
            MethodBody       callerBody = new MethodBody();
            MethodDefinition callerDef  = new MethodDefinition()
            {
                InternFactory            = (def as MethodDefinition).InternFactory,
                ContainingTypeDefinition = def.ContainingTypeDefinition,
                IsStatic = true,
                Name     = sink.host.NameTable.GetNameFor("BOOGIE_STUB_CALLER_" + def.Name.Value),
                Type     = sink.host.PlatformType.SystemVoid,
                Body     = callerBody,
            };

            callerBody.MethodDefinition = callerDef;
            Sink.ProcedureInfo procInfo   = sink.FindOrCreateProcedure(def);
            Sink.ProcedureInfo callerInfo = sink.FindOrCreateProcedure(callerDef);

            Bpl.LocalVariable[]  localVars = new Bpl.LocalVariable[procInfo.Decl.InParams.Count];
            Bpl.IdentifierExpr[] varExpr   = new Bpl.IdentifierExpr[procInfo.Decl.InParams.Count];
            for (int i = 0; i < procInfo.Decl.InParams.Count; i++)
            {
                Bpl.LocalVariable loc = new Bpl.LocalVariable(Bpl.Token.NoToken,
                                                              new Bpl.TypedIdent(Bpl.Token.NoToken, TranslationHelper.GenerateTempVarName(),
                                                                                 procInfo.Decl.InParams[i].TypedIdent.Type));
                localVars[i] = loc;
                varExpr[i]   = new Bpl.IdentifierExpr(Bpl.Token.NoToken, loc);
            }

            Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder();
            builder.Add(getResetNavigationCheck(sink));

            string pageXaml = PhoneCodeHelper.instance().PhonePlugin.getXAMLForPage(def.ContainingTypeDefinition.ToString());

            Bpl.Variable boogieCurrentURI = sink.FindOrCreateFieldVariable(PhoneCodeHelper.CurrentURIFieldDefinition);
            Bpl.Constant boogieXamlConstant;
            if (pageXaml != null)
            {
                boogieXamlConstant = sink.FindOrCreateConstant(pageXaml);
            }
            else
            {
                boogieXamlConstant = null;
            }
            // NAVIGATION TODO: For now just assume we are in this page to be able to call the handler, this is NOT true for any handler
            // NAVIGATION TODO: ie, a network event handler
            if (boogieXamlConstant != null)
            {
                Bpl.AssumeCmd assumeCurrentPage =
                    new Bpl.AssumeCmd(Bpl.Token.NoToken,
                                      Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI),
                                                      new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant)));
                builder.Add(assumeCurrentPage);
            }

            // NAVIGATION TODO: have to do the pair generation all in one go instead of having different files that need to be sed'ed
            boogieXamlConstant = sink.FindOrCreateConstant(BOOGIE_STARTING_URI_PLACEHOLDER);
            Bpl.AssumeCmd assumeStartPage = new Bpl.AssumeCmd(Bpl.Token.NoToken,
                                                              Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI),
                                                                              new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant)));
            builder.Add(assumeStartPage);
            builder.Add(new Bpl.CallCmd(Bpl.Token.NoToken, procInfo.Decl.Name, new List <Bpl.Expr>(varExpr), new List <Bpl.IdentifierExpr>()));
            boogieXamlConstant = sink.FindOrCreateConstant(BOOGIE_ENDING_URI_PLACEHOLDER);
            Bpl.AssertCmd assertEndPage = new Bpl.AssertCmd(Bpl.Token.NoToken,
                                                            Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieCurrentURI),
                                                                            new Bpl.IdentifierExpr(Bpl.Token.NoToken, boogieXamlConstant)));

            Bpl.Expr            guard       = new Bpl.IdentifierExpr(Bpl.Token.NoToken, sink.FindOrCreateGlobalVariable(PhoneCodeHelper.BOOGIE_NAVIGATION_CHECK_VARIABLE, Bpl.Type.Bool));
            Bpl.StmtListBuilder thenBuilder = new Bpl.StmtListBuilder();
            thenBuilder.Add(assertEndPage);
            Bpl.IfCmd ifNavigated = new Bpl.IfCmd(Bpl.Token.NoToken, guard, thenBuilder.Collect(Bpl.Token.NoToken), null, new Bpl.StmtListBuilder().Collect(Bpl.Token.NoToken));

            builder.Add(ifNavigated);
            Bpl.Implementation impl =
                new Bpl.Implementation(Bpl.Token.NoToken, callerInfo.Decl.Name, new List <Bpl.TypeVariable>(), new List <Bpl.Variable>(),
                                       new List <Bpl.Variable>(), new List <Bpl.Variable>(localVars), builder.Collect(Bpl.Token.NoToken), null, new Bpl.Errors());

            sink.TranslatedProgram.AddTopLevelDeclaration(impl);
            return(impl.Proc);
        }
    public static PhoneCodeHelper instance() {
      if (_instance == null) {
        _instance = new PhoneCodeHelper(host);
      }

      return _instance;
    }
 public PhoneMethodInliningMetadataTraverser(PhoneCodeHelper phoneHelper) {
   methodsToInline = new HashSet<IMethodDefinition>();
   iterMethodsToInline = new HashSet<IMethodDefinition>();
   this.phoneHelper = phoneHelper;
   TotalMethodsCount = 0;
 }