mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-dfa] Do not assume that fields are non-initialized in readResolve() when readObject() is present
Fixes IDEA-351947 False positive warning 'Nullability and data flow problems' in readResolve GitOrigin-RevId: 26c71c3e26c087334741a5a098812f91144bdcd4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
2c419527be
commit
ff1cfed0de
+9
-3
@@ -18,6 +18,8 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.JavaPsiConstructorUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.VariableAccessUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -159,16 +161,20 @@ public final class PlainDescriptor extends PsiVarDescriptor {
|
||||
if (!placeMethod.hasModifierProperty(PsiModifier.STATIC) && target.hasModifierProperty(PsiModifier.STATIC)) return false;
|
||||
if (!target.hasModifierProperty(PsiModifier.STATIC) &&
|
||||
!placeMethod.hasModifierProperty(PsiModifier.STATIC) &&
|
||||
(isReadResolveMethod(placeMethod, placeClass) ||
|
||||
(isReadResolveMethodWithoutReadObject(placeMethod, placeClass) ||
|
||||
methodCanBeCalledFromConstructorBeforeFieldInitializing(target, placeMethod, placeClass))) {
|
||||
return true;
|
||||
}
|
||||
return getAccessOffset(placeMethod) < getWriteOffset(target);
|
||||
}
|
||||
|
||||
private static boolean isReadResolveMethod(@NotNull PsiMethod method, @NotNull PsiClass aClass) {
|
||||
private static final CallMatcher READ_OBJECT = CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_OBJECT, "readObject")
|
||||
.parameterTypes("java.io.ObjectInputStream");
|
||||
|
||||
private static boolean isReadResolveMethodWithoutReadObject(@NotNull PsiMethod method, @NotNull PsiClass aClass) {
|
||||
return "readResolve".equals(method.getName()) && method.getParameterList().isEmpty() &&
|
||||
InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_IO_SERIALIZABLE);
|
||||
!aClass.isRecord() && InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_IO_SERIALIZABLE) &&
|
||||
!ContainerUtil.exists(aClass.findMethodsByName("readObject", false), READ_OBJECT::methodMatches);
|
||||
}
|
||||
|
||||
private record TargetCallInfo(@NotNull PsiMethod constructor,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Base64;
|
||||
|
||||
class Test implements Serializable {
|
||||
@NotNull String string;
|
||||
|
||||
Test(@NotNull String string) {
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
@Serial
|
||||
private void readObject(ObjectInputStream in) throws IOException {
|
||||
this.string = in.readUTF();
|
||||
}
|
||||
|
||||
@Serial
|
||||
protected Object readResolve() {
|
||||
if (<warning descr="Condition 'string == null' is always 'false'">string == null</warning>) {
|
||||
throw new IllegalStateException("Wrong object!");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException, ClassNotFoundException {
|
||||
byte[] data = Base64.getDecoder().decode("rO0ABXNyAARUZXN0ST9d8XKvH/0CAAFMAAZzdHJpbmd0ABJMamF2YS9sYW5nL1N0cmluZzt4cHA=");
|
||||
Test object = (Test) new ObjectInputStream(new ByteArrayInputStream(data)).readObject();
|
||||
System.out.println(object);
|
||||
}
|
||||
}
|
||||
@@ -114,6 +114,7 @@ public class DataFlowInspection21Test extends DataFlowInspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
public void testReadResolve() { doTest(); }
|
||||
public void testReadResolve2() { doTest(); }
|
||||
public void testDifferentTypesButNullable() { doTest(); }
|
||||
|
||||
public void testForEachPattern() {
|
||||
|
||||
Reference in New Issue
Block a user