diff --git a/infer/src/checkers/ThreadSafety.ml b/infer/src/checkers/ThreadSafety.ml index cb777ef53..91db797b8 100644 --- a/infer/src/checkers/ThreadSafety.ml +++ b/infer/src/checkers/ThreadSafety.ml @@ -346,6 +346,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct let typename = Typ.Name.Java.from_string (Typ.Procname.java_get_class_name java_pname) in let is_container_write_ typename _ = match Typ.Name.name typename, Typ.Procname.java_get_method java_pname with + | ("android.util.SparseArray" | "android.support.v4.util.SparseArrayCompat"), + ("append" | "clear" | "delete" | "put" | "remove" | "removeAt" | "removeAtRange" + | "setValueAt") -> true | "java.util.List", ("add" | "addAll" | "clear" | "remove" | "set") -> true | "java.util.Map", ("clear" | "put" | "putAll" | "remove") -> true | _ -> false in diff --git a/infer/tests/codetoanalyze/java/threadsafety/Containers.java b/infer/tests/codetoanalyze/java/threadsafety/Containers.java index 0b791a9e2..2f03911af 100644 --- a/infer/tests/codetoanalyze/java/threadsafety/Containers.java +++ b/infer/tests/codetoanalyze/java/threadsafety/Containers.java @@ -21,6 +21,8 @@ import java.util.concurrent.CopyOnWriteArrayList; import javax.annotation.concurrent.ThreadSafe; import android.support.v4.util.Pools.SynchronizedPool; +import android.support.v4.util.SparseArrayCompat; +import android.util.SparseArray; class ContainerWrapper { private final List children = new ArrayList(); @@ -216,4 +218,22 @@ class Containers { addOrCreateList(list); } + void addToSparseArrayCompatOk() { + SparseArrayCompat sparseArray = new SparseArrayCompat(); + sparseArray.put(0, new Object()); + } + + public void addToSparseArrayCompatBad(SparseArrayCompat sparseArray) { + sparseArray.put(0, new Object()); + } + + public void addToSparseArrayOk() { + SparseArray sparseArray = new SparseArray(); + sparseArray.put(0, new Object()); + } + + public void addToSparseArrayBad(SparseArray sparseArray) { + sparseArray.put(0, new Object()); + } + } diff --git a/infer/tests/codetoanalyze/java/threadsafety/issues.exp b/infer/tests/codetoanalyze/java/threadsafety/issues.exp index 699a0cd3b..3a4b8927b 100644 --- a/infer/tests/codetoanalyze/java/threadsafety/issues.exp +++ b/infer/tests/codetoanalyze/java/threadsafety/issues.exp @@ -21,6 +21,8 @@ codetoanalyze/java/threadsafety/Builders.java, void TopLevelBuilder.setG(String) codetoanalyze/java/threadsafety/Constructors.java, Constructors Constructors.singletonBad(), 2, THREAD_SAFETY_VIOLATION, [call to Constructors.(Object),access to `Constructors.staticField`] codetoanalyze/java/threadsafety/Constructors.java, Constructors.(), 1, THREAD_SAFETY_VIOLATION, [access to `Constructors.staticField`] codetoanalyze/java/threadsafety/Constructors.java, Constructors.(Constructors), 1, THREAD_SAFETY_VIOLATION, [access to `Constructors.field`] +codetoanalyze/java/threadsafety/Containers.java, void Containers.addToSparseArrayBad(SparseArray), 1, THREAD_SAFETY_VIOLATION, [container `&sparseArray` via call to `put`] +codetoanalyze/java/threadsafety/Containers.java, void Containers.addToSparseArrayCompatBad(SparseArrayCompat), 1, THREAD_SAFETY_VIOLATION, [container `&sparseArray` via call to `put`] codetoanalyze/java/threadsafety/Containers.java, void Containers.containerWrapperUnownedWriteBad(Object), 1, THREAD_SAFETY_VIOLATION, [container `codetoanalyze.java.checkers.ContainerWrapper.children` via call to `add`,container `codetoanalyze.java.checkers.ContainerWrapper.children` via call to `add`,container `codetoanalyze.java.checkers.ContainerWrapper.children` via call to `add`] codetoanalyze/java/threadsafety/Containers.java, void Containers.listAddAllBad(Collection), 1, THREAD_SAFETY_VIOLATION, [container `codetoanalyze.java.checkers.Containers.mList` via call to `addAll`] codetoanalyze/java/threadsafety/Containers.java, void Containers.listAddBad1(String), 1, THREAD_SAFETY_VIOLATION, [container `codetoanalyze.java.checkers.Containers.mList` via call to `add`]