private bool isCancelOnBackKeyPressHandler(IMethodCall call) { if (!PhoneCodeHelper.instance().isBackKeyPressOverride(methodTraversed.ResolvedMethod)) { return(false); } return(isEventCancellationMethodCall(call)); }
// 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); }
/// <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); } }
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); } } } } } } }
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); }
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); }
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); } }
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); }