summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Modules/_struct.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Modules/_struct.c')
-rw-r--r--contrib/tools/python3/Modules/_struct.c163
1 files changed, 103 insertions, 60 deletions
diff --git a/contrib/tools/python3/Modules/_struct.c b/contrib/tools/python3/Modules/_struct.c
index 6532174a0b1..f5e1c62bb24 100644
--- a/contrib/tools/python3/Modules/_struct.c
+++ b/contrib/tools/python3/Modules/_struct.c
@@ -7,12 +7,13 @@
# define Py_BUILD_CORE_MODULE 1
#endif
-#define PY_SSIZE_T_CLEAN
-
#include "Python.h"
+#include "pycore_bytesobject.h" // _PyBytesWriter
+#include "pycore_long.h" // _PyLong_AsByteArray()
#include "pycore_moduleobject.h" // _PyModule_GetState()
-#include "structmember.h" // PyMemberDef
-#include <ctype.h>
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
+
+#include <stddef.h> // offsetof()
/*[clinic input]
class Struct "PyStructObject *" "&PyStructType"
@@ -107,19 +108,22 @@ class cache_struct_converter(CConverter):
type = 'PyStructObject *'
converter = 'cache_struct_converter'
c_default = "NULL"
+ broken_limited_capi = True
- def parse_arg(self, argname, displayname):
- return """
+ def parse_arg(self, argname, displayname, *, limited_capi):
+ assert not limited_capi
+ return self.format_code("""
if (!{converter}(module, {argname}, &{paramname})) {{{{
goto exit;
}}}}
- """.format(argname=argname, paramname=self.name,
- converter=self.converter)
+ """,
+ argname=argname,
+ converter=self.converter)
def cleanup(self):
return "Py_XDECREF(%s);\n" % self.name
[python start generated code]*/
-/*[python end generated code: output=da39a3ee5e6b4b0d input=d6746621c2fb1a7d]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=c33b27d6b06006c6]*/
static int cache_struct_converter(PyObject *, PyObject *, PyStructObject **);
@@ -764,14 +768,13 @@ np_halffloat(_structmodulestate *state, char *p, PyObject *v, const formatdef *f
static int
np_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
{
- float x = (float)PyFloat_AsDouble(v);
+ double x = PyFloat_AsDouble(v);
if (x == -1 && PyErr_Occurred()) {
PyErr_SetString(state->StructError,
"required argument is not a float");
return -1;
}
- memcpy(p, (char *)&x, sizeof x);
- return 0;
+ return PyFloat_Pack4(x, p, PY_LITTLE_ENDIAN);
}
static int
@@ -996,9 +999,10 @@ bp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
(unsigned char *)p,
8,
0, /* little_endian */
- 1 /* signed */);
+ 1, /* signed */
+ 0 /* !with_exceptions */);
Py_DECREF(v);
- if (res == -1 && PyErr_Occurred()) {
+ if (res < 0) {
PyErr_Format(state->StructError,
"'%c' format requires %lld <= number <= %lld",
f->format,
@@ -1020,9 +1024,10 @@ bp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f
(unsigned char *)p,
8,
0, /* little_endian */
- 0 /* signed */);
+ 0, /* signed */
+ 0 /* !with_exceptions */);
Py_DECREF(v);
- if (res == -1 && PyErr_Occurred()) {
+ if (res < 0) {
PyErr_Format(state->StructError,
"'%c' format requires 0 <= number <= %llu",
f->format,
@@ -1256,9 +1261,10 @@ lp_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
(unsigned char *)p,
8,
1, /* little_endian */
- 1 /* signed */);
+ 1, /* signed */
+ 0 /* !with_exceptions */);
Py_DECREF(v);
- if (res == -1 && PyErr_Occurred()) {
+ if (res < 0) {
PyErr_Format(state->StructError,
"'%c' format requires %lld <= number <= %lld",
f->format,
@@ -1280,9 +1286,10 @@ lp_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f
(unsigned char *)p,
8,
1, /* little_endian */
- 0 /* signed */);
+ 0, /* signed */
+ 0 /* !with_exceptions */);
Py_DECREF(v);
- if (res == -1 && PyErr_Occurred()) {
+ if (res < 0) {
PyErr_Format(state->StructError,
"'%c' format requires 0 <= number <= %llu",
f->format,
@@ -1412,11 +1419,11 @@ align(Py_ssize_t size, char c, const formatdef *e)
/* calculate the size of a format string */
static int
-prepare_s(PyStructObject *self)
+prepare_s(PyStructObject *self, PyObject *format)
{
const formatdef *f;
const formatdef *e;
- formatcode *codes;
+ formatcode *codes, *codes0;
const char *s;
const char *fmt;
@@ -1426,8 +1433,8 @@ prepare_s(PyStructObject *self)
_structmodulestate *state = get_struct_state_structinst(self);
- fmt = PyBytes_AS_STRING(self->s_format);
- if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(self->s_format)) {
+ fmt = PyBytes_AS_STRING(format);
+ if (strlen(fmt) != (size_t)PyBytes_GET_SIZE(format)) {
PyErr_SetString(state->StructError,
"embedded null character");
return -1;
@@ -1468,9 +1475,23 @@ prepare_s(PyStructObject *self)
switch (c) {
case 's': /* fall through */
- case 'p': len++; ncodes++; break;
+ case 'p':
+ if (len == PY_SSIZE_T_MAX) {
+ goto overflow;
+ }
+ len++;
+ ncodes++;
+ break;
case 'x': break;
- default: len += num; if (num) ncodes++; break;
+ default:
+ if (num > PY_SSIZE_T_MAX - len) {
+ goto overflow;
+ }
+ len += num;
+ if (num) {
+ ncodes++;
+ }
+ break;
}
itemsize = e->size;
@@ -1490,18 +1511,12 @@ prepare_s(PyStructObject *self)
return -1;
}
- self->s_size = size;
- self->s_len = len;
codes = PyMem_Malloc((ncodes + 1) * sizeof(formatcode));
if (codes == NULL) {
PyErr_NoMemory();
return -1;
}
- /* Free any s_codes value left over from a previous initialization. */
- if (self->s_codes != NULL)
- PyMem_Free(self->s_codes);
- self->s_codes = codes;
-
+ codes0 = codes;
s = fmt;
size = 0;
while ((c = *s++) != '\0') {
@@ -1541,6 +1556,14 @@ prepare_s(PyStructObject *self)
codes->size = 0;
codes->repeat = 0;
+ /* Free any s_codes value left over from a previous initialization. */
+ if (self->s_codes != NULL)
+ PyMem_Free(self->s_codes);
+ self->s_codes = codes0;
+ self->s_size = size;
+ self->s_len = len;
+ Py_XSETREF(self->s_format, Py_NewRef(format));
+
return 0;
overflow:
@@ -1606,9 +1629,8 @@ Struct___init___impl(PyStructObject *self, PyObject *format)
return -1;
}
- Py_SETREF(self->s_format, format);
-
- ret = prepare_s(self);
+ ret = prepare_s(self, format);
+ Py_DECREF(format);
return ret;
}
@@ -1632,8 +1654,7 @@ s_dealloc(PyStructObject *s)
{
PyTypeObject *tp = Py_TYPE(s);
PyObject_GC_UnTrack(s);
- if (s->weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *)s);
+ FT_CLEAR_WEAKREFS((PyObject *)s, s->weakreflist);
if (s->s_codes != NULL) {
PyMem_Free(s->s_codes);
}
@@ -1688,6 +1709,14 @@ fail:
return NULL;
}
+#define ENSURE_STRUCT_IS_READY(self) \
+ do { \
+ if (!(self)->s_codes) { \
+ PyErr_SetString(PyExc_RuntimeError, \
+ "Struct object is not initialized"); \
+ return NULL; \
+ } \
+ } while (0);
/*[clinic input]
Struct.unpack
@@ -1708,7 +1737,7 @@ Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer)
/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/
{
_structmodulestate *state = get_struct_state_structinst(self);
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (buffer->len != self->s_size) {
PyErr_Format(state->StructError,
"unpack requires a buffer of %zd bytes",
@@ -1740,7 +1769,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer,
/*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/
{
_structmodulestate *state = get_struct_state_structinst(self);
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (offset < 0) {
if (offset + self->s_size > 0) {
@@ -1883,8 +1912,7 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer)
{
_structmodulestate *state = get_struct_state_structinst(self);
unpackiterobject *iter;
-
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (self->s_size == 0) {
PyErr_Format(state->StructError,
@@ -2025,8 +2053,8 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
/* Validate arguments. */
soself = (PyStructObject *)self;
+ ENSURE_STRUCT_IS_READY(soself);
assert(PyStruct_Check(self, state));
- assert(soself->s_codes != NULL);
if (nargs != soself->s_len)
{
PyErr_Format(state->StructError,
@@ -2070,8 +2098,8 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
/* Validate arguments. +1 is for the first arg as buffer. */
soself = (PyStructObject *)self;
+ ENSURE_STRUCT_IS_READY(soself);
assert(PyStruct_Check(self, state));
- assert(soself->s_codes != NULL);
if (nargs != (soself->s_len + 2))
{
if (nargs == 0) {
@@ -2157,6 +2185,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
static PyObject *
s_get_format(PyStructObject *self, void *unused)
{
+ ENSURE_STRUCT_IS_READY(self);
return PyUnicode_FromStringAndSize(PyBytes_AS_STRING(self->s_format),
PyBytes_GET_SIZE(self->s_format));
}
@@ -2173,6 +2202,7 @@ PyDoc_STRVAR(s_sizeof__doc__,
static PyObject *
s_sizeof(PyStructObject *self, void *unused)
{
+ ENSURE_STRUCT_IS_READY(self);
size_t size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode);
for (formatcode *code = self->s_codes; code->fmtdef != NULL; code++) {
size += sizeof(formatcode);
@@ -2180,6 +2210,20 @@ s_sizeof(PyStructObject *self, void *unused)
return PyLong_FromSize_t(size);
}
+static PyObject *
+s_repr(PyStructObject *self)
+{
+ ENSURE_STRUCT_IS_READY(self);
+ PyObject* fmt = PyUnicode_FromStringAndSize(
+ PyBytes_AS_STRING(self->s_format), PyBytes_GET_SIZE(self->s_format));
+ if (fmt == NULL) {
+ return NULL;
+ }
+ PyObject* s = PyUnicode_FromFormat("%s(%R)", _PyType_Name(Py_TYPE(self)), fmt);
+ Py_DECREF(fmt);
+ return s;
+}
+
/* List of functions */
static struct PyMethodDef s_methods[] = {
@@ -2193,13 +2237,13 @@ static struct PyMethodDef s_methods[] = {
};
static PyMemberDef s_members[] = {
- {"__weaklistoffset__", T_PYSSIZET, offsetof(PyStructObject, weakreflist), READONLY},
+ {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(PyStructObject, weakreflist), Py_READONLY},
{NULL} /* sentinel */
};
static PyGetSetDef s_getsetlist[] = {
- {"format", (getter)s_get_format, (setter)NULL, "struct format string", NULL},
- {"size", (getter)s_get_size, (setter)NULL, "struct size in bytes", NULL},
+ {"format", (getter)s_get_format, (setter)NULL, PyDoc_STR("struct format string"), NULL},
+ {"size", (getter)s_get_size, (setter)NULL, PyDoc_STR("struct size in bytes"), NULL},
{NULL} /* sentinel */
};
@@ -2212,6 +2256,7 @@ static PyType_Slot PyStructType_slots[] = {
{Py_tp_dealloc, s_dealloc},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_setattro, PyObject_GenericSetAttr},
+ {Py_tp_repr, s_repr},
{Py_tp_doc, (void*)s__doc__},
{Py_tp_traverse, s_traverse},
{Py_tp_clear, s_clear},
@@ -2250,20 +2295,13 @@ cache_struct_converter(PyObject *module, PyObject *fmt, PyStructObject **ptr)
return 1;
}
- if (state->cache == NULL) {
- state->cache = PyDict_New();
- if (state->cache == NULL)
- return 0;
+ if (PyDict_GetItemRef(state->cache, fmt, &s_object) < 0) {
+ return 0;
}
-
- s_object = PyDict_GetItemWithError(state->cache, fmt);
if (s_object != NULL) {
- *ptr = (PyStructObject *)Py_NewRef(s_object);
+ *ptr = (PyStructObject *)s_object;
return Py_CLEANUP_SUPPORTED;
}
- else if (PyErr_Occurred()) {
- return 0;
- }
s_object = PyObject_CallOneArg(state->PyStructType, fmt);
if (s_object != NULL) {
@@ -2288,7 +2326,7 @@ static PyObject *
_clearcache_impl(PyObject *module)
/*[clinic end generated code: output=ce4fb8a7bf7cb523 input=463eaae04bab3211]*/
{
- Py_CLEAR(get_struct_state(module)->cache);
+ PyDict_Clear(get_struct_state(module)->cache);
Py_RETURN_NONE;
}
@@ -2460,8 +2498,7 @@ The optional first format char indicates byte order, size and alignment:\n\
The remaining chars indicate types of args and must match exactly;\n\
these can be preceded by a decimal repeat count:\n\
x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
- ?: _Bool (requires C99; if not available, char is used instead)\n\
- h:short; H:unsigned short; i:int; I:unsigned int;\n\
+ ?:_Bool; h:short; H:unsigned short; i:int; I:unsigned int;\n\
l:long; L:unsigned long; f:float; d:double; e:half-float.\n\
Special cases (preceding decimal count indicates length):\n\
s:string (array of char); p: pascal string (with count byte).\n\
@@ -2512,6 +2549,11 @@ _structmodule_exec(PyObject *m)
{
_structmodulestate *state = get_struct_state(m);
+ state->cache = PyDict_New();
+ if (state->cache == NULL) {
+ return -1;
+ }
+
state->PyStructType = PyType_FromModuleAndSpec(
m, &PyStructType_spec, NULL);
if (state->PyStructType == NULL) {
@@ -2584,6 +2626,7 @@ _structmodule_exec(PyObject *m)
static PyModuleDef_Slot _structmodule_slots[] = {
{Py_mod_exec, _structmodule_exec},
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
+ {Py_mod_gil, Py_MOD_GIL_NOT_USED},
{0, NULL}
};