From e19f123a6c664e1202a8249edce4fe16aac49fbd Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 13 Mar 2024 16:47:34 +0100 Subject: [PATCH] [java-dfa] IDEA-349054 Ignore current object field nullity inside readResolve() GitOrigin-RevId: dfe65dc4aa335626874a8b2a01aa68fe627e8ed9 --- .../jvm/descriptors/PlainDescriptor.java | 8 +++++- .../dataFlow/fixture/ReadResolve.java | 26 +++++++++++++++++++ .../DataFlowInspection21Test.java | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/inspection/dataFlow/fixture/ReadResolve.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/PlainDescriptor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/PlainDescriptor.java index 33242e1a4492..22e982720eb0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/PlainDescriptor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/jvm/descriptors/PlainDescriptor.java @@ -159,12 +159,18 @@ 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) && - methodCanBeCalledFromConstructorBeforeFieldInitializing(target, placeMethod, placeClass)) { + (isReadResolveMethod(placeMethod, placeClass) || + methodCanBeCalledFromConstructorBeforeFieldInitializing(target, placeMethod, placeClass))) { return true; } return getAccessOffset(placeMethod) < getWriteOffset(target); } + private static boolean isReadResolveMethod(@NotNull PsiMethod method, @NotNull PsiClass aClass) { + return "readResolve".equals(method.getName()) && method.getParameterList().isEmpty() && + InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_IO_SERIALIZABLE); + } + private record TargetCallInfo(@NotNull PsiMethod constructor, @NotNull PsiMethodCallExpression call){} private static boolean methodCanBeCalledFromConstructorBeforeFieldInitializing(@NotNull PsiField target, diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ReadResolve.java b/java/java-tests/testData/inspection/dataFlow/fixture/ReadResolve.java new file mode 100644 index 000000000000..9b3de2d4ead3 --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ReadResolve.java @@ -0,0 +1,26 @@ +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 + protected Object readResolve() { + if (string == null) { + 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); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection21Test.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection21Test.java index 9de1f6198f96..9d4b89276b01 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection21Test.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspection21Test.java @@ -113,6 +113,7 @@ public class DataFlowInspection21Test extends DataFlowInspectionTestCase { public void testSuspiciousLabelElementsJava20() { doTest(); } + public void testReadResolve() { doTest(); } public void testForEachPattern() { myFixture.addClass("""