|
|
|
/*
|
|
|
|
* Copyright (c) 2016 - present Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package codetoanalyze.java.quandary;
|
|
|
|
|
|
|
|
import com.facebook.infer.builtins.InferTaint;
|
|
|
|
|
|
|
|
/** testing how the analysis handles missing/unknown code */
|
|
|
|
|
|
|
|
public abstract class UnknownCode {
|
|
|
|
|
|
|
|
native static Object nativeMethod(Object o);
|
|
|
|
|
|
|
|
abstract Object abstractMethod(Object o);
|
|
|
|
|
|
|
|
static interface Interface {
|
|
|
|
Object interfaceMethod(Object o);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void propagateViaUnknownConstructorBad() {
|
|
|
|
String source = (String) InferTaint.inferSecretSource();
|
|
|
|
// we don't analyze the code for the core Java libraries, so this constructor will be unknown
|
|
|
|
String unknownConstructor = new String(source);
|
|
|
|
InferTaint.inferSensitiveSink(unknownConstructor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void propagateViaUnknownConstructorOk() {
|
|
|
|
String unknownConstructor = new String("");
|
|
|
|
InferTaint.inferSensitiveSink(unknownConstructor);
|
|
|
|
}
|
|
|
|
|
|
|
|
void propagateViaUnknownCodeOk(Interface i) {
|
|
|
|
Object notASource = new Object();
|
|
|
|
Object launderedSource1 = nativeMethod(notASource);
|
|
|
|
Object launderedSource2 = abstractMethod(launderedSource1);
|
|
|
|
Object launderedSource3 = i.interfaceMethod(launderedSource2);
|
|
|
|
InferTaint.inferSensitiveSink(launderedSource3);
|
|
|
|
}
|
|
|
|
|
[quandary] cheaper handling of unknown code
Summary:
Let's introduce some concepts. A "known unknown" function is one for which no Java code exists (e.g., `native`, `abstract`, and `interface methods`). An "unknown unknown" function is one for which Java code may or may not exist, but we don't have the code or we choose not to analyze it (e.g., non-modeled methods from the core Java or Android libraries).
Previously, Quandary handled both known unknowns and unknown unknowns by propagating taint from the parameters of the unknown function to its return value. It turns out that it is really expensive to do this for known unknown functions. D4142697 was the diff that starting handling known unknown functions in this way, and bisecting shows that it was the start of the recent performance problems for Quandary.
This diff essentially reverts D4142697 by handling known unknowns as skips instead. Pragmatically, doing the propagation trick for Java/Android library functions (e.g., `String` functions!) matters much more, so i'm not too worried about the missed behaviors from this. Ideally, we will go back to the old handling once performance has improved (have lots of ideas there). But I need this to unblock me in the meantime.
Reviewed By: jeremydubreil
Differential Revision: D4205507
fbshipit-source-id: 79cb9c8
8 years ago
|
|
|
static void FN_propagateViaInterfaceCodeBad(Interface i) {
|
|
|
|
Object source = InferTaint.inferSecretSource();
|
|
|
|
Object launderedSource = i.interfaceMethod(source);
|
|
|
|
InferTaint.inferSensitiveSink(launderedSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FN_propagateViaUnknownNativeCodeBad() {
|
|
|
|
Object source = InferTaint.inferSecretSource();
|
|
|
|
Object launderedSource = nativeMethod(source);
|
|
|
|
InferTaint.inferSensitiveSink(launderedSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void FN_propagateViaUnknownAbstractCodeBad() {
|
|
|
|
Object source = InferTaint.inferSecretSource();
|
|
|
|
Object launderedSource = nativeMethod(source);
|
|
|
|
InferTaint.inferSensitiveSink(launderedSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|