Prevent local value leaks via non-trivial field access

IDEA-230097 Inspection incorrectly shows "The call to 'assert true' always fails" on a Junit callback test

GitOrigin-RevId: 5ae966d139391f72c7d015297b093523dba5e5e8
This commit is contained in:
Tagir Valeev
2020-01-20 14:52:19 +07:00
committed by intellij-monorepo-bot
parent 90ca9a6360
commit 099d5fcf7c
3 changed files with 62 additions and 3 deletions

View File

@@ -466,14 +466,34 @@ public class StandardInstructionVisitor extends InstructionVisitor {
}
if (!(value.getType() instanceof PsiArrayType) &&
(TypeConstraint.fromDfType(dfType).isComparedByEquals() ||
instruction.shouldFlushFields() || !(instruction.getResultType() instanceof PsiPrimitiveType))) {
// For now drop locality on every qualified call except primitive returning pure calls
// as value might escape through the return value
instruction.shouldFlushFields() || mayLeakFromType(instruction.getResultType()))) {
value = dropLocality(value, memState);
}
return value;
}
private boolean mayLeakFromType(PsiType type) {
// Complex value from field or method return call may contain back-reference to the object, so
// local value could leak. Do not drop locality only for some simple values.
if (type == null) return true;
type = type.getDeepComponentType();
return !(type instanceof PsiPrimitiveType) && !TypeUtils.isJavaLangString(type);
}
@Override
public DfaInstructionState[] visitPush(ExpressionPushingInstruction<?> instruction,
DataFlowRunner runner,
DfaMemoryState memState,
DfaValue value) {
if (value instanceof DfaVariableValue && mayLeakFromType(value.getType())) {
DfaVariableValue qualifier = ((DfaVariableValue)value).getQualifier();
if (qualifier != null) {
dropLocality(qualifier, memState);
}
}
return super.visitPush(instruction, runner, memState, value);
}
private Set<DfaCallState> addContractResults(MethodContract contract,
Set<DfaCallState> states,
DfaValueFactory factory,