Skip to content

Commit 8b7369d

Browse files
committed
[GR-53369] Fixes for optuna, pyarrow, psycopg2, cryptography
PullRequest: graalpython/3314
2 parents 2cb20be + 9a81fe4 commit 8b7369d

File tree

18 files changed

+186
-98
lines changed

18 files changed

+186
-98
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,10 @@ PyAPI_FUNC(void*) truffle_convert_pointer(Py_ssize_t value) {
839839
return (void*) value;
840840
}
841841

842+
PyAPI_FUNC(int) truffle_no_op_clear(PyObject* o) {
843+
return 0;
844+
}
845+
842846
// defined in 'exceptions.c'
843847
void initialize_exceptions();
844848
// defined in 'pyhash.c'

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_abstract.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,15 @@ class DummyDequeLen(set):
280280
def __len__(self):
281281
return 42
282282

283+
284+
class DictSubclassWithSequenceMethods(dict):
285+
def __getitem__(self, key):
286+
return key
287+
288+
def __setitem__(self, key, value):
289+
pass
290+
291+
283292
def _default_bin_arith_args():
284293
return (
285294
(0, 0),
@@ -374,7 +383,8 @@ def _size_and_check_args():
374383
(DummyDeque(),),
375384
(DummyDeque([1,2,3]),),
376385
(DummyDequeLen(),),
377-
(DummyDequeLen([1,2,3]),),
386+
(DummyDequeLen([1,2,3]),),
387+
(DictSubclassWithSequenceMethods(),),
378388
)
379389

380390
class TestAbstractWithNative(object):
@@ -1164,6 +1174,7 @@ class TestAbstract(CPyExtTestCase):
11641174
({'a', 'b'}, 0),
11651175
(DummyListSubclass(), 1),
11661176
('hello', 1),
1177+
(DictSubclassWithSequenceMethods(), 1),
11671178
),
11681179
resultspec="O",
11691180
argspec='On',
@@ -1336,6 +1347,7 @@ def _reference_delslice(args):
13361347
([], 10, 1),
13371348
(['a', 'b', 'c'], 2, 'z'),
13381349
('hello', 2, 'z'),
1350+
(DictSubclassWithSequenceMethods(), 1, 1)
13391351
),
13401352
code=''' PyObject* wrap_PySequence_SetItem(PyObject* sequence, Py_ssize_t idx, PyObject* value) {
13411353
if (PySequence_SetItem(sequence, idx, value) < 0) {

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_err.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,3 +812,19 @@ def gen():
812812
e = ExceptionSubclass()
813813
e1 = g.throw(e)
814814
assert e1 is e
815+
816+
def test_tp_clear(self):
817+
# psycopg2 calls ((PyTypeObject *)PyExc_Exception)->tp_clear from their exception subclass's dealloc
818+
# We need to make sure it doesn't segfault
819+
Tester = CPyExtType(
820+
"TpClearTester",
821+
code="""
822+
static PyObject* test(PyObject* unused, PyObject* unused2) {
823+
PyBaseExceptionObject o = {0};
824+
((PyTypeObject *)PyExc_Exception)->tp_clear((PyObject*)&o);
825+
Py_RETURN_NONE;
826+
}
827+
""",
828+
tp_methods='{"test", (PyCFunction)test, METH_NOARGS | METH_STATIC, ""}',
829+
)
830+
Tester.test()
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
from collections import OrderedDict
41+
42+
import weakref
43+
44+
45+
def test_allows_ref():
46+
o = OrderedDict()
47+
weakref.ref(o)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/BouncyCastleFeature.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,22 @@
4242

4343
import java.security.Security;
4444

45-
import com.oracle.graal.python.runtime.PythonImageBuildOptions;
4645
import org.graalvm.nativeimage.ImageSingletons;
4746
import org.graalvm.nativeimage.hosted.Feature;
4847
import org.graalvm.nativeimage.hosted.RuntimeReflection;
4948
import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport;
5049

5150
import com.oracle.graal.python.builtins.objects.ssl.CertUtils;
51+
import com.oracle.graal.python.runtime.PythonImageBuildOptions;
5252

5353
public class BouncyCastleFeature implements Feature {
5454
@Override
5555
public void afterRegistration(AfterRegistrationAccess access) {
5656
if (!PythonImageBuildOptions.WITHOUT_SSL) {
5757
RuntimeClassInitializationSupport support = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
5858
support.initializeAtBuildTime("org.bouncycastle", "security provider");
59-
support.rerunInitialization("org.bouncycastle.jcajce.provider.drbg.DRBG$Default", "RNG");
60-
support.rerunInitialization("org.bouncycastle.jcajce.provider.drbg.DRBG$NonceAndIV", "RNG");
59+
support.initializeAtRunTime("org.bouncycastle.jcajce.provider.drbg.DRBG$Default", "RNG");
60+
support.initializeAtRunTime("org.bouncycastle.jcajce.provider.drbg.DRBG$NonceAndIV", "RNG");
6161
Security.addProvider(CertUtils.BOUNCYCASTLE_PROVIDER);
6262

6363
// Register runtime reflection here, not in a config, so it can be easily disabled

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ public static int getBuiltinTypeWeaklistoffset(PythonBuiltinClassType cls) {
153153
-> 144;
154154
case PickleBuffer -> 96; // _pickle.PickleBuffer
155155
case PTextIOWrapper -> 176; // _io.TextIOWrapper
156+
case POrderedDict -> 104;
156157
default -> 0;
157158
// @formatter:on
158159
};

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextAbstractBuiltins.java

Lines changed: 22 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,13 @@
5555
import static com.oracle.graal.python.nodes.BuiltinNames.T_SEND;
5656
import static com.oracle.graal.python.nodes.ErrorMessages.BASE_MUST_BE;
5757
import static com.oracle.graal.python.nodes.ErrorMessages.OBJ_ISNT_MAPPING;
58-
import static com.oracle.graal.python.nodes.ErrorMessages.P_OBJ_DOES_NOT_SUPPORT_ITEM_ASSIGMENT;
5958
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___DOC__;
6059
import static com.oracle.graal.python.nodes.SpecialMethodNames.T_ITEMS;
6160
import static com.oracle.graal.python.nodes.SpecialMethodNames.T_KEYS;
6261
import static com.oracle.graal.python.nodes.SpecialMethodNames.T_VALUES;
6362
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___GETITEM__;
6463
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___IADD__;
6564
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___IMUL__;
66-
import static com.oracle.graal.python.nodes.SpecialMethodNames.T___SETITEM__;
6765

6866
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
6967
import com.oracle.graal.python.builtins.modules.BuiltinConstructors;
@@ -96,7 +94,6 @@
9694
import com.oracle.graal.python.builtins.objects.ints.PInt;
9795
import com.oracle.graal.python.builtins.objects.iterator.IteratorNodes;
9896
import com.oracle.graal.python.builtins.objects.list.PList;
99-
import com.oracle.graal.python.builtins.objects.mappingproxy.PMappingproxy;
10097
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
10198
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode;
10299
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsTypeNode;
@@ -107,15 +104,16 @@
107104
import com.oracle.graal.python.lib.PyNumberFloatNode;
108105
import com.oracle.graal.python.lib.PyNumberIndexNode;
109106
import com.oracle.graal.python.lib.PyObjectCallMethodObjArgs;
110-
import com.oracle.graal.python.lib.PyObjectDelItem;
111107
import com.oracle.graal.python.lib.PyObjectGetAttr;
112108
import com.oracle.graal.python.lib.PyObjectGetItem;
113109
import com.oracle.graal.python.lib.PyObjectLookupAttr;
114-
import com.oracle.graal.python.lib.PyObjectSizeNode;
115110
import com.oracle.graal.python.lib.PySequenceCheckNode;
116111
import com.oracle.graal.python.lib.PySequenceContainsNode;
112+
import com.oracle.graal.python.lib.PySequenceDelItemNode;
117113
import com.oracle.graal.python.lib.PySequenceGetItemNode;
118114
import com.oracle.graal.python.lib.PySequenceIterSearchNode;
115+
import com.oracle.graal.python.lib.PySequenceSetItemNode;
116+
import com.oracle.graal.python.lib.PySequenceSizeNode;
119117
import com.oracle.graal.python.lib.PySliceNew;
120118
import com.oracle.graal.python.nodes.ErrorMessages;
121119
import com.oracle.graal.python.nodes.PRaiseNode;
@@ -149,7 +147,6 @@
149147
import com.oracle.truffle.api.dsl.TypeSystemReference;
150148
import com.oracle.truffle.api.frame.VirtualFrame;
151149
import com.oracle.truffle.api.nodes.Node;
152-
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
153150
import com.oracle.truffle.api.strings.TruffleString;
154151

155152
public final class PythonCextAbstractBuiltins {
@@ -501,29 +498,15 @@ Object values(Object obj,
501498

502499
@CApiBuiltin(ret = Int, args = {PyObject, Py_ssize_t, PyObject}, call = Ignored)
503500
public abstract static class PyTruffleSequence_SetItem extends CApiTernaryBuiltinNode {
504-
@Specialization(guards = "checkNode.execute(inliningTarget, obj)", limit = "1")
505-
static Object setItem(Object obj, Object key, Object value,
501+
@Specialization
502+
static Object setItem(Object obj, long key, Object value,
506503
@Bind("this") Node inliningTarget,
507-
@SuppressWarnings("unused") @Exclusive @Cached PySequenceCheckNode checkNode,
508-
@Cached PyObjectLookupAttr lookupAttrNode,
509-
@Cached InlinedConditionProfile hasSetItem,
510-
@Cached CallNode callNode,
511-
@Cached PRaiseNode.Lazy raiseNode) {
512-
Object setItemCallable = lookupAttrNode.execute(null, inliningTarget, obj, T___SETITEM__);
513-
if (hasSetItem.profile(inliningTarget, setItemCallable == PNone.NO_VALUE)) {
514-
throw raiseNode.get(inliningTarget).raise(TypeError, P_OBJ_DOES_NOT_SUPPORT_ITEM_ASSIGMENT, obj);
515-
} else {
516-
callNode.execute(setItemCallable, key, value);
517-
return 0;
504+
@Cached PySequenceSetItemNode setItemNode) {
505+
if ((int) key != key) {
506+
throw PRaiseNode.raiseUncached(inliningTarget, OverflowError, ErrorMessages.CANNOT_FIT_P_INTO_INDEXSIZED_INT, key);
518507
}
519-
}
520-
521-
@Specialization(guards = "!checkNode.execute(inliningTarget, obj)", limit = "1")
522-
static Object setItem(Object obj, @SuppressWarnings("unused") Object key, @SuppressWarnings("unused") Object value,
523-
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
524-
@SuppressWarnings("unused") @Exclusive @Cached PySequenceCheckNode checkNode,
525-
@Cached PRaiseNode raiseNode) {
526-
throw raiseNode.raise(TypeError, ErrorMessages.IS_NOT_A_SEQUENCE, obj);
508+
setItemNode.execute(obj, (int) key, value);
509+
return 0;
527510
}
528511
}
529512

@@ -673,21 +656,25 @@ protected BinaryArithmetic.AddNode createAdd() {
673656
@CApiBuiltin(ret = Int, args = {PyObject, Py_ssize_t}, call = Ignored)
674657
abstract static class PyTruffleSequence_DelItem extends CApiBinaryBuiltinNode {
675658
@Specialization
676-
static Object run(Object o, Object i,
659+
static Object run(Object o, long i,
677660
@Bind("this") Node inliningTarget,
678-
@Cached PyObjectDelItem delItemNode) {
679-
delItemNode.execute(null, inliningTarget, o, i);
661+
@Cached PySequenceDelItemNode delItemNode) {
662+
if ((int) i != i) {
663+
throw PRaiseNode.raiseUncached(inliningTarget, OverflowError, ErrorMessages.CANNOT_FIT_P_INTO_INDEXSIZED_INT, i);
664+
}
665+
delItemNode.execute(o, (int) i);
680666
return 0;
681667
}
682668
}
683669

684670
@CApiBuiltin(ret = PyObjectTransfer, args = {PyObject, Py_ssize_t}, call = Ignored)
685671
abstract static class PyTruffleSequence_GetItem extends CApiBinaryBuiltinNode {
686672
@Specialization
687-
Object doManaged(Object delegate, long position,
673+
static Object doManaged(Object delegate, long position,
674+
@Bind("this") Node inliningTarget,
688675
@Cached PySequenceGetItemNode getItemNode) {
689676
if ((int) position != position) {
690-
throw PRaiseNode.raiseUncached(this, OverflowError, ErrorMessages.CANNOT_FIT_P_INTO_INDEXSIZED_INT, position);
677+
throw PRaiseNode.raiseUncached(inliningTarget, OverflowError, ErrorMessages.CANNOT_FIT_P_INTO_INDEXSIZED_INT, position);
691678
}
692679
return getItemNode.execute(null, delegate, (int) position);
693680
}
@@ -696,21 +683,11 @@ Object doManaged(Object delegate, long position,
696683
@CApiBuiltin(ret = Py_ssize_t, args = {PyObject}, call = Ignored)
697684
abstract static class PyTruffleSequence_Size extends CApiUnaryBuiltinNode {
698685

699-
// cant use PySequence_Size: PySequence_Size returns the __len__ value also for
700-
// subclasses of types not accepted by PySequence_Check as long they have an overriden
701-
// __len__ method
702686
@Specialization
703-
static Object doSequence(Object obj,
687+
static int doSequence(Object obj,
704688
@Bind("this") Node inliningTarget,
705-
@Cached IsSameTypeNode isSameType,
706-
@Cached GetClassNode getClassNode,
707-
@Cached PyObjectSizeNode sizeNode,
708-
@Cached PRaiseNode.Lazy raiseNode) {
709-
if (obj instanceof PMappingproxy || isSameType.execute(inliningTarget, getClassNode.execute(inliningTarget, obj), PythonBuiltinClassType.PDict)) {
710-
throw raiseNode.get(inliningTarget).raise(TypeError, ErrorMessages.IS_NOT_A_SEQUENCE, obj);
711-
} else {
712-
return sizeNode.execute(null, inliningTarget, obj);
713-
}
689+
@Cached PySequenceSizeNode sizeNode) {
690+
return sizeNode.execute(null, inliningTarget, obj);
714691
}
715692
}
716693

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CExtNodes.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.builtins.objects.cext.capi;
4242

4343
import static com.oracle.graal.python.builtins.objects.PNone.NO_VALUE;
44+
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_NO_OP_CLEAR;
4445
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PTR_ADD;
4546
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PTR_COMPARE;
4647
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PY_DEALLOC;
@@ -136,6 +137,7 @@
136137
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
137138
import com.oracle.graal.python.builtins.objects.type.PythonClass;
138139
import com.oracle.graal.python.builtins.objects.type.PythonManagedClass;
140+
import com.oracle.graal.python.builtins.objects.type.TypeFlags;
139141
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
140142
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
141143
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetMroStorageNode;
@@ -890,19 +892,24 @@ public static PCallCapiFunction getUncached() {
890892
*/
891893
@TruffleBoundary
892894
public static Object lookupNativeMemberInMRO(PythonManagedClass cls, @SuppressWarnings("unused") CFields nativeMemberName, HiddenAttr managedMemberName) {
893-
if (cls instanceof PythonClass && (managedMemberName == HiddenAttr.ALLOC || managedMemberName == HiddenAttr.FREE)) {
894-
Object func = HiddenAttr.ReadNode.executeUncached(cls, managedMemberName, null);
895-
if (func != null) {
896-
return func;
897-
}
895+
if (cls instanceof PythonClass) {
896+
NativeCAPISymbol symbol = null;
898897
// We need to point to PyType_GenericAlloc or PyObject_GC_Del
899-
NativeCAPISymbol symbol;
900898
if (managedMemberName == HiddenAttr.ALLOC) {
901899
symbol = FUN_PY_TYPE_GENERIC_ALLOC;
902-
} else {
900+
} else if (managedMemberName == HiddenAttr.FREE) {
903901
symbol = FUN_PY_OBJECT_GC_DEL;
902+
} else if (managedMemberName == HiddenAttr.CLEAR) {
903+
// This will need to be subtype_clear when we implement native GC
904+
symbol = FUN_NO_OP_CLEAR;
905+
}
906+
if (symbol != null) {
907+
Object func = HiddenAttr.ReadNode.executeUncached(cls, managedMemberName, null);
908+
if (func != null) {
909+
return func;
910+
}
911+
return CApiContext.getNativeSymbol(null, symbol);
904912
}
905-
return CApiContext.getNativeSymbol(null, symbol);
906913
}
907914
MroSequenceStorage mroStorage = GetMroStorageNode.executeUncached(cls);
908915
int n = mroStorage.length();
@@ -921,6 +928,9 @@ public static Object lookupNativeMemberInMRO(PythonManagedClass cls, @SuppressWa
921928
}
922929
}
923930
}
931+
if (managedMemberName == HiddenAttr.CLEAR && (TypeNodes.GetTypeFlagsNode.executeUncached(cls) & TypeFlags.HAVE_GC) != 0) {
932+
return CApiContext.getNativeSymbol(null, FUN_NO_OP_CLEAR);
933+
}
924934
return HiddenAttr.ReadNode.executeUncached(PythonContext.get(null).lookupType(PythonBuiltinClassType.PythonObject), managedMemberName, NO_VALUE);
925935
}
926936

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/NativeCAPISymbol.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public enum NativeCAPISymbol implements NativeCExtSymbol {
7070

7171
FUN_VA_ARG_POINTER("truffle_va_arg_pointer", Pointer, Pointer),
7272
FUN_CONVERT_POINTER("truffle_convert_pointer", Pointer, Py_ssize_t),
73+
FUN_NO_OP_CLEAR("truffle_no_op_clear", Int, PyObject),
7374

7475
FUN_PYTRUFFLE_CONSTANTS("PyTruffle_constants", PY_SSIZE_T_PTR),
7576
FUN_PYTRUFFLE_STRUCT_OFFSETS("PyTruffle_struct_offsets", PY_SSIZE_T_PTR),

0 commit comments

Comments
 (0)