Summary: We get the wrong answer on most of them for now, but that is expected Reviewed By: ngorogiannis Differential Revision: D5429242 fbshipit-source-id: 4899079master
parent
4d7742fd68
commit
72e778d094
@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 201y - 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.checkers;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
|
|
||||||
|
@ThreadSafe
|
||||||
|
public class Escape {
|
||||||
|
|
||||||
|
private Obj mField;
|
||||||
|
private static Obj sGlobal;
|
||||||
|
|
||||||
|
// this can race with unsafe writes to mField.f
|
||||||
|
public synchronized Object racyRead1() {
|
||||||
|
return mField.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this can race with unsafe writes to mField.f
|
||||||
|
public synchronized Object racyRead2() {
|
||||||
|
return sGlobal.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_fieldEscapeBad() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
synchronized(this) {
|
||||||
|
mField = o;
|
||||||
|
}
|
||||||
|
o.f = new Object(); // not safe
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_globalEscapeBad() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
synchronized (Escape.class) {
|
||||||
|
sGlobal = o;
|
||||||
|
}
|
||||||
|
o.f = new Object(); // not safe
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void escapeInCallee(Obj o) {
|
||||||
|
mField = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_escapeInCalleeBad() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
escapeInCallee(o);
|
||||||
|
o.f = new Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void aliasOk() {
|
||||||
|
Obj o = new Obj(); // though there's two pointers to this address, neither escapes
|
||||||
|
Obj alias = o;
|
||||||
|
o.f = null;
|
||||||
|
alias.f = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void nonAliasReadOk() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
String s = o + "a";
|
||||||
|
o.f = null; // ok
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_escapeViaAliasBad1() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
Obj alias = o;
|
||||||
|
escapeInCallee(alias);
|
||||||
|
o.f = null; // bad
|
||||||
|
alias.f = null; // bad
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_escapeViaAliasBad2() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
Obj alias = o;
|
||||||
|
escapeInCallee(o);
|
||||||
|
o.f = null; // bad
|
||||||
|
alias.f = null; // bad
|
||||||
|
}
|
||||||
|
|
||||||
|
public Obj id(Obj o) {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_aliasViaReturnBad1() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
Obj alias = id(o);
|
||||||
|
escapeInCallee(alias);
|
||||||
|
o.f = null; // bad
|
||||||
|
alias.f = null; // bad
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_aliasViaReturnBad2() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
Obj alias = id(o);
|
||||||
|
escapeInCallee(o);
|
||||||
|
o.f = null; // bad
|
||||||
|
alias.f = null; // bad
|
||||||
|
}
|
||||||
|
|
||||||
|
private void twoParamsOneEscapes(Obj o1, Obj o2) {
|
||||||
|
synchronized (Escape.class) {
|
||||||
|
sGlobal = o1;
|
||||||
|
}
|
||||||
|
o1.f = null; // only safe if o1/o2 not aliased
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_aliasedParamsBad() {
|
||||||
|
Obj o = new Obj();
|
||||||
|
twoParamsOneEscapes(o, o); // should report racy write in callee
|
||||||
|
o.f = null; // bad
|
||||||
|
}
|
||||||
|
|
||||||
|
public void nonAliasedParamsOk() {
|
||||||
|
Obj o1 = new Obj();
|
||||||
|
Obj o2 = new Obj();
|
||||||
|
twoParamsOneEscapes(o1, o2);
|
||||||
|
o2.f = null; // ok
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ThreadSafe
|
||||||
|
class Leaky {
|
||||||
|
|
||||||
|
Leaky mLeak;
|
||||||
|
Object mField;
|
||||||
|
Object sGlobal;
|
||||||
|
|
||||||
|
public Leaky() {
|
||||||
|
mLeak = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FN_leakyConstructorBad() {
|
||||||
|
Leaky l = new Leaky();
|
||||||
|
synchronized (Leaky.class) {
|
||||||
|
sGlobal = l.mLeak; // oops, this leaks l
|
||||||
|
}
|
||||||
|
l.mField = 1; // bad
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in new issue