Skip to content

Commit cf1c1a4

Browse files
committed
Avoid using PyLong_AsVoidPtr in ctypes
1 parent 74e6330 commit cf1c1a4

File tree

4 files changed

+141
-155
lines changed

4 files changed

+141
-155
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CDataTypeBuiltins.java

Lines changed: 31 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,21 @@
4141
package com.oracle.graal.python.builtins.modules.ctypes;
4242

4343
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.DICTFLAG_FINAL;
44-
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.getHandleFromLongObject;
4544
import static com.oracle.graal.python.nodes.ErrorMessages.BUFFER_SIZE_TOO_SMALL_D_INSTEAD_OF_AT_LEAST_D_BYTES;
4645
import static com.oracle.graal.python.nodes.ErrorMessages.CTYPES_OBJECT_STRUCTURE_TOO_DEEP;
4746
import static com.oracle.graal.python.nodes.ErrorMessages.EXPECTED_P_INSTANCE_GOT_P;
4847
import static com.oracle.graal.python.nodes.ErrorMessages.EXPECTED_P_INSTANCE_INSTEAD_OF_P;
4948
import static com.oracle.graal.python.nodes.ErrorMessages.EXPECTED_P_INSTANCE_INSTEAD_OF_POINTER_TO_P;
5049
import static com.oracle.graal.python.nodes.ErrorMessages.INCOMPATIBLE_TYPES_P_INSTANCE_INSTEAD_OF_P_INSTANCE;
51-
import static com.oracle.graal.python.nodes.ErrorMessages.INTEGER_EXPECTED;
5250
import static com.oracle.graal.python.nodes.ErrorMessages.NOT_A_CTYPE_INSTANCE;
5351
import static com.oracle.graal.python.nodes.ErrorMessages.OFFSET_CANNOT_BE_NEGATIVE;
5452
import static com.oracle.graal.python.nodes.ErrorMessages.THE_HANDLE_ATTRIBUTE_OF_THE_SECOND_ARGUMENT_MUST_BE_AN_INTEGER;
5553
import static com.oracle.graal.python.nodes.ErrorMessages.UNDERLYING_BUFFER_IS_NOT_C_CONTIGUOUS;
5654
import static com.oracle.graal.python.nodes.ErrorMessages.UNDERLYING_BUFFER_IS_NOT_WRITABLE;
5755
import static com.oracle.graal.python.nodes.StringLiterals.T_COLON;
58-
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
5956
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
6057
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
6158
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
62-
import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached;
6359
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
6460

6561
import java.util.List;
@@ -73,11 +69,9 @@
7369
import com.oracle.graal.python.builtins.modules.BuiltinConstructors;
7470
import com.oracle.graal.python.builtins.modules.BuiltinFunctions.IsInstanceNode;
7571
import com.oracle.graal.python.builtins.modules.SysModuleBuiltins.AuditNode;
76-
import com.oracle.graal.python.builtins.modules.cext.PythonCextLongBuiltins.PyLong_AsVoidPtr;
7772
import com.oracle.graal.python.builtins.modules.ctypes.CFieldBuiltins.GetFuncNode;
7873
import com.oracle.graal.python.builtins.modules.ctypes.CFieldBuiltins.SetFuncNode;
7974
import com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.CtypesDlSymNode;
80-
import com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.DLHandler;
8175
import com.oracle.graal.python.builtins.modules.ctypes.CtypesNodes.PyTypeCheck;
8276
import com.oracle.graal.python.builtins.modules.ctypes.FFIType.FieldGet;
8377
import com.oracle.graal.python.builtins.modules.ctypes.FFIType.FieldSet;
@@ -87,13 +81,15 @@
8781
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerNodes;
8882
import com.oracle.graal.python.builtins.objects.PNone;
8983
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary;
84+
import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr;
9085
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageSetItem;
9186
import com.oracle.graal.python.builtins.objects.dict.PDict;
9287
import com.oracle.graal.python.builtins.objects.memoryview.PMemoryView;
9388
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
9489
import com.oracle.graal.python.builtins.objects.type.TypeNodes.InlinedIsSameTypeNode;
9590
import com.oracle.graal.python.lib.PyLongCheckNode;
9691
import com.oracle.graal.python.lib.PyObjectLookupAttr;
92+
import com.oracle.graal.python.nodes.ErrorMessages;
9793
import com.oracle.graal.python.nodes.PGuards;
9894
import com.oracle.graal.python.nodes.PNodeWithRaise;
9995
import com.oracle.graal.python.nodes.PRaiseNode;
@@ -103,11 +99,11 @@
10399
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
104100
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryClinicBuiltinNode;
105101
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
102+
import com.oracle.graal.python.runtime.exception.PException;
106103
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
107104
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
108105
import com.oracle.truffle.api.dsl.Bind;
109106
import com.oracle.truffle.api.dsl.Cached;
110-
import com.oracle.truffle.api.dsl.Fallback;
111107
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
112108
import com.oracle.truffle.api.dsl.ImportStatic;
113109
import com.oracle.truffle.api.dsl.NodeFactory;
@@ -201,17 +197,11 @@ Object CDataType_from_param(VirtualFrame frame, Object type, Object value,
201197
public abstract static class FromAddressNode extends PythonBinaryBuiltinNode {
202198

203199
@Specialization
204-
Object CDataType_from_address(Object type, int value,
205-
@Cached PyLong_AsVoidPtr asVoidPtr,
200+
static Object CDataType_from_address(Object type, Object value,
201+
@Bind("this") Node inliningTarget,
202+
@Cached PointerNodes.PointerFromLongNode pointerFromLongNode,
206203
@Cached PyCDataAtAddress atAddress) {
207-
Object buf = asVoidPtr.execute(value);
208-
return atAddress.execute(type, buf, 0);
209-
}
210-
211-
@SuppressWarnings("unused")
212-
@Fallback
213-
Object error(Object type, Object arg) {
214-
throw raise(TypeError, INTEGER_EXPECTED);
204+
return atAddress.execute(type, pointerFromLongNode.execute(inliningTarget, value));
215205
}
216206
}
217207

@@ -235,29 +225,29 @@ Object CDataType_from_buffer(VirtualFrame frame, Object type, Object obj, int of
235225
@Cached AuditNode auditNode) {
236226
StgDictObject dict = pyTypeStgDictNode.checkAbstractClass(type, getRaiseNode());
237227

238-
PMemoryView buffer = memoryViewNode.execute(frame, obj);
228+
PMemoryView mv = memoryViewNode.execute(frame, obj);
239229

240-
if (buffer.isReadOnly()) {
230+
if (mv.isReadOnly()) {
241231
throw raise(TypeError, UNDERLYING_BUFFER_IS_NOT_WRITABLE);
242232
}
243233

244-
if (!buffer.isCContiguous()) {
234+
if (!mv.isCContiguous()) {
245235
throw raise(TypeError, UNDERLYING_BUFFER_IS_NOT_C_CONTIGUOUS);
246236
}
247237

248238
if (offset < 0) {
249239
throw raise(ValueError, OFFSET_CANNOT_BE_NEGATIVE);
250240
}
251241

252-
if (dict.size > buffer.getLength() - offset) {
253-
throw raise(ValueError, BUFFER_SIZE_TOO_SMALL_D_INSTEAD_OF_AT_LEAST_D_BYTES, buffer.getLength(), dict.size + offset);
242+
if (dict.size > mv.getLength() - offset) {
243+
throw raise(ValueError, BUFFER_SIZE_TOO_SMALL_D_INSTEAD_OF_AT_LEAST_D_BYTES, mv.getLength(), dict.size + offset);
254244
}
255245

256-
auditNode.audit("ctypes.cdata/buffer", buffer, buffer.getLength(), offset);
246+
auditNode.audit("ctypes.cdata/buffer", mv, mv.getLength(), offset);
257247

258-
CDataObject result = atAddress.execute(type, buffer, offset);
248+
CDataObject result = atAddress.execute(type, Pointer.memoryView(mv).withOffset(offset));
259249

260-
keepRefNode.execute(frame, result, -1, buffer);
250+
keepRefNode.execute(frame, result, -1, mv);
261251

262252
return result;
263253
}
@@ -323,32 +313,41 @@ protected ArgumentClinicProvider getArgumentClinic() {
323313

324314
@Specialization
325315
Object CDataType_in_dll(VirtualFrame frame, Object type, Object dll, TruffleString name,
316+
@Bind("this") Node inliningTarget,
326317
@Cached PyLongCheckNode longCheckNode,
327318
@Cached("create(T__HANDLE)") GetAttributeNode getAttributeNode,
328319
@Cached PyCDataAtAddress atAddress,
329320
@Cached AuditNode auditNode,
330-
@Cached PyLong_AsVoidPtr asVoidPtr,
321+
@Cached PointerNodes.PointerFromLongNode pointerFromLongNode,
331322
@Cached CtypesDlSymNode dlSymNode) {
332323
auditNode.audit("ctypes.dlsym", dll, name);
333324
Object obj = getAttributeNode.executeObject(frame, dll);
334325
if (!longCheckNode.execute(obj)) {
335326
throw raise(TypeError, THE_HANDLE_ATTRIBUTE_OF_THE_SECOND_ARGUMENT_MUST_BE_AN_INTEGER);
336327
}
337-
DLHandler handle = getHandleFromLongObject(obj, getContext(), asVoidPtr, getRaiseNode());
338-
Object address = dlSymNode.execute(frame, handle, name, ValueError);
339-
return atAddress.execute(type, address, 0);
328+
Pointer handlePtr;
329+
try {
330+
handlePtr = pointerFromLongNode.execute(inliningTarget, obj);
331+
} catch (PException e) {
332+
throw raise(ValueError, ErrorMessages.COULD_NOT_CONVERT_THE_HANDLE_ATTRIBUTE_TO_A_POINTER);
333+
}
334+
Object address = dlSymNode.execute(frame, handlePtr, name, ValueError);
335+
if (address instanceof PythonNativeVoidPtr ptr) {
336+
address = ptr.getPointerObject();
337+
}
338+
return atAddress.execute(type, Pointer.nativeMemory(address));
340339
}
341340
}
342341

343342
protected abstract static class PyCDataAtAddress extends PNodeWithRaise {
344343

345-
abstract CDataObject execute(Object type, Object obj, int offset);
344+
abstract CDataObject execute(Object type, Pointer pointer);
346345

347346
/*
348347
* Box a memory block into a CData instance.
349348
*/
350349
@Specialization
351-
CDataObject PyCData_AtAddress_bytes(Object type, byte[] buf, int offset,
350+
CDataObject PyCData_AtAddress(Object type, Pointer pointer,
352351
@Cached PyTypeCheck pyTypeCheck,
353352
@Cached PyTypeStgDictNode pyTypeStgDictNode,
354353
@Cached PythonObjectFactory factory) {
@@ -359,40 +358,11 @@ CDataObject PyCData_AtAddress_bytes(Object type, byte[] buf, int offset,
359358

360359
CDataObject pd = factory.createCDataObject(type);
361360
assert pyTypeCheck.isCDataObject(pd);
362-
pd.b_ptr = Pointer.bytes(buf, offset);
361+
pd.b_ptr = pointer;
363362
pd.b_length = stgdict.length;
364363
pd.b_size = stgdict.size;
365364
return pd;
366365
}
367-
368-
protected static boolean isBytes(Object obj) {
369-
return obj instanceof byte[];
370-
}
371-
372-
@Specialization(guards = "!isBytes(obj)")
373-
CDataObject PyCData_AtAddress(Object type, Object obj, @SuppressWarnings("unused") int offset,
374-
@Cached PyTypeCheck pyTypeCheck,
375-
@Cached PyTypeStgDictNode pyTypeStgDictNode,
376-
@Cached AuditNode auditNode,
377-
@Cached PythonObjectFactory factory) {
378-
auditNode.audit("ctypes.cdata", obj);
379-
// assert(PyType_Check(type));
380-
StgDictObject stgdict = pyTypeStgDictNode.checkAbstractClass(type, getRaiseNode());
381-
stgdict.flags |= DICTFLAG_FINAL;
382-
383-
CDataObject pd = factory.createCDataObject(type);
384-
assert (pyTypeCheck.isCDataObject(pd));
385-
if (obj instanceof PMemoryView) {
386-
pd.b_ptr = Pointer.memoryView((PMemoryView) obj);
387-
} else {
388-
// TODO get Objects from numeric pointers.
389-
throw raise(NotImplementedError, toTruffleStringUncached("Storage is not implemented."));
390-
}
391-
pd.b_length = stgdict.length;
392-
pd.b_size = stgdict.size;
393-
return pd;
394-
}
395-
396366
}
397367

398368
// corresponds to PyCData_get

0 commit comments

Comments
 (0)