Skip to content

Commit b457028

Browse files
committed
[GR-44691] Fixes in PyBytes_AsString(AndSize) and handle StackOverflowError.
PullRequest: graalpython/2738
2 parents dece777 + 1673f09 commit b457028

File tree

4 files changed

+52
-23
lines changed

4 files changed

+52
-23
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ char* PyBytes_AsString(PyObject *obj) {
7979

8080
int PyBytes_AsStringAndSize(PyObject *obj, char **s, Py_ssize_t *len) {
8181
*s = (char*)GraalPyTruffle_Bytes_AsString(obj);
82+
if (*s == NULL) {
83+
return -1;
84+
}
8285
if (len != NULL) {
8386
*len = GraalPyBytes_Size(obj);
8487
return 0;

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

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,17 @@ def _reference_from_object(args):
5656
return bytes(obj)
5757
raise TypeError("cannot convert '%s' object to bytes" % type(obj).__name__)
5858

59+
def _as_string(args):
60+
if not isinstance(args[0], bytes):
61+
return TypeError()
62+
return args[0].decode()
5963

6064
def _as_string_and_size(args):
65+
if not isinstance(args[0], bytes):
66+
return TypeError()
6167
arg_bytes = args[0]
6268
s = arg_bytes.decode("utf-8")
63-
return (0, s, len(s))
69+
return s, len(s)
6470

6571

6672
def _reference_format(args):
@@ -127,30 +133,43 @@ def compile_module(self, name):
127133

128134
# PyBytes_AsString
129135
test_PyBytes_AsString = CPyExtFunction(
130-
lambda b: b[0].decode(),
136+
_as_string,
131137
lambda: (
132138
(b"hello",),
133139
(b"world",),
134140
(BytesSubclass(b"hello"),),
141+
(list(),),
142+
("hello",)
135143
),
136144
resultspec="s",
137145
argspec="O",
138146
arguments=["PyObject* arg"],
147+
cmpfunc=unhandled_error_compare
139148
)
140149

141150
# PyBytes_AsStringAndSize
142-
test_PyBytes_AsStringAndSize = CPyExtFunctionOutVars(
151+
test_PyBytes_AsStringAndSize = CPyExtFunction(
143152
_as_string_and_size,
144153
lambda: (
145154
(b"hello",),
146155
(b"world",),
147156
(BytesSubclass(b"hello"),),
157+
(list(),),
158+
("hello",)
148159
),
149-
resultspec="isn",
160+
code="""
161+
static PyObject* wrap_PyBytes_AsStringAndSize(PyObject* arg) {
162+
char* s;
163+
Py_ssize_t sz;
164+
if (PyBytes_AsStringAndSize(arg, &s, &sz) < 0)
165+
return NULL;
166+
return Py_BuildValue("sn", s, sz);
167+
}
168+
""",
169+
callfunction='wrap_PyBytes_AsStringAndSize',
150170
argspec="O",
151171
arguments=["PyObject* arg"],
152-
resultvars=("char* s", "Py_ssize_t sz"),
153-
resulttype="int"
172+
cmpfunc=unhandled_error_compare
154173
)
155174

156175
test_native_storage = CPyExtFunction(

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

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

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.NotImplementedError;
44+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RecursionError;
4445
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError;
4546
import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Direct;
4647
import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Ignored;
@@ -109,6 +110,7 @@
109110
import com.oracle.graal.python.builtins.objects.cext.common.CExtToJavaNode;
110111
import com.oracle.graal.python.builtins.objects.cext.common.CExtToNativeNode;
111112
import com.oracle.graal.python.builtins.objects.code.PCode;
113+
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
112114
import com.oracle.graal.python.builtins.objects.frame.PFrame;
113115
import com.oracle.graal.python.builtins.objects.frame.PFrame.Reference;
114116
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
@@ -144,6 +146,7 @@
144146
import com.oracle.graal.python.runtime.PythonContext;
145147
import com.oracle.graal.python.runtime.PythonContext.GetThreadStateNode;
146148
import com.oracle.graal.python.runtime.PythonOptions;
149+
import com.oracle.graal.python.runtime.exception.ExceptionUtils;
147150
import com.oracle.graal.python.runtime.exception.PException;
148151
import com.oracle.graal.python.runtime.exception.PythonErrorType;
149152
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
@@ -249,6 +252,13 @@ public static PException checkThrowableBeforeNative(Throwable t, String where1,
249252
// ThreadDeath subclasses are used internally by Truffle
250253
throw td;
251254
}
255+
if (t instanceof StackOverflowError soe) {
256+
PythonContext context = PythonContext.get(null);
257+
context.reacquireGilAfterStackOverflow();
258+
PBaseException newException = context.factory().createBaseException(RecursionError, ErrorMessages.MAXIMUM_RECURSION_DEPTH_EXCEEDED, EMPTY_OBJECT_ARRAY);
259+
PException pe = ExceptionUtils.wrapJavaException(soe, null, newException);
260+
throw pe;
261+
}
252262
// everything else: log and convert to PException (SystemError)
253263
CompilerDirectives.transferToInterpreter();
254264
PNodeWithContext.printStack();

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

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,17 @@
7373
import com.oracle.graal.python.builtins.objects.bytes.PBytesLike;
7474
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
7575
import com.oracle.graal.python.builtins.objects.cext.capi.CApiGuards;
76-
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes;
76+
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
7777
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.ToSulongNode;
7878
import com.oracle.graal.python.builtins.objects.cext.capi.NativeMember;
7979
import com.oracle.graal.python.builtins.objects.cext.capi.PySequenceArrayWrapper;
8080
import com.oracle.graal.python.builtins.objects.cext.capi.PythonNativeWrapper;
8181
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor;
8282
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.NativeToPythonNode;
83-
import com.oracle.graal.python.builtins.objects.cext.common.CArrayWrappers;
8483
import com.oracle.graal.python.builtins.objects.cext.common.CExtCommonNodes.GetByteArrayNode;
8584
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
8685
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetItemScalarNode;
8786
import com.oracle.graal.python.builtins.objects.ints.PInt;
88-
import com.oracle.graal.python.builtins.objects.str.PString;
8987
import com.oracle.graal.python.builtins.objects.str.StringBuiltins.EncodeNode;
9088
import com.oracle.graal.python.builtins.objects.str.StringBuiltins.ModNode;
9189
import com.oracle.graal.python.lib.PyBytesCheckNode;
@@ -97,8 +95,8 @@
9795
import com.oracle.graal.python.nodes.PRaiseNode;
9896
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
9997
import com.oracle.graal.python.nodes.object.InlinedGetClassNode;
98+
import com.oracle.graal.python.nodes.object.InlinedGetClassNode.GetPythonObjectClassNode;
10099
import com.oracle.graal.python.nodes.util.CastToByteNode;
101-
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
102100
import com.oracle.graal.python.runtime.exception.PythonErrorType;
103101
import com.oracle.graal.python.runtime.sequence.storage.ByteSequenceStorage;
104102
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
@@ -132,7 +130,7 @@ Object doOther(PythonAbstractNativeObject obj,
132130
@Bind("this") Node inliningTarget,
133131
@Cached PyBytesCheckNode check,
134132
@Cached ToSulongNode toSulongNode,
135-
@Cached CExtNodes.PCallCapiFunction callMemberGetterNode) {
133+
@Cached PCallCapiFunction callMemberGetterNode) {
136134
if (check.execute(inliningTarget, obj)) {
137135
return callMemberGetterNode.call(NativeMember.OB_SIZE.getGetterFunctionName(), toSulongNode.execute(obj));
138136
}
@@ -407,21 +405,20 @@ static Object doBytes(PBytes bytes) {
407405
}
408406

409407
@Specialization
410-
static Object doUnicode(PString str,
411-
@Cached CastToTruffleStringNode castToStringNode) {
412-
return new CArrayWrappers.CStringWrapper(castToStringNode.execute(str));
413-
}
414-
415-
@Specialization
416-
static Object doNative(PythonAbstractNativeObject obj,
417-
@Cached CExtNodes.ToSulongNode toSulong,
418-
@Cached CExtNodes.PCallCapiFunction callMemberGetterNode) {
419-
return callMemberGetterNode.call(NativeMember.OB_SVAL.getGetterFunctionName(), toSulong.execute(obj));
408+
Object doNative(PythonAbstractNativeObject obj,
409+
@Cached GetPythonObjectClassNode getClassNode,
410+
@Cached IsSubtypeNode isSubtypeNode,
411+
@Cached ToSulongNode toSulong,
412+
@Cached PCallCapiFunction callMemberGetterNode) {
413+
if (isSubtypeNode.execute(getClassNode.execute(this, obj), PythonBuiltinClassType.PBytes)) {
414+
return callMemberGetterNode.call(NativeMember.OB_SVAL.getGetterFunctionName(), toSulong.execute(obj));
415+
}
416+
return doError(obj);
420417
}
421418

422419
@Fallback
423-
Object doUnicode(Object o) {
424-
throw raise(PythonErrorType.TypeError, ErrorMessages.EXPECTED_S_P_FOUND, "bytes", o);
420+
Object doError(Object obj) {
421+
throw raise(PythonErrorType.TypeError, ErrorMessages.EXPECTED_S_P_FOUND, "bytes", obj);
425422
}
426423
}
427424
}

0 commit comments

Comments
 (0)