facebook / facebook/infer

[java] STARVATION: False Negative in Infer analysis results after converting anonymous classes to lambda expressions

Open
#1,776 1 comment 0 reactions 0 assignees View on GitHub
false-negative java
Dominant language
OCaml
Stars
15.7k
Forks
2.1k
Avg merge
19h 36m
Merged PRs (30d)
13

Description

This issue is similar with issue #1775 .

## Environment
**Infer Version:** v1.1.0-f93cb281ed
**Operating System:** Ubuntu 20.04.5 LTS

### Description:
We made modifications to the `IndirectStarvation.java` file, where we converted anonymous classes to lambda expressions. After making this change, we ran the Infer analysis using the following command: `sudo make direct_java_starvation-whole-program_test`. However, we observed inconsistencies between the results in `issues.exp.test` and the expected results in `issues.exp`.

We expect Infer to detect certain converted code to get results in the `issues.exp.test` file similar to the ones mentioned in `issues.exp`. However, the result for `IndirectStarvation.java` is different. The `STARVATION` issue does not appear in `issues.exp.test`. Therefore, we consider it a false negative.

### Steps to Reproduce:
1. Convert anonymous classes to lambda expressions in `IndirectStarvation.java`.
2. Run the command: `sudo make direct_java_starvation-whole-program_test`.
3. Compare the analysis results in `issues.exp.test` with the expected results in `issues.exp`.

### Code Samples:
Original code in `IndirectStarvation.java`:

```java
class IndirectStarvation {
static Binder binder;

@ForUiThread
private final Executor mUiThreadExecutor = null;

@ForNonUiThread
private final Executor mNonUiThreadExecutor = null;

private static void doTransact() {
try {
binder.transact(0, null, null, 0);
} catch (RemoteException e) {
}
}

Object monitorA;

public void postBlockingCallToBackgroundThreadAndLockBad() {
mUiThreadExecutor.execute(
new Runnable() {
@Override
public void run() {
synchronized (monitorA) {
}
}
});

mNonUiThreadExecutor.execute(
new Runnable() {
@Override
public void run() {
synchronized (monitorA) {
doTransact();
}
}
});
}
}
```

Converted code in `IndirectStarvation.java`:

```java
class IndirectStarvation {
static Binder binder;

@ForUiThread
private final Executor mUiThreadExecutor = null;

@ForNonUiThread
private final Executor mNonUiThreadExecutor = null;

private static void doTransact() {
try {
binder.transact(0, null, null, 0);
} catch (RemoteException e) {
}
}

Object monitorA;

public void postBlockingCallToBackgroundThreadAndLockBad() {
mUiThreadExecutor.execute(() -> {
synchronized (monitorA) {
}
});

mNonUiThreadExecutor.execute(() -> {
synchronized (monitorA) {
doTransact();
}
});
}
}
```

Content in `issue.exp`:
```
codetoanalyze/java/starvation-whole-program/IndirectStarvation.java, IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad():void, 32, STARVATION, no_bucket, ERROR, [[Trace 1] `void IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad()`,Method call: `void IndirectStarvation$1.run()`, locks `this.this$0.monitorA` in `class IndirectStarvation$1`,[Trace 2] `void IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad()`,Method call: `void IndirectStarvation$2.run()`, locks `this.this$0.monitorA` in `class IndirectStarvation$2`,Method call: `void IndirectStarvation.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`]
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.