/* * 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.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 } }