AndroidContext: Explicitly hand through on Intent-Start (coarse)
PARTIALLY: Android-Context is explicitly assigned when Intents are started. Not all types of Context are handled correctly yet.
This commit is contained in:
parent
9c8e2e7c00
commit
80c022f525
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright (c) 2013,
|
||||
* Tobias Blaschke <code@tobiasblaschke.de>
|
||||
* All rights reserved.
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The names of the contributors may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package com.ibm.wala.dalvik.ipa.callgraph.propagation.cfa;
|
||||
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.propagation.cfa.Intent;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.CallerContext;
|
||||
|
||||
import com.ibm.wala.dalvik.util.AndroidTypes;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.ContextItem;
|
||||
import com.ibm.wala.ipa.callgraph.ContextKey;
|
||||
|
||||
/**
|
||||
* Fetches an android/content/Context.
|
||||
*
|
||||
* @author Tobias Blaschke <code@tobiasblaschke.de>
|
||||
* @since 2013-10-14
|
||||
*/
|
||||
public class AndroidContext implements Context {
|
||||
/**
|
||||
* Key into the Context that represents the AndroidContext.
|
||||
*/
|
||||
public static final ContextKey ANDROID_CONTEXT_KEY = new ContextKey() {};
|
||||
private final AndroidTypes.AndroidContextType aCtxT;
|
||||
private final Context parent;
|
||||
|
||||
public AndroidContext(Context parent, AndroidTypes.AndroidContextType aCtxT) {
|
||||
this.parent = parent;
|
||||
this.aCtxT = aCtxT;
|
||||
}
|
||||
|
||||
public AndroidTypes.AndroidContextType getContextType() {
|
||||
return this.aCtxT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a ContextKey in the Context.
|
||||
*
|
||||
* @return an Intent or parent-managed object.
|
||||
* @throws IllegalArgumentException if the name is null.
|
||||
*/
|
||||
@Override
|
||||
public ContextItem get (ContextKey name) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("name is null");
|
||||
}
|
||||
if (name.equals(ANDROID_CONTEXT_KEY)) {
|
||||
return null; // TODO
|
||||
} else if(this.parent != null) {
|
||||
return this.parent.get(name);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special equality: Object may be equal to an object without associated Intent.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj instanceof AndroidContext) {
|
||||
AndroidContext other = (AndroidContext) obj;
|
||||
if (this.aCtxT.equals(other.aCtxT)) {
|
||||
if (this.parent != null) {
|
||||
return this.parent.equals(other.parent);
|
||||
} else {
|
||||
return other.parent == null;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (this.parent != null) {
|
||||
// TODO: do we really want this?
|
||||
return this.parent.equals(obj);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// TODO: do we want to "clash" with the parent here?
|
||||
return 71891 * this.aCtxT.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this.parent == null) {
|
||||
return "AndroidContext: " + this.aCtxT;
|
||||
} else {
|
||||
return "AndroidContext: " + this.aCtxT + ", parent: " + this.parent;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ import com.ibm.wala.ipa.callgraph.ContextSelector;
|
|||
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.propagation.cfa.Intent;
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.propagation.cfa.IntentContext;
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.propagation.cfa.AndroidContext;
|
||||
import com.ibm.wala.dalvik.ipa.callgraph.propagation.cfa.IntentContextInterpreter;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
|
@ -96,6 +97,7 @@ public class IntentContextSelector implements ContextSelector {
|
|||
private final ContextSelector parent;
|
||||
private final IntentStarters intentStarters;
|
||||
private final Map<InstanceKey, Intent> seen;
|
||||
private final Map<InstanceKey, AndroidContext> seenContext;
|
||||
|
||||
public IntentContextSelector(final IClassHierarchy cha) {
|
||||
this(null, cha);
|
||||
|
@ -107,6 +109,7 @@ public class IntentContextSelector implements ContextSelector {
|
|||
public IntentContextSelector(final ContextSelector parent, final IClassHierarchy cha) {
|
||||
this.parent = parent;
|
||||
this.seen = HashMapFactory.make();
|
||||
this.seenContext = HashMapFactory.make();
|
||||
this.intentStarters = new IntentStarters(cha);
|
||||
}
|
||||
|
||||
|
@ -139,6 +142,12 @@ public class IntentContextSelector implements ContextSelector {
|
|||
{
|
||||
final InstanceKey self = actualParameters[0];
|
||||
assert (self != null) : "This-Pointer was not marked as relevant!";
|
||||
|
||||
if (seenContext.containsKey(self)) {
|
||||
ctx = new AndroidContext(ctx, seenContext.get(self).getContextType());
|
||||
} else {
|
||||
logger.warn("No Android-Context seen for {}", caller);
|
||||
}
|
||||
}
|
||||
|
||||
// Seach intent and attach as context
|
||||
|
@ -287,6 +296,42 @@ public class IntentContextSelector implements ContextSelector {
|
|||
logger.warn("Can't extract Info from Intent-Constructor: {} (not implemented)", site);
|
||||
//System.out.println("\t\tFOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO: " + callee.getSelector()); // XXX
|
||||
}
|
||||
} else if (callee.isInit() && callee.getDeclaringClass().getName().equals(AndroidTypes.IntentSenderName)) {
|
||||
// TODO
|
||||
} else if (site.isSpecial() && callee.getDeclaringClass().getName().equals(
|
||||
AndroidTypes.ContextWrapperName)) {
|
||||
final InstanceKey baseKey = actualParameters[1];
|
||||
final InstanceKey wrapperKey = actualParameters[0];
|
||||
|
||||
logger.debug("Handling ContextWrapper(Context base)");
|
||||
if (seenContext.containsKey(baseKey)) {
|
||||
seenContext.put(wrapperKey, seenContext.get(baseKey));
|
||||
} else {
|
||||
if (baseKey == null) {
|
||||
logger.warn("Got baseKey as 'null'. Obviously can't handle this. Caller was: {}", caller.getMethod());
|
||||
} else {
|
||||
logger.warn("ContextWrapper: No AndroidContext was seen for baseKey");
|
||||
}
|
||||
}
|
||||
} else if ((site.isSpecial() && callee.getDeclaringClass().getName().equals(
|
||||
AndroidTypes.ContextImplName))) {
|
||||
final InstanceKey self = actualParameters[0];
|
||||
seenContext.put(self, new AndroidContext(ctx, AndroidTypes.AndroidContextType.CONTEXT_IMPL));
|
||||
} else if (callee.getDeclaringClass().getName().equals(AndroidTypes.ContextWrapperName) &&
|
||||
callee.getSelector().equals(Selector.make("attachBaseContext(Landroid/content/Context;)V"))) {
|
||||
final InstanceKey baseKey = actualParameters[1];
|
||||
final InstanceKey wrapperKey = actualParameters[0];
|
||||
|
||||
logger.debug("Handling ContextWrapper.attachBaseContext(base)");
|
||||
if (seenContext.containsKey(baseKey)) {
|
||||
seenContext.put(wrapperKey, seenContext.get(baseKey));
|
||||
} else {
|
||||
if (baseKey == null) {
|
||||
logger.warn("Got baseKey as 'null'. Obviously can't handle this. Caller was: {}", caller.getMethod());
|
||||
} else {
|
||||
logger.warn("ContextWrapper: No AndroidContext was seen for baseKey");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ctx;
|
||||
|
|
Loading…
Reference in New Issue