Skip to content

Commit c29f564

Browse files
committed
[GR-22314] Give nice error message if native access is not allowed.
PullRequest: graalpython/1109
2 parents 54305b9 + cef03fa commit c29f564

File tree

2 files changed

+43
-28
lines changed

2 files changed

+43
-28
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*/
4141
package com.oracle.graal.python.builtins.modules;
4242

43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError;
4344
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__FILE__;
4445
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ImportError;
4546
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
@@ -78,12 +79,12 @@
7879
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
7980
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
8081
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
82+
import com.oracle.graal.python.nodes.statement.ExceptionHandlingStatementNode;
8183
import com.oracle.graal.python.parser.sst.SerializationUtils;
8284
import com.oracle.graal.python.runtime.ExecutionContext.ForeignCallContext;
8385
import com.oracle.graal.python.runtime.PythonContext;
8486
import com.oracle.graal.python.runtime.PythonOptions;
8587
import com.oracle.graal.python.runtime.exception.PException;
86-
import com.oracle.graal.python.runtime.exception.PythonErrorType;
8788
import com.oracle.truffle.api.CallTarget;
8889
import com.oracle.truffle.api.CompilerDirectives;
8990
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -230,17 +231,17 @@ private Object loadDynamicModuleWithSpec(String name, String path, InteropLibrar
230231
CallTarget callTarget = env.parseInternal(Source.newBuilder(LLVM_LANGUAGE, context.getPublicTruffleFileRelaxed(path, extSuffix)).build());
231232
sulongLibrary = (TruffleObject) callTarget.call();
232233
} catch (SecurityException | IOException e) {
233-
LOGGER.severe(() -> String.format("cannot load C extension '%s'", path));
234234
logJavaException(e);
235-
throw raise(ImportError, ErrorMessages.CANNOT_LOAD_M, path, e);
235+
throw raise(ImportError, wrapJavaException(e), ErrorMessages.CANNOT_LOAD_M, path, e);
236236
} catch (RuntimeException e) {
237237
throw reportImportError(e, path);
238238
}
239239
TruffleObject pyinitFunc;
240240
try {
241241
pyinitFunc = (TruffleObject) interop.readMember(sulongLibrary, "PyInit_" + basename);
242-
} catch (UnknownIdentifierException | UnsupportedMessageException e1) {
243-
throw raise(ImportError, ErrorMessages.NO_FUNCTION_FOUND, "PyInit_", basename, path);
242+
} catch (UnknownIdentifierException | UnsupportedMessageException e) {
243+
logJavaException(e);
244+
throw raise(ImportError, wrapJavaException(e), ErrorMessages.NO_FUNCTION_FOUND, "PyInit_", basename, path);
244245
}
245246
try {
246247
Object nativeResult = interop.execute(pyinitFunc);
@@ -250,7 +251,7 @@ private Object loadDynamicModuleWithSpec(String name, String path, InteropLibrar
250251
if (!(result instanceof PythonModule)) {
251252
// PyModuleDef_Init(pyModuleDef)
252253
// TODO: PyModule_FromDefAndSpec((PyModuleDef*)m, spec);
253-
throw raise(PythonErrorType.NotImplementedError, "multi-phase init of extension module %s", name);
254+
throw raise(NotImplementedError, "multi-phase init of extension module %s", name);
254255
} else {
255256
((PythonObject) result).setAttribute(__FILE__, path);
256257
// TODO: _PyImport_FixupExtensionObject(result, name, path, sys.modules)
@@ -259,50 +260,56 @@ private Object loadDynamicModuleWithSpec(String name, String path, InteropLibrar
259260
return result;
260261
}
261262
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
262-
e.printStackTrace();
263-
throw raise(ImportError, ErrorMessages.CANNOT_INITIALIZE_WITH, "PyInit_", path, basename);
263+
logJavaException(e);
264+
throw raise(ImportError, wrapJavaException(e), ErrorMessages.CANNOT_INITIALIZE_WITH, "PyInit_", path, basename);
264265
} catch (RuntimeException e) {
265266
throw reportImportError(e, path);
266267
}
267268
}
268269

269-
private static final String CAPI_LOAD_ERROR = "Could not load C API from %s.\n";
270-
271270
@TruffleBoundary
272271
private void ensureCapiWasLoaded() {
273272
PythonContext context = getContext();
274273
if (!context.hasCApiContext()) {
274+
if (!context.getEnv().isNativeAccessAllowed()) {
275+
throw raise(ImportError, ErrorMessages.NATIVE_ACCESS_NOT_ALLOWED);
276+
}
277+
275278
Env env = context.getEnv();
276279
CompilerDirectives.transferToInterpreterAndInvalidate();
277280

278281
String libPythonName = "libpython" + ExtensionSuffixesNode.getSoAbi(context);
279282
TruffleFile homePath = env.getInternalTruffleFile(context.getCAPIHome());
280283
TruffleFile capiFile = homePath.resolve(libPythonName);
281-
Object capi = null;
284+
Object capi;
282285
try {
283286
SourceBuilder capiSrcBuilder = Source.newBuilder(LLVM_LANGUAGE, capiFile);
284287
if (!context.getLanguage().getEngineOption(PythonOptions.ExposeInternalSources)) {
285288
capiSrcBuilder.internal(true);
286289
}
287290
capi = context.getEnv().parseInternal(capiSrcBuilder.build()).call();
288291
} catch (IOException | RuntimeException e) {
289-
LOGGER.severe(() -> String.format(CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath()));
290-
LOGGER.severe(() -> "Original error was: " + e);
291-
e.printStackTrace();
292-
throw raise(PythonErrorType.ImportError, CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
292+
logJavaException(e);
293+
throw raise(ImportError, wrapJavaException(e), ErrorMessages.CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
294+
}
295+
try {
296+
// call into Python to initialize python_cext module globals
297+
ReadAttributeFromObjectNode readNode = ReadAttributeFromObjectNode.getUncached();
298+
PythonModule builtinModule = context.getCore().lookupBuiltinModule(PythonCextBuiltins.PYTHON_CEXT);
299+
300+
CallUnaryMethodNode callNode = CallUnaryMethodNode.getUncached();
301+
callNode.executeObject(null, readNode.execute(builtinModule, INITIALIZE_CAPI), capi);
302+
context.setCapiWasLoaded(capi);
303+
callNode.executeObject(null, readNode.execute(builtinModule, RUN_CAPI_LOADED_HOOKS), capi);
304+
305+
// initialization needs to be finished already but load memoryview
306+
// implementation
307+
// immediately
308+
callNode.executeObject(null, readNode.execute(builtinModule, IMPORT_NATIVE_MEMORYVIEW), capi);
309+
} catch (RuntimeException e) {
310+
logJavaException(e);
311+
throw raise(ImportError, wrapJavaException(e), ErrorMessages.CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());
293312
}
294-
// call into Python to initialize python_cext module globals
295-
ReadAttributeFromObjectNode readNode = ReadAttributeFromObjectNode.getUncached();
296-
PythonModule builtinModule = context.getCore().lookupBuiltinModule(PythonCextBuiltins.PYTHON_CEXT);
297-
298-
CallUnaryMethodNode callNode = CallUnaryMethodNode.getUncached();
299-
callNode.executeObject(null, readNode.execute(builtinModule, INITIALIZE_CAPI), capi);
300-
context.setCapiWasLoaded(capi);
301-
callNode.executeObject(null, readNode.execute(builtinModule, RUN_CAPI_LOADED_HOOKS), capi);
302-
303-
// initialization needs to be finished already but load memoryview implementation
304-
// immediately
305-
callNode.executeObject(null, readNode.execute(builtinModule, IMPORT_NATIVE_MEMORYVIEW), capi);
306313
}
307314
}
308315

@@ -318,6 +325,12 @@ private static String getJavaStacktrace(Exception e) {
318325
return sw.toString();
319326
}
320327

328+
@TruffleBoundary
329+
private PBaseException wrapJavaException(Throwable e) {
330+
PBaseException excObject = factory().createBaseException(SystemError, e.getMessage(), new Object[0]);
331+
return ExceptionHandlingStatementNode.wrapJavaException(e, this, excObject).getEscapedException();
332+
}
333+
321334
private SetItemNode getSetItemNode() {
322335
if (setItemNode == null) {
323336
CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -468,7 +481,7 @@ public Object run(PCode code, String path) {
468481
}
469482
}
470483

471-
@Builtin(name = "extension_suffixes", minNumOfPositionalArgs = 0)
484+
@Builtin(name = "extension_suffixes")
472485
@GenerateNodeFactory
473486
public abstract static class ExtensionSuffixesNode extends PythonBuiltinNode {
474487
@Specialization

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,4 +522,6 @@ public abstract class ErrorMessages {
522522
public static final String CANNOT_ENCODE_DOCSTR = "'utf-8' codec can't encode docstring '%s'";
523523
public static final String PRECISION_NOT_ALLOWED_FOR_INT = "Precision not allowed in integer format specifier";
524524
public static final String SIGN_NOT_ALLOWED_WITH_C_FOR_INT = "Sign not allowed with integer format specifier 'c'";
525+
public static final String CAPI_LOAD_ERROR = "Could not load C API from %s.";
526+
public static final String NATIVE_ACCESS_NOT_ALLOWED = "Cannot run any C extensions because native access is not allowed.\n";
525527
}

0 commit comments

Comments
 (0)