8334258: Compiler erronousely allows access to instance variable in argument expression of a constructor invocation

Reviewed-by: mcimadamore
This commit is contained in:
Archie Cobbs 2024-06-18 23:23:39 +00:00 committed by Maurizio Cimadamore
parent 2ce85d9635
commit e227c7e37d
7 changed files with 83 additions and 9 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -100,6 +100,7 @@ public class Resolve {
DeferredAttr deferredAttr;
Check chk;
Infer infer;
Preview preview;
ClassFinder finder;
ModuleFinder moduleFinder;
Types types;
@ -135,7 +136,7 @@ public class Resolve {
moduleFinder = ModuleFinder.instance(context);
types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
Preview preview = Preview.instance(context);
preview = Preview.instance(context);
Source source = Source.instance(context);
Options options = Options.instance(context);
compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
@ -1480,10 +1481,11 @@ public class Resolve {
/** Find unqualified variable or field with given name.
* Synthetic fields always skipped.
* @param pos The position to use for error reporting.
* @param env The current environment.
* @param name The name of the variable or field.
*/
Symbol findVar(Env<AttrContext> env, Name name) {
Symbol findVar(DiagnosticPosition pos, Env<AttrContext> env, Name name) {
Symbol bestSoFar = varNotFound;
Env<AttrContext> env1 = env;
boolean staticOnly = false;
@ -1508,7 +1510,7 @@ public class Resolve {
(sym.flags() & STATIC) == 0) {
if (staticOnly)
return new StaticError(sym);
if (env1.info.ctorPrologue && !isAllowedEarlyReference(env1, (VarSymbol)sym))
if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym))
return new RefBeforeCtorCalledError(sym);
}
return sym;
@ -2421,15 +2423,15 @@ public class Resolve {
* (a subset of VAL, TYP, PCK).
*/
Symbol findIdent(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
return checkNonExistentType(checkRestrictedType(pos, findIdentInternal(env, name, kind), name));
return checkNonExistentType(checkRestrictedType(pos, findIdentInternal(pos, env, name, kind), name));
}
Symbol findIdentInternal(Env<AttrContext> env, Name name, KindSelector kind) {
Symbol findIdentInternal(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
Symbol bestSoFar = typeNotFound;
Symbol sym;
if (kind.contains(KindSelector.VAL)) {
sym = findVar(env, name);
sym = findVar(pos, env, name);
if (sym.exists()) return sym;
else bestSoFar = bestOf(bestSoFar, sym);
}
@ -3776,7 +3778,7 @@ public class Resolve {
if (sym != null) {
if (staticOnly)
sym = new StaticError(sym);
else if (env1.info.ctorPrologue && !isAllowedEarlyReference(env1, (VarSymbol)sym))
else if (env1.info.ctorPrologue && !isAllowedEarlyReference(pos, env1, (VarSymbol)sym))
sym = new RefBeforeCtorCalledError(sym);
return accessBase(sym, pos, env.enclClass.sym.type,
name, true);
@ -3845,7 +3847,7 @@ public class Resolve {
* We also don't verify that the field has no initializer, which is required.
* To catch those cases, we rely on similar logic in Attr.checkAssignable().
*/
private boolean isAllowedEarlyReference(Env<AttrContext> env, VarSymbol v) {
private boolean isAllowedEarlyReference(DiagnosticPosition pos, Env<AttrContext> env, VarSymbol v) {
// Check assumptions
Assert.check(env.info.ctorPrologue);
@ -3880,6 +3882,9 @@ public class Resolve {
if (isEarlyReference(env, base, v) && v.owner != env.enclClass.sym)
return false;
// The flexible constructors feature must be enabled
preview.checkSourceLevel(pos, Feature.FLEXIBLE_CONSTRUCTORS);
// OK
return true;
}

View File

@ -0,0 +1,21 @@
/*
* @test /nodynamiccopyright/
* @bug 8334258
* @summary Disallow early assignment if FLEXIBLE_CONSTRUCTORS preview feature is not enabled
* @compile/fail/ref=EarlyAssignmentNoPreview1.out -XDrawDiagnostics EarlyAssignmentNoPreview1.java
*/
public class EarlyAssignmentNoPreview1 {
Runnable r;
public EarlyAssignmentNoPreview1() {
this(r = () -> System.out.println("hello"));
}
public EarlyAssignmentNoPreview1(Runnable r) {
}
public static void main(String[] args) {
new EarlyAssignmentNoPreview1();
}
}

View File

@ -0,0 +1,2 @@
EarlyAssignmentNoPreview1.java:12:14: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors)
1 error

View File

@ -0,0 +1,21 @@
/*
* @test /nodynamiccopyright/
* @bug 8334258
* @summary Disallow early assignment if FLEXIBLE_CONSTRUCTORS preview feature is not enabled
* @compile/fail/ref=EarlyAssignmentNoPreview2.out -XDrawDiagnostics EarlyAssignmentNoPreview2.java
*/
public class EarlyAssignmentNoPreview2 {
Runnable r;
public EarlyAssignmentNoPreview2() {
this(this.r = () -> System.out.println("hello"));
}
public EarlyAssignmentNoPreview2(Runnable r) {
}
public static void main(String[] args) {
new EarlyAssignmentNoPreview2();
}
}

View File

@ -0,0 +1,2 @@
EarlyAssignmentNoPreview2.java:12:14: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors)
1 error

View File

@ -0,0 +1,21 @@
/*
* @test /nodynamiccopyright/
* @bug 8334258
* @summary Disallow early assignment if FLEXIBLE_CONSTRUCTORS preview feature is not enabled
* @compile/fail/ref=EarlyAssignmentNoPreview3.out -XDrawDiagnostics EarlyAssignmentNoPreview3.java
*/
public class EarlyAssignmentNoPreview3 {
Runnable r;
public EarlyAssignmentNoPreview3() {
this(EarlyAssignmentNoPreview3.this.r = () -> System.out.println("hello"));
}
public EarlyAssignmentNoPreview3(Runnable r) {
}
public static void main(String[] args) {
new EarlyAssignmentNoPreview3();
}
}

View File

@ -0,0 +1,2 @@
EarlyAssignmentNoPreview3.java:12:39: compiler.err.preview.feature.disabled: (compiler.misc.feature.flexible.constructors)
1 error