You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
4.6 KiB
183 lines
4.6 KiB
/*
|
|
* Copyright (c) 2017-present, Facebook, Inc.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
package codetoanalyze.java.quandary;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Intent;
|
|
import android.util.Log;
|
|
import com.facebook.infer.builtins.InferTaint;
|
|
|
|
/** Testing that sources and sinks specified in external JSON work correctly */
|
|
public class ExternalSpecs {
|
|
|
|
// we specify this as a source with kind PrivateData in .inferconfig
|
|
private static Object privateDataSource() {
|
|
return new Object();
|
|
}
|
|
|
|
public static void logExternalSourceBad() {
|
|
Log.e("", (String) privateDataSource());
|
|
}
|
|
|
|
// we specified that this is a private data source, so passing it an intent sink like
|
|
// startActivity() is fine
|
|
public static void externalSourceAsIntentOk(Activity activity) {
|
|
activity.startActivity((Intent) privateDataSource());
|
|
}
|
|
|
|
// we specify that index 1 is an external sink with type Logging in .inferconfig
|
|
public static void loggingSink1(Object notASink, Object sink) {}
|
|
|
|
public static void callExternalSinkBad() {
|
|
loggingSink1(null, privateDataSource());
|
|
}
|
|
|
|
// passing to non-tainted param
|
|
public static void callExternalSinkOk1() {
|
|
loggingSink1(privateDataSource(), null);
|
|
}
|
|
|
|
// passing intent source to logging sink is fine
|
|
public static void callExternalSinkOk2(Activity activity) {
|
|
loggingSink1(null, activity.getIntent());
|
|
}
|
|
|
|
// we specify that all the indices are tainted with type Logging in .inferconfig
|
|
public static void loggingSink2(Object sink1, Object sink2) {}
|
|
|
|
public static void callExternalSink2Bad1() {
|
|
loggingSink2(privateDataSource(), null);
|
|
}
|
|
|
|
public static void callExternalSink2Bad2() {
|
|
loggingSink2(null, privateDataSource());
|
|
}
|
|
|
|
// passing intent sources to logging sink is fine
|
|
public static void callExternalSink2Ok(Activity activity) {
|
|
loggingSink2(activity.getIntent(), activity.getIntent());
|
|
}
|
|
|
|
static Object sanitizer(Object o) {
|
|
return o;
|
|
}
|
|
|
|
void viaSanitizerOk() {
|
|
Object source = InferTaint.inferSecretSource();
|
|
Object sanitized = sanitizer(source);
|
|
InferTaint.inferSensitiveSink(sanitized);
|
|
}
|
|
|
|
void sanitizeFootprint(Object o) {
|
|
Object sanitized = sanitizer(o);
|
|
InferTaint.inferSensitiveSink(sanitized);
|
|
}
|
|
|
|
void callSanitizeFootprintOk() {
|
|
sanitizeFootprint(InferTaint.inferSecretSource());
|
|
}
|
|
|
|
Object returnSanitizedSource() {
|
|
Object source = InferTaint.inferSecretSource();
|
|
return sanitizer(source);
|
|
}
|
|
|
|
void callSinkOnSanitizedSourceOk() {
|
|
InferTaint.inferSensitiveSink(returnSanitizedSource());
|
|
}
|
|
|
|
Object missedSanitizerBad() {
|
|
Object source = InferTaint.inferSecretSource();
|
|
Object sanitized = sanitizer(source);
|
|
InferTaint.inferSensitiveSink(source);
|
|
return sanitized;
|
|
}
|
|
|
|
void FN_sanitizeOneBranchBad(boolean b) {
|
|
Object source = InferTaint.inferSecretSource();
|
|
Object o;
|
|
if (b) {
|
|
o = sanitizer(source);
|
|
} else {
|
|
o = source;
|
|
}
|
|
InferTaint.inferSensitiveSink(o);
|
|
}
|
|
|
|
Object sanitizeOneBranchInCallee(Object o, boolean b) {
|
|
if (b) {
|
|
return sanitizer(o);
|
|
} else {
|
|
return o;
|
|
}
|
|
}
|
|
|
|
void FN_sanitizerWeakUpdateBad(boolean b) {
|
|
Object source = InferTaint.inferSecretSource();
|
|
Object o = sanitizeOneBranchInCallee(source, b);
|
|
InferTaint.inferSensitiveSink(o);
|
|
}
|
|
|
|
// if theres' a procedure with the same name defined in .inferconfig as a sink on parameter 1,
|
|
// we shouldn't crash
|
|
public static void loggingSink1() {}
|
|
|
|
// we shouldn't fail when calling this either
|
|
public static void loggingSink1(Object notASink) {}
|
|
|
|
void callLoggingSink1sOk(Object o) {
|
|
loggingSink1();
|
|
loggingSink1(o);
|
|
}
|
|
|
|
public static Object sinkThatPropagates(Object o) {
|
|
return o;
|
|
}
|
|
|
|
void callSinkThatPropagatesBad() {
|
|
Object source = InferTaint.inferSecretSource();
|
|
Object sourceAgain = sinkThatPropagates(source); // should report
|
|
loggingSink1(null, sourceAgain); // should report here too
|
|
}
|
|
}
|
|
|
|
interface InterfaceSpec {
|
|
|
|
// marked as source in .inferconfig
|
|
public Object source();
|
|
|
|
// marked as sink in .inferconfig
|
|
public void sink(Object o);
|
|
}
|
|
|
|
class InterfaceSpecImpl implements InterfaceSpec {
|
|
|
|
@Override
|
|
public Object source() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void sink(Object o) {}
|
|
|
|
public void externalSpecBad() {
|
|
sink(source());
|
|
}
|
|
}
|
|
|
|
class ConstructorSink {
|
|
|
|
// specified as a source in .inferconfig
|
|
public ConstructorSink(Object o) {}
|
|
|
|
public static ConstructorSink constructorSinkBad() {
|
|
Object source = InferTaint.inferSecretSource();
|
|
return new ConstructorSink(source);
|
|
}
|
|
}
|