Ensure disable private check cmd line option disables runtime private access checks (#10034)

Ensure that `--disable-private-check` cmd line option disables the runtime private access checks as well.
This commit is contained in:
Pavel Marek 2024-05-22 16:35:24 +02:00 committed by GitHub
parent 91a2afb098
commit ba2787c4d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 36 deletions

View File

@ -30,6 +30,7 @@ import org.enso.pkg.QualifiedName;
import org.enso.polyglot.PolyglotContext;
import org.enso.polyglot.RuntimeOptions;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Context.Builder;
import org.graalvm.polyglot.Language;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
@ -227,14 +228,16 @@ prefer-local-libraries: true
* Tests running the project located in the given {@code projDir}. Is equal to running {@code enso
* --run <projDir>}.
*
* @param ctxBuilder A context builder that might be initialized with some specific options.
* @param projDir Root directory of the project.
* @param resultConsumer Any action that is to be evaluated on the result of running the {@code
* main} method
*/
protected void testProjectRun(Path projDir, Consumer<Value> resultConsumer) {
protected void testProjectRun(
Context.Builder ctxBuilder, Path projDir, Consumer<Value> resultConsumer) {
assert projDir.toFile().exists() && projDir.toFile().isDirectory();
try (var ctx =
defaultContextBuilder()
ctxBuilder
.option(RuntimeOptions.PROJECT_ROOT, projDir.toAbsolutePath().toString())
.option(RuntimeOptions.STRICT_ERRORS, "true")
.option(RuntimeOptions.DISABLE_IR_CACHES, "true")
@ -249,6 +252,17 @@ prefer-local-libraries: true
}
}
/**
* Just a wrapper for {@link TestBase#testProjectRun(Builder, Path, Consumer)}.
*
* @param projDir Root directory of the project.
* @param resultConsumer Any action that is to be evaluated on the result of running the {@code
* main} method
*/
protected void testProjectRun(Path projDir, Consumer<Value> resultConsumer) {
testProjectRun(defaultContextBuilder(), projDir, resultConsumer);
}
/** A simple structure corresponding to an Enso module. */
public record SourceModule(QualifiedName name, String code) {}

View File

@ -1,4 +1,4 @@
package org.enso.interpreter.test;
package org.enso.interpreter.test.privateaccess;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
@ -10,6 +10,7 @@ import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import org.enso.interpreter.test.TestBase;
import org.enso.interpreter.util.ScalaConversions;
import org.enso.polyglot.PolyglotContext;
import org.enso.polyglot.RuntimeOptions;
@ -47,20 +48,13 @@ public class PrivateAccessTest extends TestBase {
main = My_Type.Cons 42
""";
var projDir = createProject("My_Project", mainSrc, tempFolder);
var mainSrcPath = projDir.resolve("src").resolve("Main.enso");
try (var ctx =
defaultContextBuilder()
.option(RuntimeOptions.PROJECT_ROOT, projDir.toAbsolutePath().toString())
.build()) {
var polyCtx = new PolyglotContext(ctx);
var mainMod = polyCtx.evalModule(mainSrcPath.toFile());
var assocType = mainMod.getAssociatedType();
var mainMethod = mainMod.getMethod(assocType, "main").get();
var res = mainMethod.execute();
assertThat(res.hasMember("data"), is(false));
assertThat(res.canInvokeMember("data"), is(false));
assertThat(res.getMember("data"), is(nullValue()));
}
testProjectRun(
projDir,
res -> {
assertThat(res.hasMember("data"), is(false));
assertThat(res.canInvokeMember("data"), is(false));
assertThat(res.getMember("data"), is(nullValue()));
});
}
@Test
@ -127,19 +121,12 @@ public class PrivateAccessTest extends TestBase {
_ -> 0
""";
var projDir = createProject("My_Project", mainSrc, tempFolder);
var mainSrcPath = projDir.resolve("src").resolve("Main.enso");
try (var ctx =
defaultContextBuilder()
.option(RuntimeOptions.PROJECT_ROOT, projDir.toAbsolutePath().toString())
.build()) {
var polyCtx = new PolyglotContext(ctx);
var mainMod = polyCtx.evalModule(mainSrcPath.toFile());
var assocType = mainMod.getAssociatedType();
var mainMethod = mainMod.getMethod(assocType, "main").get();
var res = mainMethod.execute();
assertThat(res.isNumber(), is(true));
assertThat(res.asInt(), is(42));
}
testProjectRun(
projDir,
res -> {
assertThat(res.isNumber(), is(true));
assertThat(res.asInt(), is(42));
});
}
/** Tests that pattern matching on private constructors fails in compilation. */

View File

@ -0,0 +1,40 @@
package org.enso.interpreter.test.privateaccess;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import java.io.IOException;
import org.enso.interpreter.test.TestBase;
import org.enso.polyglot.RuntimeOptions;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class PrivateCheckDisabledTest extends TestBase {
@Rule public TemporaryFolder tempFolder = new TemporaryFolder();
@Test
public void privateCtorCanBeAccessedWhenPrivateCheckIsDisabled() throws IOException {
var libSrc = """
type T
private Cons data
""";
createProject("Lib", libSrc, tempFolder);
var mainSrc =
"""
from local.Lib import T
main =
obj = T.Cons 42
obj.data
""";
var mainDir = createProject("Main", mainSrc, tempFolder);
var ctxBuilder = defaultContextBuilder().option(RuntimeOptions.DISABLE_PRIVATE_CHECK, "true");
testProjectRun(
ctxBuilder,
mainDir,
res -> {
assertThat(res.isNumber(), is(true));
assertThat(res.asInt(), is(42));
});
}
}

View File

@ -1,5 +1,6 @@
package org.enso.interpreter.node.callable.dispatch;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.TruffleFile;
import com.oracle.truffle.api.dsl.Cached;
@ -113,6 +114,16 @@ public abstract class InvokeFunctionNode extends BaseNode {
return new PanicException(err, this);
}
private void ensureFunctionIsAccessible(Function function, FunctionSchema functionSchema) {
var isPrivateCheckDisabled = getContext().isPrivateCheckDisabled();
CompilerAsserts.compilationConstant(isPrivateCheckDisabled);
if (!isPrivateCheckDisabled
&& functionSchema.isProjectPrivate()
&& !isInSameProject(function)) {
throw makePrivateAccessPanic(function);
}
}
@Specialization(
guards = {"!getContext().isInlineCachingDisabled()", "function.getSchema() == cachedSchema"},
limit = Constants.CacheSizes.ARGUMENT_SORTER_NODE)
@ -130,9 +141,7 @@ public abstract class InvokeFunctionNode extends BaseNode {
"build(argumentMapping, getDefaultsExecutionMode(), getArgumentsExecutionMode(),"
+ " getTailStatus())")
CurryNode curryNode) {
if (cachedSchema.isProjectPrivate() && !isInSameProject(function)) {
throw makePrivateAccessPanic(function);
}
ensureFunctionIsAccessible(function, cachedSchema);
ArgumentSorterNode.MappedArguments mappedArguments =
mappingNode.execute(callerFrame, function, state, arguments);
@ -174,9 +183,7 @@ public abstract class InvokeFunctionNode extends BaseNode {
Object[] arguments,
@Cached IndirectArgumentSorterNode mappingNode,
@Cached IndirectCurryNode curryNode) {
if (function.getSchema().isProjectPrivate() && !isInSameProject(function)) {
throw makePrivateAccessPanic(function);
}
ensureFunctionIsAccessible(function, function.getSchema());
CallArgumentInfo.ArgumentMapping argumentMapping =
CallArgumentInfo.ArgumentMappingBuilder.generate(function.getSchema(), getSchema());