aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_ctypes/_ctypes.c179
-rw-r--r--Modules/_ctypes/callbacks.c9
-rw-r--r--Modules/_ctypes/callproc.c10
-rw-r--r--Modules/_ctypes/cfield.c2
-rw-r--r--Modules/_ctypes/clinic/_ctypes.c.h44
-rw-r--r--Modules/_ctypes/ctypes.h14
-rw-r--r--Modules/_cursesmodule.c1130
-rw-r--r--Modules/_datetimemodule.c18
-rw-r--r--Modules/_dbmmodule.c76
-rw-r--r--Modules/_elementtree.c41
-rw-r--r--Modules/_functoolsmodule.c16
-rw-r--r--Modules/_gdbmmodule.c85
-rw-r--r--Modules/_hacl/Hacl_Hash_Blake2b.c52
-rw-r--r--Modules/_hacl/Hacl_Hash_Blake2b_Simd256.c52
-rw-r--r--Modules/_hacl/Hacl_Hash_Blake2s.c52
-rw-r--r--Modules/_hacl/Hacl_Hash_Blake2s_Simd128.c52
-rw-r--r--Modules/_hacl/Hacl_Hash_MD5.c523
-rw-r--r--Modules/_hacl/Hacl_Hash_SHA1.c12
-rw-r--r--Modules/_hacl/Hacl_Hash_SHA2.c42
-rw-r--r--Modules/_hacl/Hacl_Hash_SHA3.c22
-rw-r--r--Modules/_hacl/Hacl_Streaming_HMAC.c127
-rw-r--r--Modules/_hacl/Lib_Memzero0.c20
-rw-r--r--Modules/_hacl/include/krml/FStar_UInt128_Verified.h45
-rwxr-xr-xModules/_hacl/refresh.sh2
-rw-r--r--Modules/_hashopenssl.c468
-rw-r--r--Modules/_interpchannelsmodule.c190
-rw-r--r--Modules/_interpqueuesmodule.c185
-rw-r--r--Modules/_interpreters_common.h58
-rw-r--r--Modules/_interpretersmodule.c698
-rw-r--r--Modules/_io/bytesio.c2
-rw-r--r--Modules/_json.c30
-rw-r--r--Modules/_localemodule.c12
-rw-r--r--Modules/_lsprof.c6
-rw-r--r--Modules/_pickle.c6
-rw-r--r--Modules/_randommodule.c20
-rw-r--r--Modules/_remote_debugging_module.c3110
-rw-r--r--Modules/_ssl.c2
-rw-r--r--Modules/_testcapi/unicode.c22
-rw-r--r--Modules/_testcapimodule.c49
-rw-r--r--Modules/_testinternalcapi.c46
-rw-r--r--Modules/_testlimitedcapi/sys.c73
-rw-r--r--Modules/_threadmodule.c109
-rw-r--r--Modules/_tkinter.c5
-rw-r--r--Modules/_uuidmodule.c40
-rw-r--r--Modules/_winapi.c28
-rw-r--r--Modules/_zstd/_zstdmodule.c389
-rw-r--r--Modules/_zstd/_zstdmodule.h143
-rw-r--r--Modules/_zstd/buffer.h22
-rw-r--r--Modules/_zstd/clinic/_zstdmodule.c.h129
-rw-r--r--Modules/_zstd/clinic/compressor.c.h28
-rw-r--r--Modules/_zstd/clinic/decompressor.c.h31
-rw-r--r--Modules/_zstd/clinic/zstddict.c.h122
-rw-r--r--Modules/_zstd/compressor.c553
-rw-r--r--Modules/_zstd/decompressor.c567
-rw-r--r--Modules/_zstd/zstddict.c244
-rw-r--r--Modules/_zstd/zstddict.h29
-rw-r--r--Modules/blake2module.c30
-rw-r--r--Modules/clinic/_cursesmodule.c.h34
-rw-r--r--Modules/clinic/_dbmmodule.c.h37
-rw-r--r--Modules/clinic/_gdbmmodule.c.h70
-rw-r--r--Modules/clinic/_hashopenssl.c.h549
-rw-r--r--Modules/clinic/_randommodule.c.h10
-rw-r--r--Modules/clinic/_remote_debugging_module.c.h256
-rw-r--r--Modules/clinic/_threadmodule.c.h50
-rw-r--r--Modules/clinic/_winapi.c.h28
-rw-r--r--Modules/clinic/blake2module.c.h98
-rw-r--r--Modules/clinic/mathmodule.c.h6
-rw-r--r--Modules/clinic/md5module.c.h34
-rw-r--r--Modules/clinic/sha1module.c.h34
-rw-r--r--Modules/clinic/sha2module.c.h130
-rw-r--r--Modules/clinic/sha3module.c.h128
-rw-r--r--Modules/clinic/zlibmodule.c.h120
-rw-r--r--Modules/faulthandler.c34
-rw-r--r--Modules/fcntlmodule.c126
-rw-r--r--Modules/hashlib.h29
-rw-r--r--Modules/main.c35
-rw-r--r--Modules/mathmodule.c25
-rw-r--r--Modules/md5module.c13
-rw-r--r--Modules/mmapmodule.c26
-rw-r--r--Modules/posixmodule.c12
-rw-r--r--Modules/pwdmodule.c25
-rw-r--r--Modules/sha1module.c12
-rw-r--r--Modules/sha2module.c49
-rw-r--r--Modules/sha3module.c21
-rw-r--r--Modules/socketmodule.h2
-rw-r--r--Modules/syslogmodule.c3
-rw-r--r--Modules/timemodule.c2
-rw-r--r--Modules/zlibmodule.c88
88 files changed, 7440 insertions, 4717 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 1bb65e0a649..7e8a133caa7 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -576,8 +576,15 @@ _ctypes_CType_Type___sizeof___impl(PyObject *self, PyTypeObject *cls)
return PyLong_FromSsize_t(size);
}
+/*[clinic input]
+@getter
+_ctypes.CType_Type.__pointer_type__
+
+[clinic start generated code]*/
+
static PyObject *
-ctype_get_pointer_type(PyObject *self, void *Py_UNUSED(ignored))
+_ctypes_CType_Type___pointer_type___get_impl(PyObject *self)
+/*[clinic end generated code: output=718c9ff10b2b0012 input=ad12dc835943ceb8]*/
{
ctypes_state *st = get_module_state_by_def(Py_TYPE(self));
StgInfo *info;
@@ -588,9 +595,12 @@ ctype_get_pointer_type(PyObject *self, void *Py_UNUSED(ignored))
PyErr_Format(PyExc_TypeError, "%R must have storage info", self);
return NULL;
}
-
- if (info->pointer_type) {
- return Py_NewRef(info->pointer_type);
+ PyObject *pointer_type;
+ STGINFO_LOCK(info);
+ pointer_type = Py_XNewRef(info->pointer_type);
+ STGINFO_UNLOCK();
+ if (pointer_type) {
+ return pointer_type;
}
PyErr_Format(PyExc_AttributeError,
@@ -599,8 +609,15 @@ ctype_get_pointer_type(PyObject *self, void *Py_UNUSED(ignored))
return NULL;
}
+/*[clinic input]
+@setter
+_ctypes.CType_Type.__pointer_type__
+
+[clinic start generated code]*/
+
static int
-ctype_set_pointer_type(PyObject *self, PyObject *tp, void *Py_UNUSED(ignored))
+_ctypes_CType_Type___pointer_type___set_impl(PyObject *self, PyObject *value)
+/*[clinic end generated code: output=6259be8ea21693fa input=a05055fc7f4714b6]*/
{
ctypes_state *st = get_module_state_by_def(Py_TYPE(self));
StgInfo *info;
@@ -611,8 +628,9 @@ ctype_set_pointer_type(PyObject *self, PyObject *tp, void *Py_UNUSED(ignored))
PyErr_Format(PyExc_TypeError, "%R must have storage info", self);
return -1;
}
-
- Py_XSETREF(info->pointer_type, Py_XNewRef(tp));
+ STGINFO_LOCK(info);
+ Py_XSETREF(info->pointer_type, Py_XNewRef(value));
+ STGINFO_UNLOCK();
return 0;
}
@@ -626,8 +644,7 @@ static PyMethodDef ctype_methods[] = {
};
static PyGetSetDef ctype_getsets[] = {
- { "__pointer_type__", ctype_get_pointer_type, ctype_set_pointer_type,
- "pointer type", NULL },
+ _CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF
{ NULL, NULL }
};
@@ -1254,9 +1271,11 @@ PyCPointerType_SetProto(ctypes_state *st, PyObject *self, StgInfo *stginfo, PyOb
return -1;
}
Py_XSETREF(stginfo->proto, Py_NewRef(proto));
+ STGINFO_LOCK(info);
if (info->pointer_type == NULL) {
Py_XSETREF(info->pointer_type, Py_NewRef(self));
}
+ STGINFO_UNLOCK();
return 0;
}
@@ -3591,6 +3610,45 @@ generic_pycdata_new(ctypes_state *st,
PyCFuncPtr_Type
*/
+static inline void
+atomic_xsetref(PyObject **field, PyObject *value)
+{
+#ifdef Py_GIL_DISABLED
+ PyObject *old = *field;
+ _Py_atomic_store_ptr(field, value);
+ Py_XDECREF(old);
+#else
+ Py_XSETREF(*field, value);
+#endif
+}
+/*
+ This function atomically loads the reference from *field, and
+ tries to get a new reference to it. If the incref fails,
+ it acquires critical section of obj and returns a new reference to the *field.
+ In the general case, this avoids contention on acquiring the critical section.
+*/
+static inline PyObject *
+atomic_xgetref(PyObject *obj, PyObject **field)
+{
+#ifdef Py_GIL_DISABLED
+ PyObject *value = _Py_atomic_load_ptr(field);
+ if (value == NULL) {
+ return NULL;
+ }
+ if (_Py_TryIncrefCompare(field, value)) {
+ return value;
+ }
+ Py_BEGIN_CRITICAL_SECTION(obj);
+ value = Py_XNewRef(*field);
+ Py_END_CRITICAL_SECTION();
+ return value;
+#else
+ return Py_XNewRef(*field);
+#endif
+}
+
+
+
/*[clinic input]
@critical_section
@setter
@@ -3607,7 +3665,7 @@ _ctypes_CFuncPtr_errcheck_set_impl(PyCFuncPtrObject *self, PyObject *value)
return -1;
}
Py_XINCREF(value);
- Py_XSETREF(self->errcheck, value);
+ atomic_xsetref(&self->errcheck, value);
return 0;
}
@@ -3639,12 +3697,10 @@ static int
_ctypes_CFuncPtr_restype_set_impl(PyCFuncPtrObject *self, PyObject *value)
/*[clinic end generated code: output=0be0a086abbabf18 input=683c3bef4562ccc6]*/
{
- PyObject *checker, *oldchecker;
+ PyObject *checker;
if (value == NULL) {
- oldchecker = self->checker;
- self->checker = NULL;
- Py_CLEAR(self->restype);
- Py_XDECREF(oldchecker);
+ atomic_xsetref(&self->restype, NULL);
+ atomic_xsetref(&self->checker, NULL);
return 0;
}
ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self)));
@@ -3660,11 +3716,9 @@ _ctypes_CFuncPtr_restype_set_impl(PyCFuncPtrObject *self, PyObject *value)
if (PyObject_GetOptionalAttr(value, &_Py_ID(_check_retval_), &checker) < 0) {
return -1;
}
- oldchecker = self->checker;
- self->checker = checker;
Py_INCREF(value);
- Py_XSETREF(self->restype, value);
- Py_XDECREF(oldchecker);
+ atomic_xsetref(&self->checker, checker);
+ atomic_xsetref(&self->restype, value);
return 0;
}
@@ -3709,16 +3763,16 @@ _ctypes_CFuncPtr_argtypes_set_impl(PyCFuncPtrObject *self, PyObject *value)
PyObject *converters;
if (value == NULL || value == Py_None) {
- Py_CLEAR(self->converters);
- Py_CLEAR(self->argtypes);
+ atomic_xsetref(&self->argtypes, NULL);
+ atomic_xsetref(&self->converters, NULL);
} else {
ctypes_state *st = get_module_state_by_def(Py_TYPE(Py_TYPE(self)));
converters = converters_from_argtypes(st, value);
if (!converters)
return -1;
- Py_XSETREF(self->converters, converters);
+ atomic_xsetref(&self->converters, converters);
Py_INCREF(value);
- Py_XSETREF(self->argtypes, value);
+ atomic_xsetref(&self->argtypes, value);
}
return 0;
}
@@ -4514,16 +4568,11 @@ _build_result(PyObject *result, PyObject *callargs,
}
static PyObject *
-PyCFuncPtr_call_lock_held(PyObject *op, PyObject *inargs, PyObject *kwds)
+PyCFuncPtr_call(PyObject *op, PyObject *inargs, PyObject *kwds)
{
- _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op);
- PyObject *restype;
- PyObject *converters;
- PyObject *checker;
- PyObject *argtypes;
- PyObject *result;
- PyObject *callargs;
- PyObject *errcheck;
+ PyObject *result = NULL;
+ PyObject *callargs = NULL;
+ PyObject *ret = NULL;
#ifdef MS_WIN32
IUnknown *piunk = NULL;
#endif
@@ -4541,13 +4590,24 @@ PyCFuncPtr_call_lock_held(PyObject *op, PyObject *inargs, PyObject *kwds)
}
assert(info); /* Cannot be NULL for PyCFuncPtrObject instances */
- restype = self->restype ? self->restype : info->restype;
- converters = self->converters ? self->converters : info->converters;
- checker = self->checker ? self->checker : info->checker;
- argtypes = self->argtypes ? self->argtypes : info->argtypes;
-/* later, we probably want to have an errcheck field in stginfo */
- errcheck = self->errcheck /* ? self->errcheck : info->errcheck */;
-
+ PyObject *restype = atomic_xgetref(op, &self->restype);
+ if (restype == NULL) {
+ restype = Py_XNewRef(info->restype);
+ }
+ PyObject *converters = atomic_xgetref(op, &self->converters);
+ if (converters == NULL) {
+ converters = Py_XNewRef(info->converters);
+ }
+ PyObject *checker = atomic_xgetref(op, &self->checker);
+ if (checker == NULL) {
+ checker = Py_XNewRef(info->checker);
+ }
+ PyObject *argtypes = atomic_xgetref(op, &self->argtypes);
+ if (argtypes == NULL) {
+ argtypes = Py_XNewRef(info->argtypes);
+ }
+ /* later, we probably want to have an errcheck field in stginfo */
+ PyObject *errcheck = atomic_xgetref(op, &self->errcheck);
pProc = *(void **)self->b_ptr;
#ifdef MS_WIN32
@@ -4558,25 +4618,25 @@ PyCFuncPtr_call_lock_held(PyObject *op, PyObject *inargs, PyObject *kwds)
if (!this) {
PyErr_SetString(PyExc_ValueError,
"native com method call without 'this' parameter");
- return NULL;
+ goto finally;
}
if (!CDataObject_Check(st, this)) {
PyErr_SetString(PyExc_TypeError,
"Expected a COM this pointer as first argument");
- return NULL;
+ goto finally;
}
/* there should be more checks? No, in Python */
/* First arg is a pointer to an interface instance */
if (!this->b_ptr || *(void **)this->b_ptr == NULL) {
PyErr_SetString(PyExc_ValueError,
"NULL COM pointer access");
- return NULL;
+ goto finally;
}
piunk = *(IUnknown **)this->b_ptr;
if (NULL == piunk->lpVtbl) {
PyErr_SetString(PyExc_ValueError,
"COM method call without VTable");
- return NULL;
+ goto finally;
}
pProc = ((void **)piunk->lpVtbl)[self->index - 0x1000];
}
@@ -4584,8 +4644,9 @@ PyCFuncPtr_call_lock_held(PyObject *op, PyObject *inargs, PyObject *kwds)
callargs = _build_callargs(st, self, argtypes,
inargs, kwds,
&outmask, &inoutmask, &numretvals);
- if (callargs == NULL)
- return NULL;
+ if (callargs == NULL) {
+ goto finally;
+ }
if (converters) {
int required = Py_SAFE_DOWNCAST(PyTuple_GET_SIZE(converters),
@@ -4604,7 +4665,7 @@ PyCFuncPtr_call_lock_held(PyObject *op, PyObject *inargs, PyObject *kwds)
required,
required == 1 ? "" : "s",
actual);
- return NULL;
+ goto finally;
}
} else if (required != actual) {
Py_DECREF(callargs);
@@ -4613,7 +4674,7 @@ PyCFuncPtr_call_lock_held(PyObject *op, PyObject *inargs, PyObject *kwds)
required,
required == 1 ? "" : "s",
actual);
- return NULL;
+ goto finally;
}
}
@@ -4644,23 +4705,19 @@ PyCFuncPtr_call_lock_held(PyObject *op, PyObject *inargs, PyObject *kwds)
if (v == NULL || v != callargs) {
Py_DECREF(result);
Py_DECREF(callargs);
- return v;
+ ret = v;
+ goto finally;
}
Py_DECREF(v);
}
-
- return _build_result(result, callargs,
- outmask, inoutmask, numretvals);
-}
-
-static PyObject *
-PyCFuncPtr_call(PyObject *op, PyObject *inargs, PyObject *kwds)
-{
- PyObject *result;
- Py_BEGIN_CRITICAL_SECTION(op);
- result = PyCFuncPtr_call_lock_held(op, inargs, kwds);
- Py_END_CRITICAL_SECTION();
- return result;
+ ret = _build_result(result, callargs, outmask, inoutmask, numretvals);
+finally:
+ Py_XDECREF(restype);
+ Py_XDECREF(converters);
+ Py_XDECREF(checker);
+ Py_XDECREF(argtypes);
+ Py_XDECREF(errcheck);
+ return ret;
}
static int
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index ec113e41d16..fd508ae61f2 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -11,18 +11,9 @@
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_runtime.h" // _Py_ID()
-#ifdef MS_WIN32
-# include <malloc.h>
-#endif
-
#include <ffi.h>
#include "ctypes.h"
-#ifdef HAVE_ALLOCA_H
-/* AIX needs alloca.h for alloca() */
-#include <alloca.h>
-#endif
-
/**************************************************************/
static int
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index 404178ca623..65a0f14e2b0 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -77,16 +77,8 @@ module _ctypes
#include <mach-o/dyld.h>
#endif
-#ifdef MS_WIN32
-#include <malloc.h>
-#endif
-
#include <ffi.h>
#include "ctypes.h"
-#ifdef HAVE_ALLOCA_H
-/* AIX needs alloca.h for alloca() */
-#include <alloca.h>
-#endif
#ifdef _Py_MEMORY_SANITIZER
#include <sanitizer/msan_interface.h>
@@ -1389,7 +1381,7 @@ static PyObject *format_error(PyObject *self, PyObject *args)
code = GetLastError();
lpMsgBuf = FormatError(code);
if (lpMsgBuf) {
- result = PyUnicode_FromWideChar(lpMsgBuf, wcslen(lpMsgBuf));
+ result = PyUnicode_FromWideChar(lpMsgBuf, -1);
LocalFree(lpMsgBuf);
} else {
result = PyUnicode_FromString("<no description>");
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c
index 86bcc805360..163b9264261 100644
--- a/Modules/_ctypes/cfield.c
+++ b/Modules/_ctypes/cfield.c
@@ -1253,7 +1253,7 @@ Z_get(void *ptr, Py_ssize_t size)
wchar_t *p;
p = *(wchar_t **)ptr;
if (p) {
- return PyUnicode_FromWideChar(p, wcslen(p));
+ return PyUnicode_FromWideChar(p, -1);
} else {
Py_RETURN_NONE;
}
diff --git a/Modules/_ctypes/clinic/_ctypes.c.h b/Modules/_ctypes/clinic/_ctypes.c.h
index 92dfb8f83b7..cf2e3fa2107 100644
--- a/Modules/_ctypes/clinic/_ctypes.c.h
+++ b/Modules/_ctypes/clinic/_ctypes.c.h
@@ -31,6 +31,48 @@ _ctypes_CType_Type___sizeof__(PyObject *self, PyTypeObject *cls, PyObject *const
return _ctypes_CType_Type___sizeof___impl(self, cls);
}
+#if !defined(_ctypes_CType_Type___pointer_type___DOCSTR)
+# define _ctypes_CType_Type___pointer_type___DOCSTR NULL
+#endif
+#if defined(_CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF)
+# undef _CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF
+# define _CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF {"__pointer_type__", (getter)_ctypes_CType_Type___pointer_type___get, (setter)_ctypes_CType_Type___pointer_type___set, _ctypes_CType_Type___pointer_type___DOCSTR},
+#else
+# define _CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF {"__pointer_type__", (getter)_ctypes_CType_Type___pointer_type___get, NULL, _ctypes_CType_Type___pointer_type___DOCSTR},
+#endif
+
+static PyObject *
+_ctypes_CType_Type___pointer_type___get_impl(PyObject *self);
+
+static PyObject *
+_ctypes_CType_Type___pointer_type___get(PyObject *self, void *Py_UNUSED(context))
+{
+ return _ctypes_CType_Type___pointer_type___get_impl(self);
+}
+
+#if !defined(_ctypes_CType_Type___pointer_type___DOCSTR)
+# define _ctypes_CType_Type___pointer_type___DOCSTR NULL
+#endif
+#if defined(_CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF)
+# undef _CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF
+# define _CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF {"__pointer_type__", (getter)_ctypes_CType_Type___pointer_type___get, (setter)_ctypes_CType_Type___pointer_type___set, _ctypes_CType_Type___pointer_type___DOCSTR},
+#else
+# define _CTYPES_CTYPE_TYPE___POINTER_TYPE___GETSETDEF {"__pointer_type__", NULL, (setter)_ctypes_CType_Type___pointer_type___set, NULL},
+#endif
+
+static int
+_ctypes_CType_Type___pointer_type___set_impl(PyObject *self, PyObject *value);
+
+static int
+_ctypes_CType_Type___pointer_type___set(PyObject *self, PyObject *value, void *Py_UNUSED(context))
+{
+ int return_value;
+
+ return_value = _ctypes_CType_Type___pointer_type___set_impl(self, value);
+
+ return return_value;
+}
+
PyDoc_STRVAR(CDataType_from_address__doc__,
"from_address($self, value, /)\n"
"--\n"
@@ -1000,4 +1042,4 @@ Simple_from_outparm(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py
}
return Simple_from_outparm_impl(self, cls);
}
-/*[clinic end generated code: output=9fb75bf7e9a17df2 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=536c9bcf4e05913e input=a9049054013a1b77]*/
diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h
index 2d859ed63e1..6a45c11e61a 100644
--- a/Modules/_ctypes/ctypes.h
+++ b/Modules/_ctypes/ctypes.h
@@ -1,5 +1,17 @@
-#if defined (__SVR4) && defined (__sun)
+/* Get a definition of alloca(). */
+#if (defined (__SVR4) && defined (__sun)) || defined(HAVE_ALLOCA_H)
# include <alloca.h>
+#elif defined(MS_WIN32)
+# include <malloc.h>
+#endif
+
+/* If the system does not define alloca(), we have to hope for a compiler builtin. */
+#ifndef alloca
+# if defined __GNUC__ || (__clang_major__ >= 4)
+# define alloca __builtin_alloca
+# else
+# error "Could not define alloca() on your platform."
+# endif
#endif
#include <stdbool.h>
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index cd185bc2b02..d7788ef7a58 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -108,7 +108,6 @@ static const char PyCursesVersion[] = "2.2";
#include "pycore_capsule.h" // _PyCapsule_SetTraverse()
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_structseq.h" // _PyStructSequence_NewType()
-#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
#include "pycore_fileutils.h" // _Py_set_inheritable
#ifdef __hpux
@@ -211,18 +210,116 @@ static int curses_start_color_called = FALSE;
static const char *curses_screen_encoding = NULL;
+/* Utility Error Procedures */
+
+static void
+_curses_format_error(cursesmodule_state *state,
+ const char *curses_funcname,
+ const char *python_funcname,
+ const char *return_value,
+ const char *default_message)
+{
+ assert(!PyErr_Occurred());
+ if (python_funcname == NULL && curses_funcname == NULL) {
+ PyErr_SetString(state->error, default_message);
+ }
+ else if (python_funcname == NULL) {
+ (void)PyErr_Format(state->error, CURSES_ERROR_FORMAT,
+ curses_funcname, return_value);
+ }
+ else {
+ assert(python_funcname != NULL);
+ (void)PyErr_Format(state->error, CURSES_ERROR_VERBOSE_FORMAT,
+ curses_funcname, python_funcname, return_value);
+ }
+}
+
+/*
+ * Format a curses error for a function that returned ERR.
+ *
+ * Specify a non-NULL 'python_funcname' when the latter differs from
+ * 'curses_funcname'. If both names are NULL, uses the 'catchall_ERR'
+ * message instead.
+ */
+static void
+_curses_set_error(cursesmodule_state *state,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ _curses_format_error(state, curses_funcname, python_funcname,
+ "ERR", catchall_ERR);
+}
+
+/*
+ * Format a curses error for a function that returned NULL.
+ *
+ * Specify a non-NULL 'python_funcname' when the latter differs from
+ * 'curses_funcname'. If both names are NULL, uses the 'catchall_NULL'
+ * message instead.
+ */
+static inline void
+_curses_set_null_error(cursesmodule_state *state,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ _curses_format_error(state, curses_funcname, python_funcname,
+ "NULL", catchall_NULL);
+}
+
+/* Same as _curses_set_error() for a module object. */
+static void
+curses_set_error(PyObject *module,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ cursesmodule_state *state = get_cursesmodule_state(module);
+ _curses_set_error(state, curses_funcname, python_funcname);
+}
+
+/* Same as _curses_set_null_error() for a module object. */
+static void
+curses_set_null_error(PyObject *module,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ cursesmodule_state *state = get_cursesmodule_state(module);
+ _curses_set_null_error(state, curses_funcname, python_funcname);
+}
+
+/* Same as _curses_set_error() for a Window object. */
+static void
+curses_window_set_error(PyCursesWindowObject *win,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ cursesmodule_state *state = get_cursesmodule_state_by_win(win);
+ _curses_set_error(state, curses_funcname, python_funcname);
+}
+
+/* Same as _curses_set_null_error() for a Window object. */
+static void
+curses_window_set_null_error(PyCursesWindowObject *win,
+ const char *curses_funcname,
+ const char *python_funcname)
+{
+ cursesmodule_state *state = get_cursesmodule_state_by_win(win);
+ _curses_set_null_error(state, curses_funcname, python_funcname);
+}
+
/* Utility Checking Procedures */
/*
* Function to check that 'funcname' has been called by testing
- * the 'called' boolean. If an error occurs, a PyCursesError is
+ * the 'called' boolean. If an error occurs, an exception is
* set and this returns 0. Otherwise, this returns 1.
*
* Since this function can be called in functions that do not
* have a direct access to the module's state, '_curses.error'
* is imported on demand.
+ *
+ * Use _PyCursesStatefulCheckFunction() if the module is given.
*/
-static inline int
+static int
_PyCursesCheckFunction(int called, const char *funcname)
{
if (called == TRUE) {
@@ -230,7 +327,7 @@ _PyCursesCheckFunction(int called, const char *funcname)
}
PyObject *exc = PyImport_ImportModuleAttrString("_curses", "error");
if (exc != NULL) {
- PyErr_Format(exc, "must call %s() first", funcname);
+ PyErr_Format(exc, CURSES_ERROR_MUST_CALL_FORMAT, funcname);
Py_DECREF(exc);
}
assert(PyErr_Occurred());
@@ -244,14 +341,15 @@ _PyCursesCheckFunction(int called, const char *funcname)
*
* The exception type is obtained from the 'module' state.
*/
-static inline int
-_PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcname)
+static int
+_PyCursesStatefulCheckFunction(PyObject *module,
+ int called, const char *funcname)
{
if (called == TRUE) {
return 1;
}
cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_Format(state->error, "must call %s() first", funcname);
+ PyErr_Format(state->error, CURSES_ERROR_MUST_CALL_FORMAT, funcname);
return 0;
}
@@ -287,44 +385,39 @@ _PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcnam
/* Utility Functions */
-static inline void
-_PyCursesSetError(cursesmodule_state *state, const char *funcname)
-{
- if (funcname == NULL) {
- PyErr_SetString(state->error, catchall_ERR);
- }
- else {
- PyErr_Format(state->error, "%s() returned ERR", funcname);
- }
-}
-
/*
- * Check the return code from a curses function and return None
- * or raise an exception as appropriate.
+ * Check the return code from a curses function, returning None
+ * on success and setting an exception on error.
*/
+/*
+ * Return None if 'code' is different from ERR (implementation-defined).
+ * Otherwise, set an exception using curses_set_error() and the remaining
+ * arguments, and return NULL.
+ */
static PyObject *
-PyCursesCheckERR(PyObject *module, int code, const char *fname)
+curses_check_err(PyObject *module, int code,
+ const char *curses_funcname,
+ const char *python_funcname)
{
if (code != ERR) {
Py_RETURN_NONE;
- } else {
- cursesmodule_state *state = get_cursesmodule_state(module);
- _PyCursesSetError(state, fname);
- return NULL;
}
+ curses_set_error(module, curses_funcname, python_funcname);
+ return NULL;
}
+/* Same as curses_check_err() for a Window object. */
static PyObject *
-PyCursesCheckERR_ForWin(PyCursesWindowObject *win, int code, const char *fname)
+curses_window_check_err(PyCursesWindowObject *win, int code,
+ const char *curses_funcname,
+ const char *python_funcname)
{
if (code != ERR) {
Py_RETURN_NONE;
- } else {
- cursesmodule_state *state = get_cursesmodule_state_by_win(win);
- _PyCursesSetError(state, fname);
- return NULL;
}
+ curses_window_set_error(win, curses_funcname, python_funcname);
+ return NULL;
}
/* Convert an object to a byte (an integer of type chtype):
@@ -650,13 +743,16 @@ class component_converter(CConverter):
The Window Object
******************************************************************************/
-/* Function prototype macros for Window object
-
- X - function name
- TYPE - parameter Type
- ERGSTR - format string for construction of the return value
- PARSESTR - format string for argument parsing
-*/
+/*
+ * Macros for creating a PyCursesWindowObject object's method.
+ *
+ * Parameters
+ *
+ * X The name of the curses C function or macro to invoke.
+ * TYPE The function parameter(s) type.
+ * ERGSTR The format string for construction of the return value.
+ * PARSESTR The format string for argument parsing.
+ */
#define Window_NoArgNoReturnFunction(X) \
static PyObject *PyCursesWindow_ ## X \
@@ -664,7 +760,7 @@ class component_converter(CConverter):
{ \
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
int code = X(self->win); \
- return PyCursesCheckERR_ForWin(self, code, # X); \
+ return curses_window_check_err(self, code, # X, NULL); \
}
#define Window_NoArgTrueFalseFunction(X) \
@@ -717,7 +813,7 @@ class component_converter(CConverter):
} \
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
int code = X(self->win, arg1); \
- return PyCursesCheckERR_ForWin(self, code, # X); \
+ return curses_window_check_err(self, code, # X, NULL); \
}
#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \
@@ -730,7 +826,7 @@ class component_converter(CConverter):
} \
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); \
int code = X(self->win, arg1, arg2); \
- return PyCursesCheckERR_ForWin(self, code, # X); \
+ return curses_window_check_err(self, code, # X, NULL); \
}
/* ------------- WINDOW routines --------------- */
@@ -835,8 +931,10 @@ PyCursesWindow_dealloc(PyObject *self)
PyObject_GC_UnTrack(self);
PyCursesWindowObject *wo = (PyCursesWindowObject *)self;
if (wo->win != stdscr && wo->win != NULL) {
- // silently ignore errors in delwin(3)
- (void)delwin(wo->win);
+ if (delwin(wo->win) == ERR) {
+ curses_window_set_error(wo, "delwin", "__del__");
+ PyErr_FormatUnraisable("Exception ignored in delwin()");
+ }
}
if (wo->encoding != NULL) {
PyMem_Free(wo->encoding);
@@ -903,13 +1001,19 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1,
#ifdef HAVE_NCURSESW
type = PyCurses_ConvertToCchar_t(self, ch, &cch, wstr);
if (type == 2) {
- funcname = "add_wch";
wstr[1] = L'\0';
- setcchar(&wcval, wstr, attr, PAIR_NUMBER(attr), NULL);
- if (coordinates_group)
+ rtn = setcchar(&wcval, wstr, attr, PAIR_NUMBER(attr), NULL);
+ if (rtn == ERR) {
+ curses_window_set_error(self, "setcchar", "addch");
+ return NULL;
+ }
+ if (coordinates_group) {
rtn = mvwadd_wch(self->win,y,x, &wcval);
+ funcname = "mvwadd_wch";
+ }
else {
rtn = wadd_wch(self->win, &wcval);
+ funcname = "wadd_wch";
}
}
else
@@ -917,17 +1021,40 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1,
type = PyCurses_ConvertToCchar_t(self, ch, &cch);
#endif
if (type == 1) {
- funcname = "addch";
- if (coordinates_group)
+ if (coordinates_group) {
rtn = mvwaddch(self->win,y,x, cch | (attr_t) attr);
+ funcname = "mvwaddch";
+ }
else {
rtn = waddch(self->win, cch | (attr_t) attr);
+ funcname = "waddch";
}
}
else {
return NULL;
}
- return PyCursesCheckERR_ForWin(self, rtn, funcname);
+ return curses_window_check_err(self, rtn, funcname, "addch");
+}
+
+#ifdef HAVE_NCURSESW
+#define curses_release_wstr(STRTYPE, WSTR) \
+ do { \
+ if ((STRTYPE) == 2) { \
+ PyMem_Free((WSTR)); \
+ } \
+ } while (0)
+#else
+#define curses_release_wstr(_STRTYPE, _WSTR)
+#endif
+
+static int
+curses_wattrset(PyCursesWindowObject *self, long attr, const char *funcname)
+{
+ if (wattrset(self->win, attr) == ERR) {
+ curses_window_set_error(self, "wattrset", funcname);
+ return -1;
+ }
+ return 0;
}
/*[clinic input]
@@ -983,31 +1110,46 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1,
}
if (use_attr) {
attr_old = getattrs(self->win);
- (void)wattrset(self->win,attr);
+ if (curses_wattrset(self, attr, "addstr") < 0) {
+ curses_release_wstr(strtype, wstr);
+ return NULL;
+ }
}
#ifdef HAVE_NCURSESW
if (strtype == 2) {
- funcname = "addwstr";
- if (use_xy)
+ if (use_xy) {
rtn = mvwaddwstr(self->win,y,x,wstr);
- else
+ funcname = "mvwaddwstr";
+ }
+ else {
rtn = waddwstr(self->win,wstr);
+ funcname = "waddwstr";
+ }
PyMem_Free(wstr);
}
else
#endif
{
const char *str = PyBytes_AS_STRING(bytesobj);
- funcname = "addstr";
- if (use_xy)
+ if (use_xy) {
rtn = mvwaddstr(self->win,y,x,str);
- else
+ funcname = "mvwaddstr";
+ }
+ else {
rtn = waddstr(self->win,str);
+ funcname = "waddstr";
+ }
Py_DECREF(bytesobj);
}
- if (use_attr)
- (void)wattrset(self->win,attr_old);
- return PyCursesCheckERR_ForWin(self, rtn, funcname);
+ if (rtn == ERR) {
+ curses_window_set_error(self, funcname, "addstr");
+ return NULL;
+ }
+ if (use_attr) {
+ rtn = wattrset(self->win, attr_old);
+ return curses_window_check_err(self, rtn, "wattrset", "addstr");
+ }
+ Py_RETURN_NONE;
}
/*[clinic input]
@@ -1066,31 +1208,46 @@ _curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1,
if (use_attr) {
attr_old = getattrs(self->win);
- (void)wattrset(self->win,attr);
+ if (curses_wattrset(self, attr, "addnstr") < 0) {
+ curses_release_wstr(strtype, wstr);
+ return NULL;
+ }
}
#ifdef HAVE_NCURSESW
if (strtype == 2) {
- funcname = "addnwstr";
- if (use_xy)
+ if (use_xy) {
rtn = mvwaddnwstr(self->win,y,x,wstr,n);
- else
+ funcname = "mvwaddnwstr";
+ }
+ else {
rtn = waddnwstr(self->win,wstr,n);
+ funcname = "waddnwstr";
+ }
PyMem_Free(wstr);
}
else
#endif
{
const char *str = PyBytes_AS_STRING(bytesobj);
- funcname = "addnstr";
- if (use_xy)
+ if (use_xy) {
rtn = mvwaddnstr(self->win,y,x,str,n);
- else
+ funcname = "mvwaddnstr";
+ }
+ else {
rtn = waddnstr(self->win,str,n);
+ funcname = "waddnstr";
+ }
Py_DECREF(bytesobj);
}
- if (use_attr)
- (void)wattrset(self->win,attr_old);
- return PyCursesCheckERR_ForWin(self, rtn, funcname);
+ if (rtn == ERR) {
+ curses_window_set_error(self, funcname, "addnstr");
+ return NULL;
+ }
+ if (use_attr) {
+ rtn = wattrset(self->win, attr_old);
+ return curses_window_check_err(self, rtn, "wattrset", "addnstr");
+ }
+ Py_RETURN_NONE;
}
/*[clinic input]
@@ -1114,7 +1271,8 @@ _curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr)
if (!PyCurses_ConvertToChtype(self, ch, &bkgd))
return NULL;
- return PyCursesCheckERR_ForWin(self, wbkgd(self->win, bkgd | attr), "bkgd");
+ int rtn = wbkgd(self->win, bkgd | attr);
+ return curses_window_check_err(self, rtn, "wbkgd", "bkgd");
}
/*[clinic input]
@@ -1130,7 +1288,8 @@ static PyObject *
_curses_window_attroff_impl(PyCursesWindowObject *self, long attr)
/*[clinic end generated code: output=8a2fcd4df682fc64 input=786beedf06a7befe]*/
{
- return PyCursesCheckERR_ForWin(self, wattroff(self->win, (attr_t)attr), "attroff");
+ int rtn = wattroff(self->win, (attr_t)attr);
+ return curses_window_check_err(self, rtn, "wattroff", "attroff");
}
/*[clinic input]
@@ -1146,7 +1305,8 @@ static PyObject *
_curses_window_attron_impl(PyCursesWindowObject *self, long attr)
/*[clinic end generated code: output=7afea43b237fa870 input=5a88fba7b1524f32]*/
{
- return PyCursesCheckERR_ForWin(self, wattron(self->win, (attr_t)attr), "attron");
+ int rtn = wattron(self->win, (attr_t)attr);
+ return curses_window_check_err(self, rtn, "wattron", "attron");
}
/*[clinic input]
@@ -1162,7 +1322,8 @@ static PyObject *
_curses_window_attrset_impl(PyCursesWindowObject *self, long attr)
/*[clinic end generated code: output=84e379bff20c0433 input=42e400c0d0154ab5]*/
{
- return PyCursesCheckERR_ForWin(self, wattrset(self->win, (attr_t)attr), "attrset");
+ int rtn = wattrset(self->win, (attr_t)attr);
+ return curses_window_check_err(self, rtn, "wattrset", "attrset");
}
/*[clinic input]
@@ -1188,7 +1349,7 @@ _curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch,
return NULL;
wbkgdset(self->win, bkgd | attr);
- return PyCursesCheckERR_ForWin(self, 0, "bkgdset");
+ Py_RETURN_NONE;
}
/*[clinic input]
@@ -1228,7 +1389,7 @@ _curses_window_border_impl(PyCursesWindowObject *self, PyObject *ls,
/*[clinic end generated code: output=670ef38d3d7c2aa3 input=e015f735d67a240b]*/
{
chtype ch[8];
- int i;
+ int i, rtn;
/* Clear the array of parameters */
for(i=0; i<8; i++)
@@ -1249,10 +1410,10 @@ _curses_window_border_impl(PyCursesWindowObject *self, PyObject *ls,
#undef CONVERTTOCHTYPE
- wborder(self->win,
- ch[0], ch[1], ch[2], ch[3],
- ch[4], ch[5], ch[6], ch[7]);
- Py_RETURN_NONE;
+ rtn = wborder(self->win,
+ ch[0], ch[1], ch[2], ch[3],
+ ch[4], ch[5], ch[6], ch[7]);
+ return curses_window_check_err(self, rtn, "wborder", "border");
}
/*[clinic input]
@@ -1286,8 +1447,7 @@ _curses_window_box_impl(PyCursesWindowObject *self, int group_right_1,
return NULL;
}
}
- box(self->win,ch1,ch2);
- Py_RETURN_NONE;
+ return curses_window_check_err(self, box(self->win, ch1, ch2), "box", NULL);
}
#if defined(HAVE_NCURSES_H) || defined(MVWDELCH_IS_EXPRESSION)
@@ -1312,38 +1472,34 @@ int py_mvwdelch(WINDOW *w, int y, int x)
/* chgat, added by Fabian Kreutz <fabian.kreutz at gmx.net> */
#ifdef HAVE_CURSES_WCHGAT
-/*[-clinic input]
-_curses.window.chgat
-
- [
- y: int
- Y-coordinate.
- x: int
- X-coordinate.
- ]
-
- n: int = -1
- Number of characters.
-
- attr: long
- Attributes for characters.
- /
-Set the attributes of characters.
+PyDoc_STRVAR(_curses_window_chgat__doc__,
+"chgat([y, x,] [n=-1,] attr)\n"
+"Set the attributes of characters.\n"
+"\n"
+" y\n"
+" Y-coordinate.\n"
+" x\n"
+" X-coordinate.\n"
+" n\n"
+" Number of characters.\n"
+" attr\n"
+" Attributes for characters.\n"
+"\n"
+"Set the attributes of num characters at the current cursor position, or at\n"
+"position (y, x) if supplied. If no value of num is given or num = -1, the\n"
+"attribute will be set on all the characters to the end of the line. This\n"
+"function does not move the cursor. The changed line will be touched using\n"
+"the touchline() method so that the contents will be redisplayed by the next\n"
+"window refresh.");
-Set the attributes of num characters at the current cursor position, or at
-position (y, x) if supplied. If no value of num is given or num = -1, the
-attribute will be set on all the characters to the end of the line. This
-function does not move the cursor. The changed line will be touched using
-the touchline() method so that the contents will be redisplayed by the next
-window refresh.
-[-clinic start generated code]*/
static PyObject *
PyCursesWindow_ChgAt(PyObject *op, PyObject *args)
{
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
int rtn;
+ const char *funcname;
int x, y;
int num = -1;
short color;
@@ -1363,19 +1519,20 @@ PyCursesWindow_ChgAt(PyObject *op, PyObject *args)
attr = lattr;
break;
case 3:
- if (!PyArg_ParseTuple(args,"iil;int,int,attr", &y, &x, &lattr))
+ if (!PyArg_ParseTuple(args,"iil;y,x,attr", &y, &x, &lattr))
return NULL;
attr = lattr;
use_xy = TRUE;
break;
case 4:
- if (!PyArg_ParseTuple(args,"iiil;int,int,n,attr", &y, &x, &num, &lattr))
+ if (!PyArg_ParseTuple(args,"iiil;y,x,n,attr", &y, &x, &num, &lattr))
return NULL;
attr = lattr;
use_xy = TRUE;
break;
default:
- PyErr_SetString(PyExc_TypeError, "chgat requires 1 to 4 arguments");
+ PyErr_SetString(PyExc_TypeError,
+ "_curses.window.chgat requires 1 to 4 arguments");
return NULL;
}
@@ -1384,13 +1541,18 @@ PyCursesWindow_ChgAt(PyObject *op, PyObject *args)
if (use_xy) {
rtn = mvwchgat(self->win,y,x,num,attr,color,NULL);
- touchline(self->win,y,1);
+ funcname = "mvwchgat";
} else {
getyx(self->win,y,x);
rtn = wchgat(self->win,num,attr,color,NULL);
- touchline(self->win,y,1);
+ funcname = "wchgat";
}
- return PyCursesCheckERR_ForWin(self, rtn, "chgat");
+ if (rtn == ERR) {
+ curses_window_set_error(self, funcname, "chgat");
+ return NULL;
+ }
+ rtn = touchline(self->win,y,1);
+ return curses_window_check_err(self, rtn, "touchline", "chgat");
}
#endif
@@ -1413,12 +1575,17 @@ _curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1,
int y, int x)
/*[clinic end generated code: output=22e77bb9fa11b461 input=d2f79e630a4fc6d0]*/
{
+ int rtn;
+ const char *funcname;
if (!group_right_1) {
- return PyCursesCheckERR_ForWin(self, wdelch(self->win), "wdelch");
+ rtn = wdelch(self->win);
+ funcname = "wdelch";
}
else {
- return PyCursesCheckERR_ForWin(self, py_mvwdelch(self->win, y, x), "mvwdelch");
+ rtn = py_mvwdelch(self->win, y, x);
+ funcname = "mvwdelch";
}
+ return curses_window_check_err(self, rtn, funcname, "delch");
}
/*[clinic input]
@@ -1453,8 +1620,7 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1,
win = derwin(self->win,nlines,ncols,begin_y,begin_x);
if (win == NULL) {
- cursesmodule_state *state = get_cursesmodule_state_by_win(self);
- PyErr_SetString(state->error, catchall_NULL);
+ curses_window_set_null_error(self, "derwin", NULL);
return NULL;
}
@@ -1485,17 +1651,20 @@ _curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch,
if (!PyCurses_ConvertToChtype(self, ch, &ch_))
return NULL;
+ int rtn;
+ const char *funcname;
#ifdef py_is_pad
if (py_is_pad(self->win)) {
- return PyCursesCheckERR_ForWin(self,
- pechochar(self->win, ch_ | (attr_t)attr),
- "echochar");
+ rtn = pechochar(self->win, ch_ | (attr_t)attr);
+ funcname = "pechochar";
}
else
#endif
- return PyCursesCheckERR_ForWin(self,
- wechochar(self->win, ch_ | (attr_t)attr),
- "echochar");
+ {
+ rtn = wechochar(self->win, ch_ | (attr_t)attr);
+ funcname = "wechochar";
+ }
+ return curses_window_check_err(self, rtn, funcname, "echochar");
}
#ifdef NCURSES_MOUSE_VERSION
@@ -1520,20 +1689,40 @@ _curses_window_enclose_impl(PyCursesWindowObject *self, int y, int x)
#endif
/*[clinic input]
-_curses.window.getbkgd -> long
+_curses.window.getbkgd
Return the window's current background character/attribute pair.
[clinic start generated code]*/
-static long
+static PyObject *
_curses_window_getbkgd_impl(PyCursesWindowObject *self)
-/*[clinic end generated code: output=c52b25dc16b215c3 input=a69db882fa35426c]*/
+/*[clinic end generated code: output=3ff953412b0e6028 input=7cf1f59a31f89df4]*/
+{
+ chtype rtn = getbkgd(self->win);
+ if (rtn == (chtype)ERR) {
+ curses_window_set_error(self, "getbkgd", NULL);
+ return NULL;
+ }
+ return PyLong_FromLong(rtn);
+}
+
+static PyObject *
+curses_check_signals_on_input_error(PyCursesWindowObject *self,
+ const char *curses_funcname,
+ const char *python_funcname)
{
- return (long) getbkgd(self->win);
+ assert(!PyErr_Occurred());
+ if (PyErr_CheckSignals()) {
+ return NULL;
+ }
+ cursesmodule_state *state = get_cursesmodule_state_by_win(self);
+ PyErr_Format(state->error, "%s() (called by %s()): no input",
+ curses_funcname, python_funcname);
+ return NULL;
}
/*[clinic input]
-_curses.window.getch -> int
+_curses.window.getch
[
y: int
@@ -1550,10 +1739,10 @@ keypad keys and so on return numbers higher than 256. In no-delay mode, -1
is returned if there is no input, else getch() waits until a key is pressed.
[clinic start generated code]*/
-static int
+static PyObject *
_curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1,
int y, int x)
-/*[clinic end generated code: output=980aa6af0c0ca387 input=bb24ebfb379f991f]*/
+/*[clinic end generated code: output=e1639e87d545e676 input=73f350336b1ee8c8]*/
{
int rtn;
@@ -1566,7 +1755,17 @@ _curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1,
}
Py_END_ALLOW_THREADS
- return rtn;
+ if (rtn == ERR) {
+ // We suppress ERR returned by wgetch() in nodelay mode
+ // after we handled possible interruption signals.
+ if (PyErr_CheckSignals()) {
+ return NULL;
+ }
+ // ERR is an implementation detail, so to be on the safe side,
+ // we forcibly set the return value to -1 as documented above.
+ rtn = -1;
+ }
+ return PyLong_FromLong(rtn);
}
/*[clinic input]
@@ -1604,13 +1803,9 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1,
Py_END_ALLOW_THREADS
if (rtn == ERR) {
- /* getch() returns ERR in nodelay mode */
- PyErr_CheckSignals();
- if (!PyErr_Occurred()) {
- cursesmodule_state *state = get_cursesmodule_state_by_win(self);
- PyErr_SetString(state->error, "no input");
- }
- return NULL;
+ /* wgetch() returns ERR in nodelay mode */
+ const char *funcname = group_right_1 ? "mvwgetch" : "wgetch";
+ return curses_check_signals_on_input_error(self, funcname, "getkey");
} else if (rtn <= 255) {
#ifdef NCURSES_VERSION_MAJOR
#if NCURSES_VERSION_MAJOR*100+NCURSES_VERSION_MINOR <= 507
@@ -1663,13 +1858,9 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1,
Py_END_ALLOW_THREADS
if (ct == ERR) {
- if (PyErr_CheckSignals())
- return NULL;
-
- /* get_wch() returns ERR in nodelay mode */
- cursesmodule_state *state = get_cursesmodule_state_by_win(self);
- PyErr_SetString(state->error, "no input");
- return NULL;
+ /* wget_wch() returns ERR in nodelay mode */
+ const char *funcname = group_right_1 ? "mvwget_wch" : "wget_wch";
+ return curses_check_signals_on_input_error(self, funcname, "get_wch");
}
if (ct == KEY_CODE_YES)
return PyLong_FromLong(rtn);
@@ -1678,84 +1869,102 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1,
}
#endif
-/*[-clinic input]
-_curses.window.getstr
-
- [
- y: int
- Y-coordinate.
- x: int
- X-coordinate.
- ]
- n: int = 1023
- Maximal number of characters.
- /
+/*
+ * Helper function for parsing parameters from getstr() and instr().
+ * This function is necessary because Argument Clinic does not know
+ * how to handle nested optional groups with default values inside.
+ *
+ * Return 1 on success and 0 on failure, similar to PyArg_ParseTuple().
+ */
+static int
+curses_clinic_parse_optional_xy_n(PyObject *args,
+ int *y, int *x, unsigned int *n, int *use_xy,
+ const char *qualname)
+{
+ switch (PyTuple_GET_SIZE(args)) {
+ case 0: {
+ *use_xy = 0;
+ return 1;
+ }
+ case 1: {
+ *use_xy = 0;
+ return PyArg_ParseTuple(args, "O&;n",
+ _PyLong_UnsignedInt_Converter, n);
+ }
+ case 2: {
+ *use_xy = 1;
+ return PyArg_ParseTuple(args, "ii;y,x", y, x);
+ }
+ case 3: {
+ *use_xy = 1;
+ return PyArg_ParseTuple(args, "iiO&;y,x,n", y, x,
+ _PyLong_UnsignedInt_Converter, n);
+ }
+ default: {
+ *use_xy = 0;
+ PyErr_Format(PyExc_TypeError, "%s requires 0 to 3 arguments",
+ qualname);
+ return 0;
+ }
+ }
+}
-Read a string from the user, with primitive line editing capacity.
-[-clinic start generated code]*/
+PyDoc_STRVAR(_curses_window_getstr__doc__,
+"getstr([[y, x,] n=2047])\n"
+"Read a string from the user, with primitive line editing capacity.\n"
+"\n"
+" y\n"
+" Y-coordinate.\n"
+" x\n"
+" X-coordinate.\n"
+" n\n"
+" Maximal number of characters.");
static PyObject *
-PyCursesWindow_GetStr(PyObject *op, PyObject *args)
+PyCursesWindow_getstr(PyObject *op, PyObject *args)
{
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+ int rtn, use_xy = 0, y = 0, x = 0;
+ unsigned int max_buf_size = 2048;
+ unsigned int n = max_buf_size - 1;
+ PyObject *res;
- int x, y, n;
- char rtn[1024]; /* This should be big enough.. I hope */
- int rtn2;
+ if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy,
+ "_curses.window.instr"))
+ {
+ return NULL;
+ }
- switch (PyTuple_Size(args)) {
- case 0:
- Py_BEGIN_ALLOW_THREADS
- rtn2 = wgetnstr(self->win,rtn, 1023);
- Py_END_ALLOW_THREADS
- break;
- case 1:
- if (!PyArg_ParseTuple(args,"i;n", &n))
- return NULL;
- if (n < 0) {
- PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
- return NULL;
- }
- Py_BEGIN_ALLOW_THREADS
- rtn2 = wgetnstr(self->win, rtn, Py_MIN(n, 1023));
- Py_END_ALLOW_THREADS
- break;
- case 2:
- if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
- return NULL;
+ n = Py_MIN(n, max_buf_size - 1);
+ res = PyBytes_FromStringAndSize(NULL, n + 1);
+ if (res == NULL) {
+ return NULL;
+ }
+ char *buf = PyBytes_AS_STRING(res);
+
+ if (use_xy) {
Py_BEGIN_ALLOW_THREADS
#ifdef STRICT_SYSV_CURSES
- rtn2 = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, 1023);
+ rtn = wmove(self->win, y, x) == ERR
+ ? ERR
+ : wgetnstr(self->win, buf, n);
#else
- rtn2 = mvwgetnstr(self->win,y,x,rtn, 1023);
+ rtn = mvwgetnstr(self->win, y, x, buf, n);
#endif
Py_END_ALLOW_THREADS
- break;
- case 3:
- if (!PyArg_ParseTuple(args,"iii;y,x,n", &y, &x, &n))
- return NULL;
- if (n < 0) {
- PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
- return NULL;
- }
-#ifdef STRICT_SYSV_CURSES
- Py_BEGIN_ALLOW_THREADS
- rtn2 = wmove(self->win,y,x)==ERR ? ERR :
- wgetnstr(self->win, rtn, Py_MIN(n, 1023));
- Py_END_ALLOW_THREADS
-#else
+ }
+ else {
Py_BEGIN_ALLOW_THREADS
- rtn2 = mvwgetnstr(self->win, y, x, rtn, Py_MIN(n, 1023));
+ rtn = wgetnstr(self->win, buf, n);
Py_END_ALLOW_THREADS
-#endif
- break;
- default:
- PyErr_SetString(PyExc_TypeError, "getstr requires 0 to 3 arguments");
- return NULL;
}
- if (rtn2 == ERR)
- rtn[0] = 0;
- return PyBytes_FromString(rtn);
+
+ if (rtn == ERR) {
+ Py_DECREF(res);
+ return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
+ }
+ _PyBytes_Resize(&res, strlen(buf)); // 'res' is set to NULL on failure
+ return res;
}
/*[clinic input]
@@ -1794,10 +2003,12 @@ _curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1,
return NULL;
if (group_left_1) {
if (wmove(self->win, y, x) == ERR) {
- return PyCursesCheckERR_ForWin(self, ERR, "wmove");
+ curses_window_set_error(self, "wmove", "hline");
+ return NULL;
}
}
- return PyCursesCheckERR_ForWin(self, whline(self->win, ch_ | (attr_t)attr, n), "hline");
+ int rtn = whline(self->win, ch_ | (attr_t)attr, n);
+ return curses_window_check_err(self, rtn, "whline", "hline");
}
/*[clinic input]
@@ -1837,18 +2048,21 @@ _curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1,
if (!PyCurses_ConvertToChtype(self, ch, &ch_))
return NULL;
+ const char *funcname;
if (!group_left_1) {
rtn = winsch(self->win, ch_ | (attr_t)attr);
+ funcname = "winsch";
}
else {
rtn = mvwinsch(self->win, y, x, ch_ | (attr_t)attr);
+ funcname = "mvwwinsch";
}
- return PyCursesCheckERR_ForWin(self, rtn, "insch");
+ return curses_window_check_err(self, rtn, funcname, "insch");
}
/*[clinic input]
-_curses.window.inch -> unsigned_long
+_curses.window.inch
[
y: int
@@ -1863,86 +2077,80 @@ Return the character at the given position in the window.
The bottom 8 bits are the character proper, and upper bits are the attributes.
[clinic start generated code]*/
-static unsigned long
+static PyObject *
_curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1,
int y, int x)
-/*[clinic end generated code: output=6c4719fe978fe86a input=fac23ee11e3b3a66]*/
+/*[clinic end generated code: output=97ca8581baaafd06 input=4b4fb43d85b177c3]*/
{
- unsigned long rtn;
+ chtype rtn;
+ const char *funcname;
if (!group_right_1) {
rtn = winch(self->win);
+ funcname = "winch";
}
else {
rtn = mvwinch(self->win, y, x);
+ funcname = "mvwinch";
}
+ if (rtn == (chtype)ERR) {
+ curses_window_set_error(self, funcname, "inch");
+ return NULL;
+ }
+ return PyLong_FromUnsignedLong(rtn);
+}
+
+PyDoc_STRVAR(_curses_window_instr__doc__,
+"instr([y, x,] n=2047)\n"
+"Return a string of characters, extracted from the window.\n"
+"\n"
+" y\n"
+" Y-coordinate.\n"
+" x\n"
+" X-coordinate.\n"
+" n\n"
+" Maximal number of characters.\n"
+"\n"
+"Return a string of characters, extracted from the window starting at the\n"
+"current cursor position, or at y, x if specified. Attributes are stripped\n"
+"from the characters. If n is specified, instr() returns a string at most\n"
+"n characters long (exclusive of the trailing NUL).");
- return rtn;
-}
-
-/*[-clinic input]
-_curses.window.instr
-
- [
- y: int
- Y-coordinate.
- x: int
- X-coordinate.
- ]
- n: int = 1023
- Maximal number of characters.
- /
-
-Return a string of characters, extracted from the window.
-
-Return a string of characters, extracted from the window starting at the
-current cursor position, or at y, x if specified. Attributes are stripped
-from the characters. If n is specified, instr() returns a string at most
-n characters long (exclusive of the trailing NUL).
-[-clinic start generated code]*/
static PyObject *
-PyCursesWindow_InStr(PyObject *op, PyObject *args)
+PyCursesWindow_instr(PyObject *op, PyObject *args)
{
PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op);
+ int rtn, use_xy = 0, y = 0, x = 0;
+ unsigned int max_buf_size = 2048;
+ unsigned int n = max_buf_size - 1;
+ PyObject *res;
- int x, y, n;
- char rtn[1024]; /* This should be big enough.. I hope */
- int rtn2;
+ if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy,
+ "_curses.window.instr"))
+ {
+ return NULL;
+ }
- switch (PyTuple_Size(args)) {
- case 0:
- rtn2 = winnstr(self->win,rtn, 1023);
- break;
- case 1:
- if (!PyArg_ParseTuple(args,"i;n", &n))
- return NULL;
- if (n < 0) {
- PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
- return NULL;
- }
- rtn2 = winnstr(self->win, rtn, Py_MIN(n, 1023));
- break;
- case 2:
- if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x))
- return NULL;
- rtn2 = mvwinnstr(self->win,y,x,rtn,1023);
- break;
- case 3:
- if (!PyArg_ParseTuple(args, "iii;y,x,n", &y, &x, &n))
- return NULL;
- if (n < 0) {
- PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative");
- return NULL;
- }
- rtn2 = mvwinnstr(self->win, y, x, rtn, Py_MIN(n,1023));
- break;
- default:
- PyErr_SetString(PyExc_TypeError, "instr requires 0 or 3 arguments");
+ n = Py_MIN(n, max_buf_size - 1);
+ res = PyBytes_FromStringAndSize(NULL, n + 1);
+ if (res == NULL) {
return NULL;
}
- if (rtn2 == ERR)
- rtn[0] = 0;
- return PyBytes_FromString(rtn);
+ char *buf = PyBytes_AS_STRING(res);
+
+ if (use_xy) {
+ rtn = mvwinnstr(self->win, y, x, buf, n);
+ }
+ else {
+ rtn = winnstr(self->win, buf, n);
+ }
+
+ if (rtn == ERR) {
+ Py_DECREF(res);
+ return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
+ }
+ _PyBytes_Resize(&res, strlen(buf)); // 'res' is set to NULL on failure
+ return res;
}
/*[clinic input]
@@ -1999,31 +2207,46 @@ _curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1,
if (use_attr) {
attr_old = getattrs(self->win);
- (void)wattrset(self->win, (attr_t)attr);
+ if (curses_wattrset(self, attr, "insstr") < 0) {
+ curses_release_wstr(strtype, wstr);
+ return NULL;
+ }
}
#ifdef HAVE_NCURSESW
if (strtype == 2) {
- funcname = "inswstr";
- if (use_xy)
+ if (use_xy) {
rtn = mvwins_wstr(self->win,y,x,wstr);
- else
+ funcname = "mvwins_wstr";
+ }
+ else {
rtn = wins_wstr(self->win,wstr);
+ funcname = "wins_wstr";
+ }
PyMem_Free(wstr);
}
else
#endif
{
const char *str = PyBytes_AS_STRING(bytesobj);
- funcname = "insstr";
- if (use_xy)
+ if (use_xy) {
rtn = mvwinsstr(self->win,y,x,str);
- else
+ funcname = "mvwinsstr";
+ }
+ else {
rtn = winsstr(self->win,str);
+ funcname = "winsstr";
+ }
Py_DECREF(bytesobj);
}
- if (use_attr)
- (void)wattrset(self->win,attr_old);
- return PyCursesCheckERR_ForWin(self, rtn, funcname);
+ if (rtn == ERR) {
+ curses_window_set_error(self, funcname, "insstr");
+ return NULL;
+ }
+ if (use_attr) {
+ rtn = wattrset(self->win, attr_old);
+ return curses_window_check_err(self, rtn, "wattrset", "insstr");
+ }
+ Py_RETURN_NONE;
}
/*[clinic input]
@@ -2084,31 +2307,46 @@ _curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1,
if (use_attr) {
attr_old = getattrs(self->win);
- (void)wattrset(self->win, (attr_t)attr);
+ if (curses_wattrset(self, attr, "insnstr") < 0) {
+ curses_release_wstr(strtype, wstr);
+ return NULL;
+ }
}
#ifdef HAVE_NCURSESW
if (strtype == 2) {
- funcname = "insn_wstr";
- if (use_xy)
+ if (use_xy) {
rtn = mvwins_nwstr(self->win,y,x,wstr,n);
- else
+ funcname = "mvwins_nwstr";
+ }
+ else {
rtn = wins_nwstr(self->win,wstr,n);
+ funcname = "wins_nwstr";
+ }
PyMem_Free(wstr);
}
else
#endif
{
const char *str = PyBytes_AS_STRING(bytesobj);
- funcname = "insnstr";
- if (use_xy)
+ if (use_xy) {
rtn = mvwinsnstr(self->win,y,x,str,n);
- else
+ funcname = "mvwinsnstr";
+ }
+ else {
rtn = winsnstr(self->win,str,n);
+ funcname = "winsnstr";
+ }
Py_DECREF(bytesobj);
}
- if (use_attr)
- (void)wattrset(self->win,attr_old);
- return PyCursesCheckERR_ForWin(self, rtn, funcname);
+ if (rtn == ERR) {
+ curses_window_set_error(self, funcname, "insnstr");
+ return NULL;
+ }
+ if (use_attr) {
+ rtn = wattrset(self->win, attr_old);
+ return curses_window_check_err(self, rtn, "wattrset", "insnstr");
+ }
+ Py_RETURN_NONE;
}
/*[clinic input]
@@ -2130,8 +2368,7 @@ _curses_window_is_linetouched_impl(PyCursesWindowObject *self, int line)
int erg;
erg = is_linetouched(self->win, line);
if (erg == ERR) {
- PyErr_SetString(PyExc_TypeError,
- "is_linetouched: line number outside of boundaries");
+ curses_window_set_error(self, "is_linetouched", NULL);
return NULL;
}
return PyBool_FromLong(erg);
@@ -2185,8 +2422,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self)
#ifdef py_is_pad
if (py_is_pad(self->win)) {
if (!group_right_1) {
- cursesmodule_state *state = get_cursesmodule_state_by_win(self);
- PyErr_SetString(state->error,
+ PyErr_SetString(PyExc_TypeError,
"noutrefresh() called for a pad "
"requires 6 arguments");
return NULL;
@@ -2195,7 +2431,8 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self)
rtn = pnoutrefresh(self->win, pminrow, pmincol,
sminrow, smincol, smaxrow, smaxcol);
Py_END_ALLOW_THREADS
- return PyCursesCheckERR_ForWin(self, rtn, "pnoutrefresh");
+ return curses_window_check_err(self, rtn,
+ "pnoutrefresh", "noutrefresh");
}
if (group_right_1) {
PyErr_SetString(PyExc_TypeError,
@@ -2206,7 +2443,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self)
Py_BEGIN_ALLOW_THREADS
rtn = wnoutrefresh(self->win);
Py_END_ALLOW_THREADS
- return PyCursesCheckERR_ForWin(self, rtn, "wnoutrefresh");
+ return curses_window_check_err(self, rtn, "wnoutrefresh", "noutrefresh");
}
/*[clinic input]
@@ -2248,11 +2485,11 @@ _curses_window_overlay_impl(PyCursesWindowObject *self,
if (group_right_1) {
rtn = copywin(self->win, destwin->win, sminrow, smincol,
dminrow, dmincol, dmaxrow, dmaxcol, TRUE);
- return PyCursesCheckERR_ForWin(self, rtn, "copywin");
+ return curses_window_check_err(self, rtn, "copywin", "overlay");
}
else {
rtn = overlay(self->win, destwin->win);
- return PyCursesCheckERR_ForWin(self, rtn, "overlay");
+ return curses_window_check_err(self, rtn, "overlay", NULL);
}
}
@@ -2296,11 +2533,11 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self,
if (group_right_1) {
rtn = copywin(self->win, destwin->win, sminrow, smincol,
dminrow, dmincol, dmaxrow, dmaxcol, FALSE);
- return PyCursesCheckERR_ForWin(self, rtn, "copywin");
+ return curses_window_check_err(self, rtn, "copywin", "overwrite");
}
else {
rtn = overwrite(self->win, destwin->win);
- return PyCursesCheckERR_ForWin(self, rtn, "overwrite");
+ return curses_window_check_err(self, rtn, "overwrite", NULL);
}
}
@@ -2329,7 +2566,7 @@ _curses_window_putwin_impl(PyCursesWindowObject *self, PyObject *file)
return PyErr_SetFromErrno(PyExc_OSError);
if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0)
goto exit;
- res = PyCursesCheckERR_ForWin(self, putwin(self->win, fp), "putwin");
+ res = curses_window_check_err(self, putwin(self->win, fp), "putwin", NULL);
if (res == NULL)
goto exit;
fseek(fp, 0, 0);
@@ -2368,7 +2605,8 @@ static PyObject *
_curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num)
/*[clinic end generated code: output=ea216e334f9ce1b4 input=152155e258a77a7a]*/
{
- return PyCursesCheckERR_ForWin(self, wredrawln(self->win,beg,num), "redrawln");
+ int rtn = wredrawln(self->win,beg, num);
+ return curses_window_check_err(self, rtn, "wredrawln", "redrawln");
}
/*[clinic input]
@@ -2410,8 +2648,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1,
#ifdef py_is_pad
if (py_is_pad(self->win)) {
if (!group_right_1) {
- cursesmodule_state *state = get_cursesmodule_state_by_win(self);
- PyErr_SetString(state->error,
+ PyErr_SetString(PyExc_TypeError,
"refresh() for a pad requires 6 arguments");
return NULL;
}
@@ -2419,7 +2656,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1,
rtn = prefresh(self->win, pminrow, pmincol,
sminrow, smincol, smaxrow, smaxcol);
Py_END_ALLOW_THREADS
- return PyCursesCheckERR_ForWin(self, rtn, "prefresh");
+ return curses_window_check_err(self, rtn, "prefresh", "refresh");
}
#endif
if (group_right_1) {
@@ -2430,7 +2667,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1,
Py_BEGIN_ALLOW_THREADS
rtn = wrefresh(self->win);
Py_END_ALLOW_THREADS
- return PyCursesCheckERR_ForWin(self, rtn, "prefresh");
+ return curses_window_check_err(self, rtn, "wrefresh", "refresh");
}
/*[clinic input]
@@ -2452,7 +2689,8 @@ _curses_window_setscrreg_impl(PyCursesWindowObject *self, int top,
int bottom)
/*[clinic end generated code: output=486ab5db218d2b1a input=1b517b986838bf0e]*/
{
- return PyCursesCheckERR_ForWin(self, wsetscrreg(self->win, top, bottom), "wsetscrreg");
+ int rtn = wsetscrreg(self->win, top, bottom);
+ return curses_window_check_err(self, rtn, "wsetscrreg", "setscrreg");
}
/*[clinic input]
@@ -2482,19 +2720,23 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1,
/*[clinic end generated code: output=93e898afc348f59a input=2129fa47fd57721c]*/
{
WINDOW *win;
+ const char *funcname;
/* printf("Subwin: %i %i %i %i \n", nlines, ncols, begin_y, begin_x); */
#ifdef py_is_pad
if (py_is_pad(self->win)) {
win = subpad(self->win, nlines, ncols, begin_y, begin_x);
+ funcname = "subpad";
}
else
#endif
+ {
win = subwin(self->win, nlines, ncols, begin_y, begin_x);
+ funcname = "subwin";
+ }
if (win == NULL) {
- cursesmodule_state *state = get_cursesmodule_state_by_win(self);
- PyErr_SetString(state->error, catchall_NULL);
+ curses_window_set_null_error(self, funcname, "subwin");
return NULL;
}
@@ -2521,12 +2763,17 @@ _curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1,
int lines)
/*[clinic end generated code: output=4541a8a11852d360 input=c969ca0cfabbdbec]*/
{
+ int rtn;
+ const char *funcname;
if (!group_right_1) {
- return PyCursesCheckERR_ForWin(self, scroll(self->win), "scroll");
+ rtn = scroll(self->win);
+ funcname = "scroll";
}
else {
- return PyCursesCheckERR_ForWin(self, wscrl(self->win, lines), "scroll");
+ rtn = wscrl(self->win, lines);
+ funcname = "wscrl";
}
+ return curses_window_check_err(self, rtn, funcname, "scroll");
}
/*[clinic input]
@@ -2550,12 +2797,17 @@ _curses_window_touchline_impl(PyCursesWindowObject *self, int start,
int count, int group_right_1, int changed)
/*[clinic end generated code: output=65d05b3f7438c61d input=a98aa4f79b6be845]*/
{
+ int rtn;
+ const char *funcname;
if (!group_right_1) {
- return PyCursesCheckERR_ForWin(self, touchline(self->win, start, count), "touchline");
+ rtn = touchline(self->win, start, count);
+ funcname = "touchline";
}
else {
- return PyCursesCheckERR_ForWin(self, wtouchln(self->win, start, count, changed), "touchline");
+ rtn = wtouchln(self->win, start, count, changed);
+ funcname = "wtouchln";
}
+ return curses_window_check_err(self, rtn, funcname, "touchline");
}
/*[clinic input]
@@ -2593,10 +2845,13 @@ _curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1,
if (!PyCurses_ConvertToChtype(self, ch, &ch_))
return NULL;
if (group_left_1) {
- if (wmove(self->win, y, x) == ERR)
- return PyCursesCheckERR_ForWin(self, ERR, "wmove");
+ if (wmove(self->win, y, x) == ERR) {
+ curses_window_set_error(self, "wmove", "vline");
+ return NULL;
+ }
}
- return PyCursesCheckERR_ForWin(self, wvline(self->win, ch_ | (attr_t)attr, n), "vline");
+ int rtn = wvline(self->win, ch_ | (attr_t)attr, n);
+ return curses_window_check_err(self, rtn, "wvline", "vline");
}
static PyObject *
@@ -2653,7 +2908,10 @@ static PyMethodDef PyCursesWindow_methods[] = {
_CURSES_WINDOW_ATTRSET_METHODDEF
_CURSES_WINDOW_BKGD_METHODDEF
#ifdef HAVE_CURSES_WCHGAT
- {"chgat", PyCursesWindow_ChgAt, METH_VARARGS},
+ {
+ "chgat", PyCursesWindow_ChgAt, METH_VARARGS,
+ _curses_window_chgat__doc__
+ },
#endif
_CURSES_WINDOW_BKGDSET_METHODDEF
_CURSES_WINDOW_BORDER_METHODDEF
@@ -2676,7 +2934,10 @@ static PyMethodDef PyCursesWindow_methods[] = {
_CURSES_WINDOW_GET_WCH_METHODDEF
{"getmaxyx", PyCursesWindow_getmaxyx, METH_NOARGS},
{"getparyx", PyCursesWindow_getparyx, METH_NOARGS},
- {"getstr", PyCursesWindow_GetStr, METH_VARARGS},
+ {
+ "getstr", PyCursesWindow_getstr, METH_VARARGS,
+ _curses_window_getstr__doc__
+ },
{"getyx", PyCursesWindow_getyx, METH_NOARGS},
_CURSES_WINDOW_HLINE_METHODDEF
{"idcok", PyCursesWindow_idcok, METH_VARARGS},
@@ -2690,7 +2951,10 @@ static PyMethodDef PyCursesWindow_methods[] = {
{"insertln", PyCursesWindow_winsertln, METH_NOARGS},
_CURSES_WINDOW_INSNSTR_METHODDEF
_CURSES_WINDOW_INSSTR_METHODDEF
- {"instr", PyCursesWindow_InStr, METH_VARARGS},
+ {
+ "instr", PyCursesWindow_instr, METH_VARARGS,
+ _curses_window_instr__doc__
+ },
_CURSES_WINDOW_IS_LINETOUCHED_METHODDEF
{"is_wintouched", PyCursesWindow_is_wintouched, METH_NOARGS},
{"keypad", PyCursesWindow_keypad, METH_VARARGS},
@@ -2761,50 +3025,79 @@ static PyType_Spec PyCursesWindow_Type_spec = {
/* -------------------------------------------------------*/
-/* Function Body Macros - They are ugly but very, very useful. ;-)
-
- X - function name
- TYPE - parameter Type
- ERGSTR - format string for construction of the return value
- PARSESTR - format string for argument parsing
- */
-
-#define NoArgNoReturnFunctionBody(X) \
-{ \
- PyCursesStatefulInitialised(module); \
- return PyCursesCheckERR(module, X(), # X); }
+/*
+ * Macros for implementing simple module's methods.
+ *
+ * Parameters
+ *
+ * X The name of the curses C function or macro to invoke.
+ * FLAG When false, prefixes the function name with 'no' at runtime,
+ * This parameter is present in the signature and auto-generated
+ * by Argument Clinic.
+ *
+ * These macros should only be used for generating the body of
+ * the module's methods since they need a module reference.
+ *
+ * The Python function name must be the same as the curses function name (X).
+ */
-#define NoArgOrFlagNoReturnFunctionBody(X, flag) \
-{ \
- PyCursesStatefulInitialised(module); \
- if (flag) \
- return PyCursesCheckERR(module, X(), # X); \
- else \
- return PyCursesCheckERR(module, no ## X(), # X); \
+#define NoArgNoReturnFunctionBody(X) \
+{ \
+ PyCursesStatefulInitialised(module); \
+ return curses_check_err(module, X(), # X, NULL); \
+}
+
+#define NoArgOrFlagNoReturnFunctionBody(X, FLAG) \
+{ \
+ PyCursesStatefulInitialised(module); \
+ int rtn; \
+ const char *funcname; \
+ if (FLAG) { \
+ rtn = X(); \
+ funcname = # X; \
+ } \
+ else { \
+ rtn = no ## X(); \
+ funcname = "no" # X; \
+ } \
+ return curses_check_err(module, rtn, funcname, # X); \
+}
+
+#define NoArgReturnIntFunctionBody(X) \
+{ \
+ PyCursesStatefulInitialised(module); \
+ int rtn = X(); \
+ if (rtn == ERR) { \
+ curses_set_error(module, # X, NULL); \
+ return NULL; \
+ } \
+ return PyLong_FromLong(rtn); \
+}
+
+#define NoArgReturnStringFunctionBody(X) \
+{ \
+ PyCursesStatefulInitialised(module); \
+ const char *res = X(); \
+ if (res == NULL) { \
+ curses_set_null_error(module, # X, NULL); \
+ return NULL; \
+ } \
+ return PyBytes_FromString(res); \
+}
+
+#define NoArgTrueFalseFunctionBody(X) \
+{ \
+ PyCursesStatefulInitialised(module); \
+ return PyBool_FromLong(X()); \
+}
+
+#define NoArgNoReturnVoidFunctionBody(X) \
+{ \
+ PyCursesStatefulInitialised(module); \
+ X(); \
+ Py_RETURN_NONE; \
}
-#define NoArgReturnIntFunctionBody(X) \
-{ \
- PyCursesStatefulInitialised(module); \
- return PyLong_FromLong((long) X()); }
-
-
-#define NoArgReturnStringFunctionBody(X) \
-{ \
- PyCursesStatefulInitialised(module); \
- return PyBytes_FromString(X()); }
-
-#define NoArgTrueFalseFunctionBody(X) \
-{ \
- PyCursesStatefulInitialised(module); \
- return PyBool_FromLong(X()); }
-
-#define NoArgNoReturnVoidFunctionBody(X) \
-{ \
- PyCursesStatefulInitialised(module); \
- X(); \
- Py_RETURN_NONE; }
-
/*********************************************************************
Global Functions
**********************************************************************/
@@ -2903,9 +3196,8 @@ _curses_color_content_impl(PyObject *module, int color_number)
PyCursesStatefulInitialisedColor(module);
if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_Format(state->error, "%s() returned ERR",
- Py_STRINGIFY(_COLOR_CONTENT_FUNC));
+ const char *funcname = Py_STRINGIFY(_COLOR_CONTENT_FUNC);
+ curses_set_error(module, funcname, "color_content");
return NULL;
}
@@ -2959,7 +3251,10 @@ _curses_curs_set_impl(PyObject *module, int visibility)
PyCursesStatefulInitialised(module);
erg = curs_set(visibility);
- if (erg == ERR) return PyCursesCheckERR(module, erg, "curs_set");
+ if (erg == ERR) {
+ curses_set_error(module, "curs_set", NULL);
+ return NULL;
+ }
return PyLong_FromLong((long) erg);
}
@@ -3010,7 +3305,7 @@ _curses_delay_output_impl(PyObject *module, int ms)
{
PyCursesStatefulInitialised(module);
- return PyCursesCheckERR(module, delay_output(ms), "delay_output");
+ return curses_check_err(module, delay_output(ms), "delay_output", NULL);
}
/*[clinic input]
@@ -3143,8 +3438,7 @@ _curses_getmouse_impl(PyObject *module)
rtn = getmouse( &event );
if (rtn == ERR) {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, "getmouse() returned ERR");
+ curses_set_error(module, "getmouse", NULL);
return NULL;
}
return Py_BuildValue("(hiiik)",
@@ -3182,7 +3476,7 @@ _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z,
event.y = y;
event.z = z;
event.bstate = bstate;
- return PyCursesCheckERR(module, ungetmouse(&event), "ungetmouse");
+ return curses_check_err(module, ungetmouse(&event), "ungetmouse", NULL);
}
#endif
@@ -3238,8 +3532,7 @@ _curses_getwin(PyObject *module, PyObject *file)
fseek(fp, 0, 0);
win = getwin(fp);
if (win == NULL) {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, catchall_NULL);
+ curses_set_null_error(module, "getwin", NULL);
goto error;
}
cursesmodule_state *state = get_cursesmodule_state(module);
@@ -3268,7 +3561,7 @@ _curses_halfdelay_impl(PyObject *module, unsigned char tenths)
{
PyCursesStatefulInitialised(module);
- return PyCursesCheckERR(module, halfdelay(tenths), "halfdelay");
+ return curses_check_err(module, halfdelay(tenths), "halfdelay", NULL);
}
/*[clinic input]
@@ -3353,9 +3646,10 @@ _curses_init_color_impl(PyObject *module, int color_number, short r, short g,
PyCursesStatefulInitialised(module);
PyCursesStatefulInitialisedColor(module);
- return PyCursesCheckERR(module,
+ return curses_check_err(module,
_CURSES_INIT_COLOR_FUNC(color_number, r, g, b),
- Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC));
+ Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC),
+ NULL);
}
/*[clinic input]
@@ -3389,9 +3683,8 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg)
COLOR_PAIRS - 1);
}
else {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_Format(state->error, "%s() returned ERR",
- Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC));
+ const char *funcname = Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC);
+ curses_set_error(module, funcname, "init_pair");
}
return NULL;
}
@@ -3414,16 +3707,19 @@ _curses_initscr_impl(PyObject *module)
WINDOW *win;
if (curses_initscr_called) {
- wrefresh(stdscr);
cursesmodule_state *state = get_cursesmodule_state(module);
+ int code = wrefresh(stdscr);
+ if (code == ERR) {
+ _curses_set_null_error(state, "wrefresh", "initscr");
+ return NULL;
+ }
return PyCursesWindow_New(state, stdscr, NULL, NULL);
}
win = initscr();
if (win == NULL) {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, catchall_NULL);
+ curses_set_null_error(module, "initscr", NULL);
return NULL;
}
@@ -3550,7 +3846,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd)
if (fd == -1) {
PyObject* sys_stdout;
- if (_PySys_GetOptionalAttrString("stdout", &sys_stdout) < 0) {
+ if (PySys_GetOptionalAttrString("stdout", &sys_stdout) < 0) {
return NULL;
}
@@ -3628,7 +3924,7 @@ _curses_set_escdelay_impl(PyObject *module, int ms)
return NULL;
}
- return PyCursesCheckERR(module, set_escdelay(ms), "set_escdelay");
+ return curses_check_err(module, set_escdelay(ms), "set_escdelay", NULL);
}
/*[clinic input]
@@ -3667,7 +3963,7 @@ _curses_set_tabsize_impl(PyObject *module, int size)
return NULL;
}
- return PyCursesCheckERR(module, set_tabsize(size), "set_tabsize");
+ return curses_check_err(module, set_tabsize(size), "set_tabsize", NULL);
}
#endif
@@ -3685,7 +3981,7 @@ _curses_intrflush_impl(PyObject *module, int flag)
{
PyCursesStatefulInitialised(module);
- return PyCursesCheckERR(module, intrflush(NULL, flag), "intrflush");
+ return curses_check_err(module, intrflush(NULL, flag), "intrflush", NULL);
}
/*[clinic input]
@@ -3798,7 +4094,7 @@ _curses_meta_impl(PyObject *module, int yes)
{
PyCursesStatefulInitialised(module);
- return PyCursesCheckERR(module, meta(stdscr, yes), "meta");
+ return curses_check_err(module, meta(stdscr, yes), "meta", NULL);
}
#ifdef NCURSES_MOUSE_VERSION
@@ -3821,8 +4117,12 @@ _curses_mouseinterval_impl(PyObject *module, int interval)
/*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/
{
PyCursesStatefulInitialised(module);
-
- return PyCursesCheckERR(module, mouseinterval(interval), "mouseinterval");
+ int value = mouseinterval(interval);
+ if (value == ERR) {
+ curses_set_error(module, "mouseinterval", NULL);
+ return NULL;
+ }
+ return PyLong_FromLong(value);
}
/*[clinic input]
@@ -3898,8 +4198,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols)
win = newpad(nlines, ncols);
if (win == NULL) {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, catchall_NULL);
+ curses_set_null_error(module, "newpad", NULL);
return NULL;
}
@@ -3939,8 +4238,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols,
win = newwin(nlines,ncols,begin_y,begin_x);
if (win == NULL) {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, catchall_NULL);
+ curses_set_null_error(module, "newwin", NULL);
return NULL;
}
@@ -4059,9 +4357,8 @@ _curses_pair_content_impl(PyObject *module, int pair_number)
COLOR_PAIRS - 1);
}
else {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_Format(state->error, "%s() returned ERR",
- Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC));
+ const char *funcname = Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC);
+ curses_set_error(module, funcname, "pair_content");
}
return NULL;
}
@@ -4105,7 +4402,7 @@ static PyObject *
_curses_putp_impl(PyObject *module, const char *string)
/*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/
{
- return PyCursesCheckERR(module, putp(string), "putp");
+ return curses_check_err(module, putp(string), "putp", NULL);
}
/*[clinic input]
@@ -4279,10 +4576,12 @@ _curses_resizeterm_impl(PyObject *module, short nlines, short ncols)
/*[clinic end generated code: output=4de3abab50c67f02 input=414e92a63e3e9899]*/
{
PyObject *result;
+ int code;
PyCursesStatefulInitialised(module);
- result = PyCursesCheckERR(module, resizeterm(nlines, ncols), "resizeterm");
+ code = resizeterm(nlines, ncols);
+ result = curses_check_err(module, code, "resizeterm", NULL);
if (!result)
return NULL;
if (!update_lines_cols(module)) {
@@ -4318,10 +4617,12 @@ _curses_resize_term_impl(PyObject *module, short nlines, short ncols)
/*[clinic end generated code: output=46c6d749fa291dbd input=276afa43d8ea7091]*/
{
PyObject *result;
+ int code;
PyCursesStatefulInitialised(module);
- result = PyCursesCheckERR(module, resize_term(nlines, ncols), "resize_term");
+ code = resize_term(nlines, ncols);
+ result = curses_check_err(module, code, "resize_term", NULL);
if (!result)
return NULL;
if (!update_lines_cols(module)) {
@@ -4390,8 +4691,7 @@ _curses_start_color_impl(PyObject *module)
PyCursesStatefulInitialised(module);
if (start_color() == ERR) {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, "start_color() returned ERR");
+ curses_set_error(module, "start_color", NULL);
return NULL;
}
@@ -4543,8 +4843,7 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3,
result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9);
if (!result) {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, "tparm() returned NULL");
+ curses_set_null_error(module, "tparm", NULL);
return NULL;
}
@@ -4570,7 +4869,7 @@ _curses_typeahead_impl(PyObject *module, int fd)
{
PyCursesStatefulInitialised(module);
- return PyCursesCheckERR(module, typeahead( fd ), "typeahead");
+ return curses_check_err(module, typeahead(fd), "typeahead", NULL);
}
#endif
@@ -4597,7 +4896,12 @@ _curses_unctrl(PyObject *module, PyObject *ch)
if (!PyCurses_ConvertToChtype(NULL, ch, &ch_))
return NULL;
- return PyBytes_FromString(unctrl(ch_));
+ const char *res = unctrl(ch_);
+ if (res == NULL) {
+ curses_set_null_error(module, "unctrl", NULL);
+ return NULL;
+ }
+ return PyBytes_FromString(res);
}
/*[clinic input]
@@ -4620,7 +4924,7 @@ _curses_ungetch(PyObject *module, PyObject *ch)
if (!PyCurses_ConvertToChtype(NULL, ch, &ch_))
return NULL;
- return PyCursesCheckERR(module, ungetch(ch_), "ungetch");
+ return curses_check_err(module, ungetch(ch_), "ungetch", NULL);
}
#ifdef HAVE_NCURSESW
@@ -4690,7 +4994,7 @@ _curses_unget_wch(PyObject *module, PyObject *ch)
if (!PyCurses_ConvertToWchar_t(ch, &wch))
return NULL;
- return PyCursesCheckERR(module, unget_wch(wch), "unget_wch");
+ return curses_check_err(module, unget_wch(wch), "unget_wch", NULL);
}
#endif
@@ -4739,13 +5043,7 @@ _curses_use_default_colors_impl(PyObject *module)
PyCursesStatefulInitialisedColor(module);
code = use_default_colors();
- if (code != ERR) {
- Py_RETURN_NONE;
- } else {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, "use_default_colors() returned ERR");
- return NULL;
- }
+ return curses_check_err(module, code, "use_default_colors", NULL);
}
/*[clinic input]
@@ -4772,13 +5070,7 @@ _curses_assume_default_colors_impl(PyObject *module, int fg, int bg)
PyCursesStatefulInitialisedColor(module);
code = assume_default_colors(fg, bg);
- if (code != ERR) {
- Py_RETURN_NONE;
- } else {
- cursesmodule_state *state = get_cursesmodule_state(module);
- PyErr_SetString(state->error, "assume_default_colors() returned ERR");
- return NULL;
- }
+ return curses_check_err(module, code, "assume_default_colors", NULL);
}
#endif /* STRICT_SYSV_CURSES */
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 9bba0e3354b..eb90be81c8d 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -1088,6 +1088,7 @@ parse_isoformat_time(const char *dtstr, size_t dtlen, int *hour, int *minute,
// -3: Failed to parse time component
// -4: Failed to parse time separator
// -5: Malformed timezone string
+ // -6: Timezone fields are not in range
const char *p = dtstr;
const char *p_end = dtstr + dtlen;
@@ -1134,6 +1135,11 @@ parse_isoformat_time(const char *dtstr, size_t dtlen, int *hour, int *minute,
rv = parse_hh_mm_ss_ff(tzinfo_pos, p_end, &tzhour, &tzminute, &tzsecond,
tzmicrosecond);
+ // Check if timezone fields are in range
+ if (check_time_args(tzhour, tzminute, tzsecond, *tzmicrosecond, 0) < 0) {
+ return -6;
+ }
+
*tzoffset = tzsign * ((tzhour * 3600) + (tzminute * 60) + tzsecond);
*tzmicrosecond *= tzsign;
@@ -5039,6 +5045,9 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) {
&tzoffset, &tzimicrosecond);
if (rv < 0) {
+ if (rv == -6) {
+ goto error;
+ }
goto invalid_string_error;
}
@@ -5075,6 +5084,9 @@ invalid_iso_midnight:
invalid_string_error:
PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", tstr);
return NULL;
+
+error:
+ return NULL;
}
@@ -5539,8 +5551,9 @@ datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
time_t secs;
int us;
- if (_PyTime_AsTimevalTime_t(ts, &secs, &us, _PyTime_ROUND_FLOOR) < 0)
+ if (_PyTime_AsTimevalTime_t(ts, &secs, &us, _PyTime_ROUND_HALF_EVEN) < 0) {
return NULL;
+ }
assert(0 <= us && us <= 999999);
return datetime_from_timet_and_us(cls, f, secs, us, tzinfo);
@@ -5927,6 +5940,9 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr)
len -= (p - dt_ptr);
rv = parse_isoformat_time(p, len, &hour, &minute, &second,
&microsecond, &tzoffset, &tzusec);
+ if (rv == -6) {
+ goto error;
+ }
}
if (rv < 0) {
goto invalid_string_error;
diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c
index cc65cbd98d7..0cd0f043de4 100644
--- a/Modules/_dbmmodule.c
+++ b/Modules/_dbmmodule.c
@@ -69,6 +69,7 @@ typedef struct {
#include "clinic/_dbmmodule.c.h"
#define check_dbmobject_open(v, err) \
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED((v)) \
if ((v)->di_dbm == NULL) { \
PyErr_SetString(err, "DBM object has already been closed"); \
return NULL; \
@@ -116,7 +117,7 @@ dbm_dealloc(PyObject *self)
}
static Py_ssize_t
-dbm_length(PyObject *self)
+dbm_length_lock_held(PyObject *self)
{
dbmobject *dp = dbmobject_CAST(self);
_dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
@@ -138,8 +139,18 @@ dbm_length(PyObject *self)
return dp->di_size;
}
+static Py_ssize_t
+dbm_length(PyObject *self)
+{
+ Py_ssize_t result;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ result = dbm_length_lock_held(self);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
static int
-dbm_bool(PyObject *self)
+dbm_bool_lock_held(PyObject *self)
{
dbmobject *dp = dbmobject_CAST(self);
_dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
@@ -170,8 +181,18 @@ dbm_bool(PyObject *self)
return 1;
}
+static int
+dbm_bool(PyObject *self)
+{
+ int result;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ result = dbm_bool_lock_held(self);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
static PyObject *
-dbm_subscript(PyObject *self, PyObject *key)
+dbm_subscript_lock_held(PyObject *self, PyObject *key)
{
datum drec, krec;
Py_ssize_t tmp_size;
@@ -197,8 +218,18 @@ dbm_subscript(PyObject *self, PyObject *key)
return PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
}
+static PyObject *
+dbm_subscript(PyObject *self, PyObject *key)
+{
+ PyObject *result;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ result = dbm_subscript_lock_held(self, key);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
static int
-dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
+dbm_ass_sub_lock_held(PyObject *self, PyObject *v, PyObject *w)
{
datum krec, drec;
Py_ssize_t tmp_size;
@@ -252,7 +283,18 @@ dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
return 0;
}
+static int
+dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
+{
+ int result;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ result = dbm_ass_sub_lock_held(self, v, w);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
/*[clinic input]
+@critical_section
_dbm.dbm.close
Close the database.
@@ -260,7 +302,7 @@ Close the database.
static PyObject *
_dbm_dbm_close_impl(dbmobject *self)
-/*[clinic end generated code: output=c8dc5b6709600b86 input=046db72377d51be8]*/
+/*[clinic end generated code: output=c8dc5b6709600b86 input=4a94f79facbc28ca]*/
{
if (self->di_dbm) {
dbm_close(self->di_dbm);
@@ -270,6 +312,7 @@ _dbm_dbm_close_impl(dbmobject *self)
}
/*[clinic input]
+@critical_section
_dbm.dbm.keys
cls: defining_class
@@ -279,7 +322,7 @@ Return a list of all keys in the database.
static PyObject *
_dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=f2a593b3038e5996 input=d3706a28fc051097]*/
+/*[clinic end generated code: output=f2a593b3038e5996 input=6ddefeadf2a80156]*/
{
PyObject *v, *item;
datum key;
@@ -310,7 +353,7 @@ _dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls)
}
static int
-dbm_contains(PyObject *self, PyObject *arg)
+dbm_contains_lock_held(PyObject *self, PyObject *arg)
{
dbmobject *dp = dbmobject_CAST(self);
datum key, val;
@@ -343,7 +386,18 @@ dbm_contains(PyObject *self, PyObject *arg)
return val.dptr != NULL;
}
+static int
+dbm_contains(PyObject *self, PyObject *arg)
+{
+ int result;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ result = dbm_contains_lock_held(self, arg);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
/*[clinic input]
+@critical_section
_dbm.dbm.get
cls: defining_class
key: str(accept={str, robuffer}, zeroes=True)
@@ -356,7 +410,7 @@ Return the value for key if present, otherwise default.
static PyObject *
_dbm_dbm_get_impl(dbmobject *self, PyTypeObject *cls, const char *key,
Py_ssize_t key_length, PyObject *default_value)
-/*[clinic end generated code: output=b4e55f8b6d482bc4 input=66b993b8349fa8c1]*/
+/*[clinic end generated code: output=b4e55f8b6d482bc4 input=1d88a22bb5e55202]*/
{
datum dbm_key, val;
_dbm_state *state = PyType_GetModuleState(cls);
@@ -373,6 +427,7 @@ _dbm_dbm_get_impl(dbmobject *self, PyTypeObject *cls, const char *key,
}
/*[clinic input]
+@critical_section
_dbm.dbm.setdefault
cls: defining_class
key: str(accept={str, robuffer}, zeroes=True)
@@ -387,7 +442,7 @@ If key is not in the database, it is inserted with default as the value.
static PyObject *
_dbm_dbm_setdefault_impl(dbmobject *self, PyTypeObject *cls, const char *key,
Py_ssize_t key_length, PyObject *default_value)
-/*[clinic end generated code: output=9c2f6ea6d0fb576c input=126a3ff15c5f8232]*/
+/*[clinic end generated code: output=9c2f6ea6d0fb576c input=c01510ef7571e13b]*/
{
datum dbm_key, val;
Py_ssize_t tmp_size;
@@ -427,6 +482,7 @@ _dbm_dbm_setdefault_impl(dbmobject *self, PyTypeObject *cls, const char *key,
}
/*[clinic input]
+@critical_section
_dbm.dbm.clear
cls: defining_class
/
@@ -436,7 +492,7 @@ Remove all items from the database.
static PyObject *
_dbm_dbm_clear_impl(dbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=8d126b9e1d01a434 input=43aa6ca1acb7f5f5]*/
+/*[clinic end generated code: output=8d126b9e1d01a434 input=a1aa5d99adfb9656]*/
{
_dbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c
index 8c3efa36353..fe24629f9f6 100644
--- a/Modules/_elementtree.c
+++ b/Modules/_elementtree.c
@@ -811,6 +811,8 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
PyTypeObject *tp = Py_TYPE(self);
elementtreestate *st = get_elementtree_state_by_type(tp);
+ // The deepcopy() helper takes care of incrementing the refcount
+ // of the object to copy so to avoid use-after-frees.
tag = deepcopy(st, self->tag, memo);
if (!tag)
return NULL;
@@ -845,11 +847,13 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
assert(!element->extra || !element->extra->length);
if (self->extra) {
- if (element_resize(element, self->extra->length) < 0)
+ Py_ssize_t expected_count = self->extra->length;
+ if (element_resize(element, expected_count) < 0) {
+ assert(!element->extra->length);
goto error;
+ }
- // TODO(picnixz): check for an evil child's __deepcopy__ on 'self'
- for (i = 0; i < self->extra->length; i++) {
+ for (i = 0; self->extra && i < self->extra->length; i++) {
PyObject* child = deepcopy(st, self->extra->children[i], memo);
if (!child || !Element_Check(st, child)) {
if (child) {
@@ -859,11 +863,24 @@ _elementtree_Element___deepcopy___impl(ElementObject *self, PyObject *memo)
element->extra->length = i;
goto error;
}
+ if (self->extra && expected_count != self->extra->length) {
+ // 'self->extra' got mutated and 'element' may not have
+ // sufficient space to hold the next iteration's item.
+ expected_count = self->extra->length;
+ if (element_resize(element, expected_count) < 0) {
+ Py_DECREF(child);
+ element->extra->length = i;
+ goto error;
+ }
+ }
element->extra->children[i] = child;
}
assert(!element->extra->length);
- element->extra->length = self->extra->length;
+ // The original 'self->extra' may be gone at this point if deepcopy()
+ // has side-effects. However, 'i' is the number of copied items that
+ // we were able to successfully copy.
+ element->extra->length = i;
}
/* add object to memo dictionary (so deepcopy won't visit it again) */
@@ -906,13 +923,20 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
break;
}
}
- if (simple)
+ if (simple) {
return PyDict_Copy(object);
+ }
/* Fall through to general case */
}
else if (Element_CheckExact(st, object)) {
- return _elementtree_Element___deepcopy___impl(
+ // The __deepcopy__() call may call arbitrary code even if the
+ // object to copy is a built-in XML element (one of its children
+ // any of its parents in its own __deepcopy__() implementation).
+ Py_INCREF(object);
+ PyObject *res = _elementtree_Element___deepcopy___impl(
(ElementObject *)object, memo);
+ Py_DECREF(object);
+ return res;
}
}
@@ -923,8 +947,11 @@ deepcopy(elementtreestate *st, PyObject *object, PyObject *memo)
return NULL;
}
+ Py_INCREF(object);
PyObject *args[2] = {object, memo};
- return PyObject_Vectorcall(st->deepcopy_obj, args, 2, NULL);
+ PyObject *res = PyObject_Vectorcall(st->deepcopy_obj, args, 2, NULL);
+ Py_DECREF(object);
+ return res;
}
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 899eef50ecc..354dbad84b5 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -1383,8 +1383,8 @@ bounded_lru_cache_update_lock_held(lru_cache_object *self,
this same key, then this setitem call will update the cache dict
with this new link, leaving the old link as an orphan (i.e. not
having a cache dict entry that refers to it). */
- if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
- hash) < 0) {
+ if (_PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)self->cache, key,
+ (PyObject *)link, hash) < 0) {
Py_DECREF(link);
return NULL;
}
@@ -1453,8 +1453,8 @@ bounded_lru_cache_update_lock_held(lru_cache_object *self,
for successful insertion in the cache dict before adding the
link to the linked list. Otherwise, the potentially reentrant
__eq__ call could cause the then orphan link to be visited. */
- if (_PyDict_SetItem_KnownHash(self->cache, key, (PyObject *)link,
- hash) < 0) {
+ if (_PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)self->cache, key,
+ (PyObject *)link, hash) < 0) {
/* Somehow the cache dict update failed. We no longer can
restore the old link. Let the error propagate upward and
leave the cache short one link. */
@@ -1689,7 +1689,13 @@ _functools__lru_cache_wrapper_cache_clear_impl(PyObject *self)
lru_list_elem *list = lru_cache_unlink_list(_self);
FT_ATOMIC_STORE_SSIZE_RELAXED(_self->hits, 0);
FT_ATOMIC_STORE_SSIZE_RELAXED(_self->misses, 0);
- PyDict_Clear(_self->cache);
+ if (_self->wrapper == bounded_lru_cache_wrapper) {
+ /* The critical section on the lru cache itself protects the dictionary
+ for bounded_lru_cache instances. */
+ _PyDict_Clear_LockHeld(_self->cache);
+ } else {
+ PyDict_Clear(_self->cache);
+ }
lru_cache_clear_list(list);
Py_RETURN_NONE;
}
diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c
index ab2ebdba924..9c402e20e51 100644
--- a/Modules/_gdbmmodule.c
+++ b/Modules/_gdbmmodule.c
@@ -81,6 +81,7 @@ typedef struct {
#include "clinic/_gdbmmodule.c.h"
#define check_gdbmobject_open(v, err) \
+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED((v)) \
if ((v)->di_dbm == NULL) { \
PyErr_SetString(err, "GDBM object has already been closed"); \
return NULL; \
@@ -142,7 +143,7 @@ gdbm_dealloc(PyObject *op)
}
static Py_ssize_t
-gdbm_length(PyObject *op)
+gdbm_length_lock_held(PyObject *op)
{
gdbmobject *dp = _gdbmobject_CAST(op);
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
@@ -188,8 +189,18 @@ gdbm_length(PyObject *op)
return dp->di_size;
}
+static Py_ssize_t
+gdbm_length(PyObject *op)
+{
+ Py_ssize_t result;
+ Py_BEGIN_CRITICAL_SECTION(op);
+ result = gdbm_length_lock_held(op);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
static int
-gdbm_bool(PyObject *op)
+gdbm_bool_lock_held(PyObject *op)
{
gdbmobject *dp = _gdbmobject_CAST(op);
_gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
@@ -218,6 +229,16 @@ gdbm_bool(PyObject *op)
return 1;
}
+static int
+gdbm_bool(PyObject *op)
+{
+ int result;
+ Py_BEGIN_CRITICAL_SECTION(op);
+ result = gdbm_bool_lock_held(op);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
// Wrapper function for PyArg_Parse(o, "s#", &d.dptr, &d.size).
// This function is needed to support PY_SSIZE_T_CLEAN.
// Return 1 on success, same to PyArg_Parse().
@@ -240,7 +261,7 @@ parse_datum(PyObject *o, datum *d, const char *failmsg)
}
static PyObject *
-gdbm_subscript(PyObject *op, PyObject *key)
+gdbm_subscript_lock_held(PyObject *op, PyObject *key)
{
PyObject *v;
datum drec, krec;
@@ -265,6 +286,16 @@ gdbm_subscript(PyObject *op, PyObject *key)
return v;
}
+static PyObject *
+gdbm_subscript(PyObject *op, PyObject *key)
+{
+ PyObject *result;
+ Py_BEGIN_CRITICAL_SECTION(op);
+ result = gdbm_subscript_lock_held(op, key);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
/*[clinic input]
_gdbm.gdbm.get
@@ -290,7 +321,7 @@ _gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, PyObject *default_value)
}
static int
-gdbm_ass_sub(PyObject *op, PyObject *v, PyObject *w)
+gdbm_ass_sub_lock_held(PyObject *op, PyObject *v, PyObject *w)
{
datum krec, drec;
const char *failmsg = "gdbm mappings have bytes or string indices only";
@@ -335,7 +366,18 @@ gdbm_ass_sub(PyObject *op, PyObject *v, PyObject *w)
return 0;
}
+static int
+gdbm_ass_sub(PyObject *op, PyObject *v, PyObject *w)
+{
+ int result;
+ Py_BEGIN_CRITICAL_SECTION(op);
+ result = gdbm_ass_sub_lock_held(op, v, w);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
/*[clinic input]
+@critical_section
_gdbm.gdbm.setdefault
key: object
@@ -348,7 +390,7 @@ Get value for key, or set it to default and return default if not present.
static PyObject *
_gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
PyObject *default_value)
-/*[clinic end generated code: output=f3246e880509f142 input=0db46b69e9680171]*/
+/*[clinic end generated code: output=f3246e880509f142 input=854374cd81ab51b6]*/
{
PyObject *res;
@@ -363,6 +405,7 @@ _gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
}
/*[clinic input]
+@critical_section
_gdbm.gdbm.close
Close the database.
@@ -370,7 +413,7 @@ Close the database.
static PyObject *
_gdbm_gdbm_close_impl(gdbmobject *self)
-/*[clinic end generated code: output=f5abb4d6bb9e52d5 input=0a203447379b45fd]*/
+/*[clinic end generated code: output=f5abb4d6bb9e52d5 input=56b604f4e77f533d]*/
{
if (self->di_dbm) {
gdbm_close(self->di_dbm);
@@ -381,6 +424,7 @@ _gdbm_gdbm_close_impl(gdbmobject *self)
/* XXX Should return a set or a set view */
/*[clinic input]
+@critical_section
_gdbm.gdbm.keys
cls: defining_class
@@ -390,7 +434,7 @@ Get a list of all keys in the database.
static PyObject *
_gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=c24b824e81404755 input=1428b7c79703d7d5]*/
+/*[clinic end generated code: output=c24b824e81404755 input=785988b1ea8f77e0]*/
{
PyObject *v, *item;
datum key, nextkey;
@@ -432,7 +476,7 @@ _gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
}
static int
-gdbm_contains(PyObject *self, PyObject *arg)
+gdbm_contains_lock_held(PyObject *self, PyObject *arg)
{
gdbmobject *dp = (gdbmobject *)self;
datum key;
@@ -463,7 +507,18 @@ gdbm_contains(PyObject *self, PyObject *arg)
return gdbm_exists(dp->di_dbm, key);
}
+static int
+gdbm_contains(PyObject *self, PyObject *arg)
+{
+ int result;
+ Py_BEGIN_CRITICAL_SECTION(self);
+ result = gdbm_contains_lock_held(self, arg);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
+
/*[clinic input]
+@critical_section
_gdbm.gdbm.firstkey
cls: defining_class
@@ -477,7 +532,7 @@ hash values, and won't be sorted by the key values.
static PyObject *
_gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=139275e9c8b60827 input=ed8782a029a5d299]*/
+/*[clinic end generated code: output=139275e9c8b60827 input=aad5a7c886c542f5]*/
{
PyObject *v;
datum key;
@@ -497,6 +552,7 @@ _gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls)
}
/*[clinic input]
+@critical_section
_gdbm.gdbm.nextkey
cls: defining_class
@@ -517,7 +573,7 @@ to create a list in memory that contains them all:
static PyObject *
_gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
Py_ssize_t key_length)
-/*[clinic end generated code: output=c81a69300ef41766 input=365e297bc0b3db48]*/
+/*[clinic end generated code: output=c81a69300ef41766 input=181f1130d5bfeb1e]*/
{
PyObject *v;
datum dbm_key, nextkey;
@@ -539,6 +595,7 @@ _gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
}
/*[clinic input]
+@critical_section
_gdbm.gdbm.reorganize
cls: defining_class
@@ -554,7 +611,7 @@ kept and reused as new (key,value) pairs are added.
static PyObject *
_gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=d77c69e8e3dd644a input=e1359faeef844e46]*/
+/*[clinic end generated code: output=d77c69e8e3dd644a input=3e3ca0d2ea787861]*/
{
_gdbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
@@ -573,6 +630,7 @@ _gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls)
}
/*[clinic input]
+@critical_section
_gdbm.gdbm.sync
cls: defining_class
@@ -585,7 +643,7 @@ any unwritten data to be written to the disk.
static PyObject *
_gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=bb680a2035c3f592 input=3d749235f79b6f2a]*/
+/*[clinic end generated code: output=bb680a2035c3f592 input=6054385b071d238a]*/
{
_gdbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
@@ -595,6 +653,7 @@ _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
}
/*[clinic input]
+@critical_section
_gdbm.gdbm.clear
cls: defining_class
/
@@ -604,7 +663,7 @@ Remove all items from the database.
static PyObject *
_gdbm_gdbm_clear_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=673577c573318661 input=34136d52fcdd4210]*/
+/*[clinic end generated code: output=673577c573318661 input=b17467adfe62f23d]*/
{
_gdbm_state *state = PyType_GetModuleState(cls);
assert(state != NULL);
diff --git a/Modules/_hacl/Hacl_Hash_Blake2b.c b/Modules/_hacl/Hacl_Hash_Blake2b.c
index 21ab2b88c79..a5b75d61798 100644
--- a/Modules/_hacl/Hacl_Hash_Blake2b.c
+++ b/Modules/_hacl/Hacl_Hash_Blake2b.c
@@ -544,11 +544,9 @@ void Hacl_Hash_Blake2b_init(uint64_t *hash, uint32_t kk, uint32_t nn)
uint64_t x = r;
os[i] = x;);
tmp[0U] =
- (uint64_t)nn1
- ^
- ((uint64_t)kk1
- << 8U
- ^ ((uint64_t)p.fanout << 16U ^ ((uint64_t)p.depth << 24U ^ (uint64_t)p.leaf_length << 32U)));
+ (uint64_t)nn1 ^
+ ((uint64_t)kk1 << 8U ^
+ ((uint64_t)p.fanout << 16U ^ ((uint64_t)p.depth << 24U ^ (uint64_t)p.leaf_length << 32U)));
tmp[1U] = p.node_offset;
tmp[2U] = (uint64_t)p.node_depth ^ (uint64_t)p.inner_length << 8U;
tmp[3U] = 0ULL;
@@ -860,14 +858,10 @@ static Hacl_Hash_Blake2b_state_t
uint64_t x = r4;
os[i0] = x;);
tmp[0U] =
- (uint64_t)nn1
- ^
- ((uint64_t)kk2
- << 8U
- ^
- ((uint64_t)pv.fanout
- << 16U
- ^ ((uint64_t)pv.depth << 24U ^ (uint64_t)pv.leaf_length << 32U)));
+ (uint64_t)nn1 ^
+ ((uint64_t)kk2 << 8U ^
+ ((uint64_t)pv.fanout << 16U ^
+ ((uint64_t)pv.depth << 24U ^ (uint64_t)pv.leaf_length << 32U)));
tmp[1U] = pv.node_offset;
tmp[2U] = (uint64_t)pv.node_depth ^ (uint64_t)pv.inner_length << 8U;
tmp[3U] = 0ULL;
@@ -1059,11 +1053,9 @@ static void reset_raw(Hacl_Hash_Blake2b_state_t *state, Hacl_Hash_Blake2b_params
uint64_t x = r;
os[i0] = x;);
tmp[0U] =
- (uint64_t)nn1
- ^
- ((uint64_t)kk2
- << 8U
- ^ ((uint64_t)pv.fanout << 16U ^ ((uint64_t)pv.depth << 24U ^ (uint64_t)pv.leaf_length << 32U)));
+ (uint64_t)nn1 ^
+ ((uint64_t)kk2 << 8U ^
+ ((uint64_t)pv.fanout << 16U ^ ((uint64_t)pv.depth << 24U ^ (uint64_t)pv.leaf_length << 32U)));
tmp[1U] = pv.node_offset;
tmp[2U] = (uint64_t)pv.node_depth ^ (uint64_t)pv.inner_length << 8U;
tmp[3U] = 0ULL;
@@ -1200,8 +1192,7 @@ Hacl_Hash_Blake2b_update(Hacl_Hash_Blake2b_state_t *state, uint8_t *chunk, uint3
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2b_state_t){
.block_state = block_state1,
@@ -1265,8 +1256,7 @@ Hacl_Hash_Blake2b_update(Hacl_Hash_Blake2b_state_t *state, uint8_t *chunk, uint3
nb);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2b_state_t){
.block_state = block_state1,
@@ -1296,8 +1286,7 @@ Hacl_Hash_Blake2b_update(Hacl_Hash_Blake2b_state_t *state, uint8_t *chunk, uint3
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2b_state_t){
.block_state = block_state10,
@@ -1359,8 +1348,7 @@ Hacl_Hash_Blake2b_update(Hacl_Hash_Blake2b_state_t *state, uint8_t *chunk, uint3
nb);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2b_state_t){
.block_state = block_state1,
@@ -1690,14 +1678,10 @@ Hacl_Hash_Blake2b_hash_with_key_and_params(
uint64_t x = r;
os[i] = x;);
tmp[0U] =
- (uint64_t)nn
- ^
- ((uint64_t)kk
- << 8U
- ^
- ((uint64_t)params.fanout
- << 16U
- ^ ((uint64_t)params.depth << 24U ^ (uint64_t)params.leaf_length << 32U)));
+ (uint64_t)nn ^
+ ((uint64_t)kk << 8U ^
+ ((uint64_t)params.fanout << 16U ^
+ ((uint64_t)params.depth << 24U ^ (uint64_t)params.leaf_length << 32U)));
tmp[1U] = params.node_offset;
tmp[2U] = (uint64_t)params.node_depth ^ (uint64_t)params.inner_length << 8U;
tmp[3U] = 0ULL;
diff --git a/Modules/_hacl/Hacl_Hash_Blake2b_Simd256.c b/Modules/_hacl/Hacl_Hash_Blake2b_Simd256.c
index c4d9b4a689d..f955f1c6115 100644
--- a/Modules/_hacl/Hacl_Hash_Blake2b_Simd256.c
+++ b/Modules/_hacl/Hacl_Hash_Blake2b_Simd256.c
@@ -274,11 +274,9 @@ Hacl_Hash_Blake2b_Simd256_init(Lib_IntVector_Intrinsics_vec256 *hash, uint32_t k
uint64_t x = r;
os[i] = x;);
tmp[0U] =
- (uint64_t)nn1
- ^
- ((uint64_t)kk1
- << 8U
- ^ ((uint64_t)p.fanout << 16U ^ ((uint64_t)p.depth << 24U ^ (uint64_t)p.leaf_length << 32U)));
+ (uint64_t)nn1 ^
+ ((uint64_t)kk1 << 8U ^
+ ((uint64_t)p.fanout << 16U ^ ((uint64_t)p.depth << 24U ^ (uint64_t)p.leaf_length << 32U)));
tmp[1U] = p.node_offset;
tmp[2U] = (uint64_t)p.node_depth ^ (uint64_t)p.inner_length << 8U;
tmp[3U] = 0ULL;
@@ -746,14 +744,10 @@ static Hacl_Hash_Blake2b_Simd256_state_t
uint64_t x = r4;
os[i0] = x;);
tmp[0U] =
- (uint64_t)nn1
- ^
- ((uint64_t)kk2
- << 8U
- ^
- ((uint64_t)pv.fanout
- << 16U
- ^ ((uint64_t)pv.depth << 24U ^ (uint64_t)pv.leaf_length << 32U)));
+ (uint64_t)nn1 ^
+ ((uint64_t)kk2 << 8U ^
+ ((uint64_t)pv.fanout << 16U ^
+ ((uint64_t)pv.depth << 24U ^ (uint64_t)pv.leaf_length << 32U)));
tmp[1U] = pv.node_offset;
tmp[2U] = (uint64_t)pv.node_depth ^ (uint64_t)pv.inner_length << 8U;
tmp[3U] = 0ULL;
@@ -936,11 +930,9 @@ reset_raw(Hacl_Hash_Blake2b_Simd256_state_t *state, Hacl_Hash_Blake2b_params_and
uint64_t x = r;
os[i0] = x;);
tmp[0U] =
- (uint64_t)nn1
- ^
- ((uint64_t)kk2
- << 8U
- ^ ((uint64_t)pv.fanout << 16U ^ ((uint64_t)pv.depth << 24U ^ (uint64_t)pv.leaf_length << 32U)));
+ (uint64_t)nn1 ^
+ ((uint64_t)kk2 << 8U ^
+ ((uint64_t)pv.fanout << 16U ^ ((uint64_t)pv.depth << 24U ^ (uint64_t)pv.leaf_length << 32U)));
tmp[1U] = pv.node_offset;
tmp[2U] = (uint64_t)pv.node_depth ^ (uint64_t)pv.inner_length << 8U;
tmp[3U] = 0ULL;
@@ -1075,8 +1067,7 @@ Hacl_Hash_Blake2b_Simd256_update(
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2b_Simd256_state_t){
.block_state = block_state1,
@@ -1140,8 +1131,7 @@ Hacl_Hash_Blake2b_Simd256_update(
nb);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2b_Simd256_state_t){
.block_state = block_state1,
@@ -1171,8 +1161,7 @@ Hacl_Hash_Blake2b_Simd256_update(
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2b_Simd256_state_t){
.block_state = block_state10,
@@ -1234,8 +1223,7 @@ Hacl_Hash_Blake2b_Simd256_update(
nb);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2b_Simd256_state_t){
.block_state = block_state1,
@@ -1578,14 +1566,10 @@ Hacl_Hash_Blake2b_Simd256_hash_with_key_and_params(
uint64_t x = r;
os[i] = x;);
tmp[0U] =
- (uint64_t)nn
- ^
- ((uint64_t)kk
- << 8U
- ^
- ((uint64_t)params.fanout
- << 16U
- ^ ((uint64_t)params.depth << 24U ^ (uint64_t)params.leaf_length << 32U)));
+ (uint64_t)nn ^
+ ((uint64_t)kk << 8U ^
+ ((uint64_t)params.fanout << 16U ^
+ ((uint64_t)params.depth << 24U ^ (uint64_t)params.leaf_length << 32U)));
tmp[1U] = params.node_offset;
tmp[2U] = (uint64_t)params.node_depth ^ (uint64_t)params.inner_length << 8U;
tmp[3U] = 0ULL;
diff --git a/Modules/_hacl/Hacl_Hash_Blake2s.c b/Modules/_hacl/Hacl_Hash_Blake2s.c
index 730ba135afb..0d4fcc7f395 100644
--- a/Modules/_hacl/Hacl_Hash_Blake2s.c
+++ b/Modules/_hacl/Hacl_Hash_Blake2s.c
@@ -543,13 +543,13 @@ void Hacl_Hash_Blake2s_init(uint32_t *hash, uint32_t kk, uint32_t nn)
uint32_t x = r;
os[i] = x;);
tmp[0U] =
- (uint32_t)(uint8_t)nn
- ^ ((uint32_t)(uint8_t)kk << 8U ^ ((uint32_t)p.fanout << 16U ^ (uint32_t)p.depth << 24U));
+ (uint32_t)(uint8_t)nn ^
+ ((uint32_t)(uint8_t)kk << 8U ^ ((uint32_t)p.fanout << 16U ^ (uint32_t)p.depth << 24U));
tmp[1U] = p.leaf_length;
tmp[2U] = (uint32_t)p.node_offset;
tmp[3U] =
- (uint32_t)(p.node_offset >> 32U)
- ^ ((uint32_t)p.node_depth << 16U ^ (uint32_t)p.inner_length << 24U);
+ (uint32_t)(p.node_offset >> 32U) ^
+ ((uint32_t)p.node_depth << 16U ^ (uint32_t)p.inner_length << 24U);
uint32_t tmp0 = tmp[0U];
uint32_t tmp1 = tmp[1U];
uint32_t tmp2 = tmp[2U];
@@ -846,16 +846,14 @@ static Hacl_Hash_Blake2s_state_t
uint32_t x = r4;
os[i0] = x;);
tmp[0U] =
- (uint32_t)pv.digest_length
- ^
- ((uint32_t)pv.key_length
- << 8U
- ^ ((uint32_t)pv.fanout << 16U ^ (uint32_t)pv.depth << 24U));
+ (uint32_t)pv.digest_length ^
+ ((uint32_t)pv.key_length << 8U ^
+ ((uint32_t)pv.fanout << 16U ^ (uint32_t)pv.depth << 24U));
tmp[1U] = pv.leaf_length;
tmp[2U] = (uint32_t)pv.node_offset;
tmp[3U] =
- (uint32_t)(pv.node_offset >> 32U)
- ^ ((uint32_t)pv.node_depth << 16U ^ (uint32_t)pv.inner_length << 24U);
+ (uint32_t)(pv.node_offset >> 32U) ^
+ ((uint32_t)pv.node_depth << 16U ^ (uint32_t)pv.inner_length << 24U);
uint32_t tmp0 = tmp[0U];
uint32_t tmp1 = tmp[1U];
uint32_t tmp2 = tmp[2U];
@@ -1042,13 +1040,13 @@ static void reset_raw(Hacl_Hash_Blake2s_state_t *state, Hacl_Hash_Blake2b_params
uint32_t x = r;
os[i0] = x;);
tmp[0U] =
- (uint32_t)pv.digest_length
- ^ ((uint32_t)pv.key_length << 8U ^ ((uint32_t)pv.fanout << 16U ^ (uint32_t)pv.depth << 24U));
+ (uint32_t)pv.digest_length ^
+ ((uint32_t)pv.key_length << 8U ^ ((uint32_t)pv.fanout << 16U ^ (uint32_t)pv.depth << 24U));
tmp[1U] = pv.leaf_length;
tmp[2U] = (uint32_t)pv.node_offset;
tmp[3U] =
- (uint32_t)(pv.node_offset >> 32U)
- ^ ((uint32_t)pv.node_depth << 16U ^ (uint32_t)pv.inner_length << 24U);
+ (uint32_t)(pv.node_offset >> 32U) ^
+ ((uint32_t)pv.node_depth << 16U ^ (uint32_t)pv.inner_length << 24U);
uint32_t tmp0 = tmp[0U];
uint32_t tmp1 = tmp[1U];
uint32_t tmp2 = tmp[2U];
@@ -1182,8 +1180,7 @@ Hacl_Hash_Blake2s_update(Hacl_Hash_Blake2s_state_t *state, uint8_t *chunk, uint3
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2s_state_t){
.block_state = block_state1,
@@ -1237,8 +1234,7 @@ Hacl_Hash_Blake2s_update(Hacl_Hash_Blake2s_state_t *state, uint8_t *chunk, uint3
Hacl_Hash_Blake2s_update_multi(data1_len, wv, hash, total_len1, data1, nb);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2s_state_t){
.block_state = block_state1,
@@ -1268,8 +1264,7 @@ Hacl_Hash_Blake2s_update(Hacl_Hash_Blake2s_state_t *state, uint8_t *chunk, uint3
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2s_state_t){
.block_state = block_state10,
@@ -1321,8 +1316,7 @@ Hacl_Hash_Blake2s_update(Hacl_Hash_Blake2s_state_t *state, uint8_t *chunk, uint3
Hacl_Hash_Blake2s_update_multi(data1_len, wv, hash, total_len1, data1, nb);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2s_state_t){
.block_state = block_state1,
@@ -1639,16 +1633,14 @@ Hacl_Hash_Blake2s_hash_with_key_and_params(
uint32_t x = r;
os[i] = x;);
tmp[0U] =
- (uint32_t)params.digest_length
- ^
- ((uint32_t)params.key_length
- << 8U
- ^ ((uint32_t)params.fanout << 16U ^ (uint32_t)params.depth << 24U));
+ (uint32_t)params.digest_length ^
+ ((uint32_t)params.key_length << 8U ^
+ ((uint32_t)params.fanout << 16U ^ (uint32_t)params.depth << 24U));
tmp[1U] = params.leaf_length;
tmp[2U] = (uint32_t)params.node_offset;
tmp[3U] =
- (uint32_t)(params.node_offset >> 32U)
- ^ ((uint32_t)params.node_depth << 16U ^ (uint32_t)params.inner_length << 24U);
+ (uint32_t)(params.node_offset >> 32U) ^
+ ((uint32_t)params.node_depth << 16U ^ (uint32_t)params.inner_length << 24U);
uint32_t tmp0 = tmp[0U];
uint32_t tmp1 = tmp[1U];
uint32_t tmp2 = tmp[2U];
diff --git a/Modules/_hacl/Hacl_Hash_Blake2s_Simd128.c b/Modules/_hacl/Hacl_Hash_Blake2s_Simd128.c
index 7e9cd79544f..fa46be045f3 100644
--- a/Modules/_hacl/Hacl_Hash_Blake2s_Simd128.c
+++ b/Modules/_hacl/Hacl_Hash_Blake2s_Simd128.c
@@ -271,13 +271,13 @@ Hacl_Hash_Blake2s_Simd128_init(Lib_IntVector_Intrinsics_vec128 *hash, uint32_t k
uint32_t x = r;
os[i] = x;);
tmp[0U] =
- (uint32_t)(uint8_t)nn
- ^ ((uint32_t)(uint8_t)kk << 8U ^ ((uint32_t)p.fanout << 16U ^ (uint32_t)p.depth << 24U));
+ (uint32_t)(uint8_t)nn ^
+ ((uint32_t)(uint8_t)kk << 8U ^ ((uint32_t)p.fanout << 16U ^ (uint32_t)p.depth << 24U));
tmp[1U] = p.leaf_length;
tmp[2U] = (uint32_t)p.node_offset;
tmp[3U] =
- (uint32_t)(p.node_offset >> 32U)
- ^ ((uint32_t)p.node_depth << 16U ^ (uint32_t)p.inner_length << 24U);
+ (uint32_t)(p.node_offset >> 32U) ^
+ ((uint32_t)p.node_depth << 16U ^ (uint32_t)p.inner_length << 24U);
uint32_t tmp0 = tmp[0U];
uint32_t tmp1 = tmp[1U];
uint32_t tmp2 = tmp[2U];
@@ -736,16 +736,14 @@ static Hacl_Hash_Blake2s_Simd128_state_t
uint32_t x = r4;
os[i0] = x;);
tmp[0U] =
- (uint32_t)pv.digest_length
- ^
- ((uint32_t)pv.key_length
- << 8U
- ^ ((uint32_t)pv.fanout << 16U ^ (uint32_t)pv.depth << 24U));
+ (uint32_t)pv.digest_length ^
+ ((uint32_t)pv.key_length << 8U ^
+ ((uint32_t)pv.fanout << 16U ^ (uint32_t)pv.depth << 24U));
tmp[1U] = pv.leaf_length;
tmp[2U] = (uint32_t)pv.node_offset;
tmp[3U] =
- (uint32_t)(pv.node_offset >> 32U)
- ^ ((uint32_t)pv.node_depth << 16U ^ (uint32_t)pv.inner_length << 24U);
+ (uint32_t)(pv.node_offset >> 32U) ^
+ ((uint32_t)pv.node_depth << 16U ^ (uint32_t)pv.inner_length << 24U);
uint32_t tmp0 = tmp[0U];
uint32_t tmp1 = tmp[1U];
uint32_t tmp2 = tmp[2U];
@@ -923,13 +921,13 @@ reset_raw(Hacl_Hash_Blake2s_Simd128_state_t *state, Hacl_Hash_Blake2b_params_and
uint32_t x = r;
os[i0] = x;);
tmp[0U] =
- (uint32_t)pv.digest_length
- ^ ((uint32_t)pv.key_length << 8U ^ ((uint32_t)pv.fanout << 16U ^ (uint32_t)pv.depth << 24U));
+ (uint32_t)pv.digest_length ^
+ ((uint32_t)pv.key_length << 8U ^ ((uint32_t)pv.fanout << 16U ^ (uint32_t)pv.depth << 24U));
tmp[1U] = pv.leaf_length;
tmp[2U] = (uint32_t)pv.node_offset;
tmp[3U] =
- (uint32_t)(pv.node_offset >> 32U)
- ^ ((uint32_t)pv.node_depth << 16U ^ (uint32_t)pv.inner_length << 24U);
+ (uint32_t)(pv.node_offset >> 32U) ^
+ ((uint32_t)pv.node_depth << 16U ^ (uint32_t)pv.inner_length << 24U);
uint32_t tmp0 = tmp[0U];
uint32_t tmp1 = tmp[1U];
uint32_t tmp2 = tmp[2U];
@@ -1061,8 +1059,7 @@ Hacl_Hash_Blake2s_Simd128_update(
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2s_Simd128_state_t){
.block_state = block_state1,
@@ -1116,8 +1113,7 @@ Hacl_Hash_Blake2s_Simd128_update(
Hacl_Hash_Blake2s_Simd128_update_multi(data1_len, wv, hash, total_len1, data1, nb);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2s_Simd128_state_t){
.block_state = block_state1,
@@ -1147,8 +1143,7 @@ Hacl_Hash_Blake2s_Simd128_update(
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2s_Simd128_state_t){
.block_state = block_state10,
@@ -1200,8 +1195,7 @@ Hacl_Hash_Blake2s_Simd128_update(
Hacl_Hash_Blake2s_Simd128_update_multi(data1_len, wv, hash, total_len1, data1, nb);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_Blake2s_Simd128_state_t){
.block_state = block_state1,
@@ -1531,16 +1525,14 @@ Hacl_Hash_Blake2s_Simd128_hash_with_key_and_params(
uint32_t x = r;
os[i] = x;);
tmp[0U] =
- (uint32_t)params.digest_length
- ^
- ((uint32_t)params.key_length
- << 8U
- ^ ((uint32_t)params.fanout << 16U ^ (uint32_t)params.depth << 24U));
+ (uint32_t)params.digest_length ^
+ ((uint32_t)params.key_length << 8U ^
+ ((uint32_t)params.fanout << 16U ^ (uint32_t)params.depth << 24U));
tmp[1U] = params.leaf_length;
tmp[2U] = (uint32_t)params.node_offset;
tmp[3U] =
- (uint32_t)(params.node_offset >> 32U)
- ^ ((uint32_t)params.node_depth << 16U ^ (uint32_t)params.inner_length << 24U);
+ (uint32_t)(params.node_offset >> 32U) ^
+ ((uint32_t)params.node_depth << 16U ^ (uint32_t)params.inner_length << 24U);
uint32_t tmp0 = tmp[0U];
uint32_t tmp1 = tmp[1U];
uint32_t tmp2 = tmp[2U];
diff --git a/Modules/_hacl/Hacl_Hash_MD5.c b/Modules/_hacl/Hacl_Hash_MD5.c
index 75ce8d2926e..305c75483c0 100644
--- a/Modules/_hacl/Hacl_Hash_MD5.c
+++ b/Modules/_hacl/Hacl_Hash_MD5.c
@@ -66,11 +66,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti0 = _t[0U];
uint32_t
v =
- vb0
- +
- ((va + ((vb0 & vc0) | (~vb0 & vd0)) + xk + ti0)
- << 7U
- | (va + ((vb0 & vc0) | (~vb0 & vd0)) + xk + ti0) >> 25U);
+ vb0 +
+ ((va + ((vb0 & vc0) | (~vb0 & vd0)) + xk + ti0) << 7U |
+ (va + ((vb0 & vc0) | (~vb0 & vd0)) + xk + ti0) >> 25U);
abcd[0U] = v;
uint32_t va0 = abcd[3U];
uint32_t vb1 = abcd[0U];
@@ -82,11 +80,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti1 = _t[1U];
uint32_t
v0 =
- vb1
- +
- ((va0 + ((vb1 & vc1) | (~vb1 & vd1)) + xk0 + ti1)
- << 12U
- | (va0 + ((vb1 & vc1) | (~vb1 & vd1)) + xk0 + ti1) >> 20U);
+ vb1 +
+ ((va0 + ((vb1 & vc1) | (~vb1 & vd1)) + xk0 + ti1) << 12U |
+ (va0 + ((vb1 & vc1) | (~vb1 & vd1)) + xk0 + ti1) >> 20U);
abcd[3U] = v0;
uint32_t va1 = abcd[2U];
uint32_t vb2 = abcd[3U];
@@ -98,11 +94,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti2 = _t[2U];
uint32_t
v1 =
- vb2
- +
- ((va1 + ((vb2 & vc2) | (~vb2 & vd2)) + xk1 + ti2)
- << 17U
- | (va1 + ((vb2 & vc2) | (~vb2 & vd2)) + xk1 + ti2) >> 15U);
+ vb2 +
+ ((va1 + ((vb2 & vc2) | (~vb2 & vd2)) + xk1 + ti2) << 17U |
+ (va1 + ((vb2 & vc2) | (~vb2 & vd2)) + xk1 + ti2) >> 15U);
abcd[2U] = v1;
uint32_t va2 = abcd[1U];
uint32_t vb3 = abcd[2U];
@@ -114,11 +108,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti3 = _t[3U];
uint32_t
v2 =
- vb3
- +
- ((va2 + ((vb3 & vc3) | (~vb3 & vd3)) + xk2 + ti3)
- << 22U
- | (va2 + ((vb3 & vc3) | (~vb3 & vd3)) + xk2 + ti3) >> 10U);
+ vb3 +
+ ((va2 + ((vb3 & vc3) | (~vb3 & vd3)) + xk2 + ti3) << 22U |
+ (va2 + ((vb3 & vc3) | (~vb3 & vd3)) + xk2 + ti3) >> 10U);
abcd[1U] = v2;
uint32_t va3 = abcd[0U];
uint32_t vb4 = abcd[1U];
@@ -130,11 +122,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti4 = _t[4U];
uint32_t
v3 =
- vb4
- +
- ((va3 + ((vb4 & vc4) | (~vb4 & vd4)) + xk3 + ti4)
- << 7U
- | (va3 + ((vb4 & vc4) | (~vb4 & vd4)) + xk3 + ti4) >> 25U);
+ vb4 +
+ ((va3 + ((vb4 & vc4) | (~vb4 & vd4)) + xk3 + ti4) << 7U |
+ (va3 + ((vb4 & vc4) | (~vb4 & vd4)) + xk3 + ti4) >> 25U);
abcd[0U] = v3;
uint32_t va4 = abcd[3U];
uint32_t vb5 = abcd[0U];
@@ -146,11 +136,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti5 = _t[5U];
uint32_t
v4 =
- vb5
- +
- ((va4 + ((vb5 & vc5) | (~vb5 & vd5)) + xk4 + ti5)
- << 12U
- | (va4 + ((vb5 & vc5) | (~vb5 & vd5)) + xk4 + ti5) >> 20U);
+ vb5 +
+ ((va4 + ((vb5 & vc5) | (~vb5 & vd5)) + xk4 + ti5) << 12U |
+ (va4 + ((vb5 & vc5) | (~vb5 & vd5)) + xk4 + ti5) >> 20U);
abcd[3U] = v4;
uint32_t va5 = abcd[2U];
uint32_t vb6 = abcd[3U];
@@ -162,11 +150,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti6 = _t[6U];
uint32_t
v5 =
- vb6
- +
- ((va5 + ((vb6 & vc6) | (~vb6 & vd6)) + xk5 + ti6)
- << 17U
- | (va5 + ((vb6 & vc6) | (~vb6 & vd6)) + xk5 + ti6) >> 15U);
+ vb6 +
+ ((va5 + ((vb6 & vc6) | (~vb6 & vd6)) + xk5 + ti6) << 17U |
+ (va5 + ((vb6 & vc6) | (~vb6 & vd6)) + xk5 + ti6) >> 15U);
abcd[2U] = v5;
uint32_t va6 = abcd[1U];
uint32_t vb7 = abcd[2U];
@@ -178,11 +164,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti7 = _t[7U];
uint32_t
v6 =
- vb7
- +
- ((va6 + ((vb7 & vc7) | (~vb7 & vd7)) + xk6 + ti7)
- << 22U
- | (va6 + ((vb7 & vc7) | (~vb7 & vd7)) + xk6 + ti7) >> 10U);
+ vb7 +
+ ((va6 + ((vb7 & vc7) | (~vb7 & vd7)) + xk6 + ti7) << 22U |
+ (va6 + ((vb7 & vc7) | (~vb7 & vd7)) + xk6 + ti7) >> 10U);
abcd[1U] = v6;
uint32_t va7 = abcd[0U];
uint32_t vb8 = abcd[1U];
@@ -194,11 +178,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti8 = _t[8U];
uint32_t
v7 =
- vb8
- +
- ((va7 + ((vb8 & vc8) | (~vb8 & vd8)) + xk7 + ti8)
- << 7U
- | (va7 + ((vb8 & vc8) | (~vb8 & vd8)) + xk7 + ti8) >> 25U);
+ vb8 +
+ ((va7 + ((vb8 & vc8) | (~vb8 & vd8)) + xk7 + ti8) << 7U |
+ (va7 + ((vb8 & vc8) | (~vb8 & vd8)) + xk7 + ti8) >> 25U);
abcd[0U] = v7;
uint32_t va8 = abcd[3U];
uint32_t vb9 = abcd[0U];
@@ -210,11 +192,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti9 = _t[9U];
uint32_t
v8 =
- vb9
- +
- ((va8 + ((vb9 & vc9) | (~vb9 & vd9)) + xk8 + ti9)
- << 12U
- | (va8 + ((vb9 & vc9) | (~vb9 & vd9)) + xk8 + ti9) >> 20U);
+ vb9 +
+ ((va8 + ((vb9 & vc9) | (~vb9 & vd9)) + xk8 + ti9) << 12U |
+ (va8 + ((vb9 & vc9) | (~vb9 & vd9)) + xk8 + ti9) >> 20U);
abcd[3U] = v8;
uint32_t va9 = abcd[2U];
uint32_t vb10 = abcd[3U];
@@ -226,11 +206,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti10 = _t[10U];
uint32_t
v9 =
- vb10
- +
- ((va9 + ((vb10 & vc10) | (~vb10 & vd10)) + xk9 + ti10)
- << 17U
- | (va9 + ((vb10 & vc10) | (~vb10 & vd10)) + xk9 + ti10) >> 15U);
+ vb10 +
+ ((va9 + ((vb10 & vc10) | (~vb10 & vd10)) + xk9 + ti10) << 17U |
+ (va9 + ((vb10 & vc10) | (~vb10 & vd10)) + xk9 + ti10) >> 15U);
abcd[2U] = v9;
uint32_t va10 = abcd[1U];
uint32_t vb11 = abcd[2U];
@@ -242,11 +220,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti11 = _t[11U];
uint32_t
v10 =
- vb11
- +
- ((va10 + ((vb11 & vc11) | (~vb11 & vd11)) + xk10 + ti11)
- << 22U
- | (va10 + ((vb11 & vc11) | (~vb11 & vd11)) + xk10 + ti11) >> 10U);
+ vb11 +
+ ((va10 + ((vb11 & vc11) | (~vb11 & vd11)) + xk10 + ti11) << 22U |
+ (va10 + ((vb11 & vc11) | (~vb11 & vd11)) + xk10 + ti11) >> 10U);
abcd[1U] = v10;
uint32_t va11 = abcd[0U];
uint32_t vb12 = abcd[1U];
@@ -258,11 +234,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti12 = _t[12U];
uint32_t
v11 =
- vb12
- +
- ((va11 + ((vb12 & vc12) | (~vb12 & vd12)) + xk11 + ti12)
- << 7U
- | (va11 + ((vb12 & vc12) | (~vb12 & vd12)) + xk11 + ti12) >> 25U);
+ vb12 +
+ ((va11 + ((vb12 & vc12) | (~vb12 & vd12)) + xk11 + ti12) << 7U |
+ (va11 + ((vb12 & vc12) | (~vb12 & vd12)) + xk11 + ti12) >> 25U);
abcd[0U] = v11;
uint32_t va12 = abcd[3U];
uint32_t vb13 = abcd[0U];
@@ -274,11 +248,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti13 = _t[13U];
uint32_t
v12 =
- vb13
- +
- ((va12 + ((vb13 & vc13) | (~vb13 & vd13)) + xk12 + ti13)
- << 12U
- | (va12 + ((vb13 & vc13) | (~vb13 & vd13)) + xk12 + ti13) >> 20U);
+ vb13 +
+ ((va12 + ((vb13 & vc13) | (~vb13 & vd13)) + xk12 + ti13) << 12U |
+ (va12 + ((vb13 & vc13) | (~vb13 & vd13)) + xk12 + ti13) >> 20U);
abcd[3U] = v12;
uint32_t va13 = abcd[2U];
uint32_t vb14 = abcd[3U];
@@ -290,11 +262,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti14 = _t[14U];
uint32_t
v13 =
- vb14
- +
- ((va13 + ((vb14 & vc14) | (~vb14 & vd14)) + xk13 + ti14)
- << 17U
- | (va13 + ((vb14 & vc14) | (~vb14 & vd14)) + xk13 + ti14) >> 15U);
+ vb14 +
+ ((va13 + ((vb14 & vc14) | (~vb14 & vd14)) + xk13 + ti14) << 17U |
+ (va13 + ((vb14 & vc14) | (~vb14 & vd14)) + xk13 + ti14) >> 15U);
abcd[2U] = v13;
uint32_t va14 = abcd[1U];
uint32_t vb15 = abcd[2U];
@@ -306,11 +276,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti15 = _t[15U];
uint32_t
v14 =
- vb15
- +
- ((va14 + ((vb15 & vc15) | (~vb15 & vd15)) + xk14 + ti15)
- << 22U
- | (va14 + ((vb15 & vc15) | (~vb15 & vd15)) + xk14 + ti15) >> 10U);
+ vb15 +
+ ((va14 + ((vb15 & vc15) | (~vb15 & vd15)) + xk14 + ti15) << 22U |
+ (va14 + ((vb15 & vc15) | (~vb15 & vd15)) + xk14 + ti15) >> 10U);
abcd[1U] = v14;
uint32_t va15 = abcd[0U];
uint32_t vb16 = abcd[1U];
@@ -322,11 +290,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti16 = _t[16U];
uint32_t
v15 =
- vb16
- +
- ((va15 + ((vb16 & vd16) | (vc16 & ~vd16)) + xk15 + ti16)
- << 5U
- | (va15 + ((vb16 & vd16) | (vc16 & ~vd16)) + xk15 + ti16) >> 27U);
+ vb16 +
+ ((va15 + ((vb16 & vd16) | (vc16 & ~vd16)) + xk15 + ti16) << 5U |
+ (va15 + ((vb16 & vd16) | (vc16 & ~vd16)) + xk15 + ti16) >> 27U);
abcd[0U] = v15;
uint32_t va16 = abcd[3U];
uint32_t vb17 = abcd[0U];
@@ -338,11 +304,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti17 = _t[17U];
uint32_t
v16 =
- vb17
- +
- ((va16 + ((vb17 & vd17) | (vc17 & ~vd17)) + xk16 + ti17)
- << 9U
- | (va16 + ((vb17 & vd17) | (vc17 & ~vd17)) + xk16 + ti17) >> 23U);
+ vb17 +
+ ((va16 + ((vb17 & vd17) | (vc17 & ~vd17)) + xk16 + ti17) << 9U |
+ (va16 + ((vb17 & vd17) | (vc17 & ~vd17)) + xk16 + ti17) >> 23U);
abcd[3U] = v16;
uint32_t va17 = abcd[2U];
uint32_t vb18 = abcd[3U];
@@ -354,11 +318,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti18 = _t[18U];
uint32_t
v17 =
- vb18
- +
- ((va17 + ((vb18 & vd18) | (vc18 & ~vd18)) + xk17 + ti18)
- << 14U
- | (va17 + ((vb18 & vd18) | (vc18 & ~vd18)) + xk17 + ti18) >> 18U);
+ vb18 +
+ ((va17 + ((vb18 & vd18) | (vc18 & ~vd18)) + xk17 + ti18) << 14U |
+ (va17 + ((vb18 & vd18) | (vc18 & ~vd18)) + xk17 + ti18) >> 18U);
abcd[2U] = v17;
uint32_t va18 = abcd[1U];
uint32_t vb19 = abcd[2U];
@@ -370,11 +332,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti19 = _t[19U];
uint32_t
v18 =
- vb19
- +
- ((va18 + ((vb19 & vd19) | (vc19 & ~vd19)) + xk18 + ti19)
- << 20U
- | (va18 + ((vb19 & vd19) | (vc19 & ~vd19)) + xk18 + ti19) >> 12U);
+ vb19 +
+ ((va18 + ((vb19 & vd19) | (vc19 & ~vd19)) + xk18 + ti19) << 20U |
+ (va18 + ((vb19 & vd19) | (vc19 & ~vd19)) + xk18 + ti19) >> 12U);
abcd[1U] = v18;
uint32_t va19 = abcd[0U];
uint32_t vb20 = abcd[1U];
@@ -386,11 +346,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti20 = _t[20U];
uint32_t
v19 =
- vb20
- +
- ((va19 + ((vb20 & vd20) | (vc20 & ~vd20)) + xk19 + ti20)
- << 5U
- | (va19 + ((vb20 & vd20) | (vc20 & ~vd20)) + xk19 + ti20) >> 27U);
+ vb20 +
+ ((va19 + ((vb20 & vd20) | (vc20 & ~vd20)) + xk19 + ti20) << 5U |
+ (va19 + ((vb20 & vd20) | (vc20 & ~vd20)) + xk19 + ti20) >> 27U);
abcd[0U] = v19;
uint32_t va20 = abcd[3U];
uint32_t vb21 = abcd[0U];
@@ -402,11 +360,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti21 = _t[21U];
uint32_t
v20 =
- vb21
- +
- ((va20 + ((vb21 & vd21) | (vc21 & ~vd21)) + xk20 + ti21)
- << 9U
- | (va20 + ((vb21 & vd21) | (vc21 & ~vd21)) + xk20 + ti21) >> 23U);
+ vb21 +
+ ((va20 + ((vb21 & vd21) | (vc21 & ~vd21)) + xk20 + ti21) << 9U |
+ (va20 + ((vb21 & vd21) | (vc21 & ~vd21)) + xk20 + ti21) >> 23U);
abcd[3U] = v20;
uint32_t va21 = abcd[2U];
uint32_t vb22 = abcd[3U];
@@ -418,11 +374,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti22 = _t[22U];
uint32_t
v21 =
- vb22
- +
- ((va21 + ((vb22 & vd22) | (vc22 & ~vd22)) + xk21 + ti22)
- << 14U
- | (va21 + ((vb22 & vd22) | (vc22 & ~vd22)) + xk21 + ti22) >> 18U);
+ vb22 +
+ ((va21 + ((vb22 & vd22) | (vc22 & ~vd22)) + xk21 + ti22) << 14U |
+ (va21 + ((vb22 & vd22) | (vc22 & ~vd22)) + xk21 + ti22) >> 18U);
abcd[2U] = v21;
uint32_t va22 = abcd[1U];
uint32_t vb23 = abcd[2U];
@@ -434,11 +388,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti23 = _t[23U];
uint32_t
v22 =
- vb23
- +
- ((va22 + ((vb23 & vd23) | (vc23 & ~vd23)) + xk22 + ti23)
- << 20U
- | (va22 + ((vb23 & vd23) | (vc23 & ~vd23)) + xk22 + ti23) >> 12U);
+ vb23 +
+ ((va22 + ((vb23 & vd23) | (vc23 & ~vd23)) + xk22 + ti23) << 20U |
+ (va22 + ((vb23 & vd23) | (vc23 & ~vd23)) + xk22 + ti23) >> 12U);
abcd[1U] = v22;
uint32_t va23 = abcd[0U];
uint32_t vb24 = abcd[1U];
@@ -450,11 +402,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti24 = _t[24U];
uint32_t
v23 =
- vb24
- +
- ((va23 + ((vb24 & vd24) | (vc24 & ~vd24)) + xk23 + ti24)
- << 5U
- | (va23 + ((vb24 & vd24) | (vc24 & ~vd24)) + xk23 + ti24) >> 27U);
+ vb24 +
+ ((va23 + ((vb24 & vd24) | (vc24 & ~vd24)) + xk23 + ti24) << 5U |
+ (va23 + ((vb24 & vd24) | (vc24 & ~vd24)) + xk23 + ti24) >> 27U);
abcd[0U] = v23;
uint32_t va24 = abcd[3U];
uint32_t vb25 = abcd[0U];
@@ -466,11 +416,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti25 = _t[25U];
uint32_t
v24 =
- vb25
- +
- ((va24 + ((vb25 & vd25) | (vc25 & ~vd25)) + xk24 + ti25)
- << 9U
- | (va24 + ((vb25 & vd25) | (vc25 & ~vd25)) + xk24 + ti25) >> 23U);
+ vb25 +
+ ((va24 + ((vb25 & vd25) | (vc25 & ~vd25)) + xk24 + ti25) << 9U |
+ (va24 + ((vb25 & vd25) | (vc25 & ~vd25)) + xk24 + ti25) >> 23U);
abcd[3U] = v24;
uint32_t va25 = abcd[2U];
uint32_t vb26 = abcd[3U];
@@ -482,11 +430,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti26 = _t[26U];
uint32_t
v25 =
- vb26
- +
- ((va25 + ((vb26 & vd26) | (vc26 & ~vd26)) + xk25 + ti26)
- << 14U
- | (va25 + ((vb26 & vd26) | (vc26 & ~vd26)) + xk25 + ti26) >> 18U);
+ vb26 +
+ ((va25 + ((vb26 & vd26) | (vc26 & ~vd26)) + xk25 + ti26) << 14U |
+ (va25 + ((vb26 & vd26) | (vc26 & ~vd26)) + xk25 + ti26) >> 18U);
abcd[2U] = v25;
uint32_t va26 = abcd[1U];
uint32_t vb27 = abcd[2U];
@@ -498,11 +444,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti27 = _t[27U];
uint32_t
v26 =
- vb27
- +
- ((va26 + ((vb27 & vd27) | (vc27 & ~vd27)) + xk26 + ti27)
- << 20U
- | (va26 + ((vb27 & vd27) | (vc27 & ~vd27)) + xk26 + ti27) >> 12U);
+ vb27 +
+ ((va26 + ((vb27 & vd27) | (vc27 & ~vd27)) + xk26 + ti27) << 20U |
+ (va26 + ((vb27 & vd27) | (vc27 & ~vd27)) + xk26 + ti27) >> 12U);
abcd[1U] = v26;
uint32_t va27 = abcd[0U];
uint32_t vb28 = abcd[1U];
@@ -514,11 +458,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti28 = _t[28U];
uint32_t
v27 =
- vb28
- +
- ((va27 + ((vb28 & vd28) | (vc28 & ~vd28)) + xk27 + ti28)
- << 5U
- | (va27 + ((vb28 & vd28) | (vc28 & ~vd28)) + xk27 + ti28) >> 27U);
+ vb28 +
+ ((va27 + ((vb28 & vd28) | (vc28 & ~vd28)) + xk27 + ti28) << 5U |
+ (va27 + ((vb28 & vd28) | (vc28 & ~vd28)) + xk27 + ti28) >> 27U);
abcd[0U] = v27;
uint32_t va28 = abcd[3U];
uint32_t vb29 = abcd[0U];
@@ -530,11 +472,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti29 = _t[29U];
uint32_t
v28 =
- vb29
- +
- ((va28 + ((vb29 & vd29) | (vc29 & ~vd29)) + xk28 + ti29)
- << 9U
- | (va28 + ((vb29 & vd29) | (vc29 & ~vd29)) + xk28 + ti29) >> 23U);
+ vb29 +
+ ((va28 + ((vb29 & vd29) | (vc29 & ~vd29)) + xk28 + ti29) << 9U |
+ (va28 + ((vb29 & vd29) | (vc29 & ~vd29)) + xk28 + ti29) >> 23U);
abcd[3U] = v28;
uint32_t va29 = abcd[2U];
uint32_t vb30 = abcd[3U];
@@ -546,11 +486,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti30 = _t[30U];
uint32_t
v29 =
- vb30
- +
- ((va29 + ((vb30 & vd30) | (vc30 & ~vd30)) + xk29 + ti30)
- << 14U
- | (va29 + ((vb30 & vd30) | (vc30 & ~vd30)) + xk29 + ti30) >> 18U);
+ vb30 +
+ ((va29 + ((vb30 & vd30) | (vc30 & ~vd30)) + xk29 + ti30) << 14U |
+ (va29 + ((vb30 & vd30) | (vc30 & ~vd30)) + xk29 + ti30) >> 18U);
abcd[2U] = v29;
uint32_t va30 = abcd[1U];
uint32_t vb31 = abcd[2U];
@@ -562,11 +500,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti31 = _t[31U];
uint32_t
v30 =
- vb31
- +
- ((va30 + ((vb31 & vd31) | (vc31 & ~vd31)) + xk30 + ti31)
- << 20U
- | (va30 + ((vb31 & vd31) | (vc31 & ~vd31)) + xk30 + ti31) >> 12U);
+ vb31 +
+ ((va30 + ((vb31 & vd31) | (vc31 & ~vd31)) + xk30 + ti31) << 20U |
+ (va30 + ((vb31 & vd31) | (vc31 & ~vd31)) + xk30 + ti31) >> 12U);
abcd[1U] = v30;
uint32_t va31 = abcd[0U];
uint32_t vb32 = abcd[1U];
@@ -578,11 +514,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti32 = _t[32U];
uint32_t
v31 =
- vb32
- +
- ((va31 + (vb32 ^ (vc32 ^ vd32)) + xk31 + ti32)
- << 4U
- | (va31 + (vb32 ^ (vc32 ^ vd32)) + xk31 + ti32) >> 28U);
+ vb32 +
+ ((va31 + (vb32 ^ (vc32 ^ vd32)) + xk31 + ti32) << 4U |
+ (va31 + (vb32 ^ (vc32 ^ vd32)) + xk31 + ti32) >> 28U);
abcd[0U] = v31;
uint32_t va32 = abcd[3U];
uint32_t vb33 = abcd[0U];
@@ -594,11 +528,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti33 = _t[33U];
uint32_t
v32 =
- vb33
- +
- ((va32 + (vb33 ^ (vc33 ^ vd33)) + xk32 + ti33)
- << 11U
- | (va32 + (vb33 ^ (vc33 ^ vd33)) + xk32 + ti33) >> 21U);
+ vb33 +
+ ((va32 + (vb33 ^ (vc33 ^ vd33)) + xk32 + ti33) << 11U |
+ (va32 + (vb33 ^ (vc33 ^ vd33)) + xk32 + ti33) >> 21U);
abcd[3U] = v32;
uint32_t va33 = abcd[2U];
uint32_t vb34 = abcd[3U];
@@ -610,11 +542,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti34 = _t[34U];
uint32_t
v33 =
- vb34
- +
- ((va33 + (vb34 ^ (vc34 ^ vd34)) + xk33 + ti34)
- << 16U
- | (va33 + (vb34 ^ (vc34 ^ vd34)) + xk33 + ti34) >> 16U);
+ vb34 +
+ ((va33 + (vb34 ^ (vc34 ^ vd34)) + xk33 + ti34) << 16U |
+ (va33 + (vb34 ^ (vc34 ^ vd34)) + xk33 + ti34) >> 16U);
abcd[2U] = v33;
uint32_t va34 = abcd[1U];
uint32_t vb35 = abcd[2U];
@@ -626,11 +556,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti35 = _t[35U];
uint32_t
v34 =
- vb35
- +
- ((va34 + (vb35 ^ (vc35 ^ vd35)) + xk34 + ti35)
- << 23U
- | (va34 + (vb35 ^ (vc35 ^ vd35)) + xk34 + ti35) >> 9U);
+ vb35 +
+ ((va34 + (vb35 ^ (vc35 ^ vd35)) + xk34 + ti35) << 23U |
+ (va34 + (vb35 ^ (vc35 ^ vd35)) + xk34 + ti35) >> 9U);
abcd[1U] = v34;
uint32_t va35 = abcd[0U];
uint32_t vb36 = abcd[1U];
@@ -642,11 +570,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti36 = _t[36U];
uint32_t
v35 =
- vb36
- +
- ((va35 + (vb36 ^ (vc36 ^ vd36)) + xk35 + ti36)
- << 4U
- | (va35 + (vb36 ^ (vc36 ^ vd36)) + xk35 + ti36) >> 28U);
+ vb36 +
+ ((va35 + (vb36 ^ (vc36 ^ vd36)) + xk35 + ti36) << 4U |
+ (va35 + (vb36 ^ (vc36 ^ vd36)) + xk35 + ti36) >> 28U);
abcd[0U] = v35;
uint32_t va36 = abcd[3U];
uint32_t vb37 = abcd[0U];
@@ -658,11 +584,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti37 = _t[37U];
uint32_t
v36 =
- vb37
- +
- ((va36 + (vb37 ^ (vc37 ^ vd37)) + xk36 + ti37)
- << 11U
- | (va36 + (vb37 ^ (vc37 ^ vd37)) + xk36 + ti37) >> 21U);
+ vb37 +
+ ((va36 + (vb37 ^ (vc37 ^ vd37)) + xk36 + ti37) << 11U |
+ (va36 + (vb37 ^ (vc37 ^ vd37)) + xk36 + ti37) >> 21U);
abcd[3U] = v36;
uint32_t va37 = abcd[2U];
uint32_t vb38 = abcd[3U];
@@ -674,11 +598,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti38 = _t[38U];
uint32_t
v37 =
- vb38
- +
- ((va37 + (vb38 ^ (vc38 ^ vd38)) + xk37 + ti38)
- << 16U
- | (va37 + (vb38 ^ (vc38 ^ vd38)) + xk37 + ti38) >> 16U);
+ vb38 +
+ ((va37 + (vb38 ^ (vc38 ^ vd38)) + xk37 + ti38) << 16U |
+ (va37 + (vb38 ^ (vc38 ^ vd38)) + xk37 + ti38) >> 16U);
abcd[2U] = v37;
uint32_t va38 = abcd[1U];
uint32_t vb39 = abcd[2U];
@@ -690,11 +612,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti39 = _t[39U];
uint32_t
v38 =
- vb39
- +
- ((va38 + (vb39 ^ (vc39 ^ vd39)) + xk38 + ti39)
- << 23U
- | (va38 + (vb39 ^ (vc39 ^ vd39)) + xk38 + ti39) >> 9U);
+ vb39 +
+ ((va38 + (vb39 ^ (vc39 ^ vd39)) + xk38 + ti39) << 23U |
+ (va38 + (vb39 ^ (vc39 ^ vd39)) + xk38 + ti39) >> 9U);
abcd[1U] = v38;
uint32_t va39 = abcd[0U];
uint32_t vb40 = abcd[1U];
@@ -706,11 +626,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti40 = _t[40U];
uint32_t
v39 =
- vb40
- +
- ((va39 + (vb40 ^ (vc40 ^ vd40)) + xk39 + ti40)
- << 4U
- | (va39 + (vb40 ^ (vc40 ^ vd40)) + xk39 + ti40) >> 28U);
+ vb40 +
+ ((va39 + (vb40 ^ (vc40 ^ vd40)) + xk39 + ti40) << 4U |
+ (va39 + (vb40 ^ (vc40 ^ vd40)) + xk39 + ti40) >> 28U);
abcd[0U] = v39;
uint32_t va40 = abcd[3U];
uint32_t vb41 = abcd[0U];
@@ -722,11 +640,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti41 = _t[41U];
uint32_t
v40 =
- vb41
- +
- ((va40 + (vb41 ^ (vc41 ^ vd41)) + xk40 + ti41)
- << 11U
- | (va40 + (vb41 ^ (vc41 ^ vd41)) + xk40 + ti41) >> 21U);
+ vb41 +
+ ((va40 + (vb41 ^ (vc41 ^ vd41)) + xk40 + ti41) << 11U |
+ (va40 + (vb41 ^ (vc41 ^ vd41)) + xk40 + ti41) >> 21U);
abcd[3U] = v40;
uint32_t va41 = abcd[2U];
uint32_t vb42 = abcd[3U];
@@ -738,11 +654,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti42 = _t[42U];
uint32_t
v41 =
- vb42
- +
- ((va41 + (vb42 ^ (vc42 ^ vd42)) + xk41 + ti42)
- << 16U
- | (va41 + (vb42 ^ (vc42 ^ vd42)) + xk41 + ti42) >> 16U);
+ vb42 +
+ ((va41 + (vb42 ^ (vc42 ^ vd42)) + xk41 + ti42) << 16U |
+ (va41 + (vb42 ^ (vc42 ^ vd42)) + xk41 + ti42) >> 16U);
abcd[2U] = v41;
uint32_t va42 = abcd[1U];
uint32_t vb43 = abcd[2U];
@@ -754,11 +668,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti43 = _t[43U];
uint32_t
v42 =
- vb43
- +
- ((va42 + (vb43 ^ (vc43 ^ vd43)) + xk42 + ti43)
- << 23U
- | (va42 + (vb43 ^ (vc43 ^ vd43)) + xk42 + ti43) >> 9U);
+ vb43 +
+ ((va42 + (vb43 ^ (vc43 ^ vd43)) + xk42 + ti43) << 23U |
+ (va42 + (vb43 ^ (vc43 ^ vd43)) + xk42 + ti43) >> 9U);
abcd[1U] = v42;
uint32_t va43 = abcd[0U];
uint32_t vb44 = abcd[1U];
@@ -770,11 +682,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti44 = _t[44U];
uint32_t
v43 =
- vb44
- +
- ((va43 + (vb44 ^ (vc44 ^ vd44)) + xk43 + ti44)
- << 4U
- | (va43 + (vb44 ^ (vc44 ^ vd44)) + xk43 + ti44) >> 28U);
+ vb44 +
+ ((va43 + (vb44 ^ (vc44 ^ vd44)) + xk43 + ti44) << 4U |
+ (va43 + (vb44 ^ (vc44 ^ vd44)) + xk43 + ti44) >> 28U);
abcd[0U] = v43;
uint32_t va44 = abcd[3U];
uint32_t vb45 = abcd[0U];
@@ -786,11 +696,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti45 = _t[45U];
uint32_t
v44 =
- vb45
- +
- ((va44 + (vb45 ^ (vc45 ^ vd45)) + xk44 + ti45)
- << 11U
- | (va44 + (vb45 ^ (vc45 ^ vd45)) + xk44 + ti45) >> 21U);
+ vb45 +
+ ((va44 + (vb45 ^ (vc45 ^ vd45)) + xk44 + ti45) << 11U |
+ (va44 + (vb45 ^ (vc45 ^ vd45)) + xk44 + ti45) >> 21U);
abcd[3U] = v44;
uint32_t va45 = abcd[2U];
uint32_t vb46 = abcd[3U];
@@ -802,11 +710,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti46 = _t[46U];
uint32_t
v45 =
- vb46
- +
- ((va45 + (vb46 ^ (vc46 ^ vd46)) + xk45 + ti46)
- << 16U
- | (va45 + (vb46 ^ (vc46 ^ vd46)) + xk45 + ti46) >> 16U);
+ vb46 +
+ ((va45 + (vb46 ^ (vc46 ^ vd46)) + xk45 + ti46) << 16U |
+ (va45 + (vb46 ^ (vc46 ^ vd46)) + xk45 + ti46) >> 16U);
abcd[2U] = v45;
uint32_t va46 = abcd[1U];
uint32_t vb47 = abcd[2U];
@@ -818,11 +724,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti47 = _t[47U];
uint32_t
v46 =
- vb47
- +
- ((va46 + (vb47 ^ (vc47 ^ vd47)) + xk46 + ti47)
- << 23U
- | (va46 + (vb47 ^ (vc47 ^ vd47)) + xk46 + ti47) >> 9U);
+ vb47 +
+ ((va46 + (vb47 ^ (vc47 ^ vd47)) + xk46 + ti47) << 23U |
+ (va46 + (vb47 ^ (vc47 ^ vd47)) + xk46 + ti47) >> 9U);
abcd[1U] = v46;
uint32_t va47 = abcd[0U];
uint32_t vb48 = abcd[1U];
@@ -834,11 +738,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti48 = _t[48U];
uint32_t
v47 =
- vb48
- +
- ((va47 + (vc48 ^ (vb48 | ~vd48)) + xk47 + ti48)
- << 6U
- | (va47 + (vc48 ^ (vb48 | ~vd48)) + xk47 + ti48) >> 26U);
+ vb48 +
+ ((va47 + (vc48 ^ (vb48 | ~vd48)) + xk47 + ti48) << 6U |
+ (va47 + (vc48 ^ (vb48 | ~vd48)) + xk47 + ti48) >> 26U);
abcd[0U] = v47;
uint32_t va48 = abcd[3U];
uint32_t vb49 = abcd[0U];
@@ -850,11 +752,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti49 = _t[49U];
uint32_t
v48 =
- vb49
- +
- ((va48 + (vc49 ^ (vb49 | ~vd49)) + xk48 + ti49)
- << 10U
- | (va48 + (vc49 ^ (vb49 | ~vd49)) + xk48 + ti49) >> 22U);
+ vb49 +
+ ((va48 + (vc49 ^ (vb49 | ~vd49)) + xk48 + ti49) << 10U |
+ (va48 + (vc49 ^ (vb49 | ~vd49)) + xk48 + ti49) >> 22U);
abcd[3U] = v48;
uint32_t va49 = abcd[2U];
uint32_t vb50 = abcd[3U];
@@ -866,11 +766,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti50 = _t[50U];
uint32_t
v49 =
- vb50
- +
- ((va49 + (vc50 ^ (vb50 | ~vd50)) + xk49 + ti50)
- << 15U
- | (va49 + (vc50 ^ (vb50 | ~vd50)) + xk49 + ti50) >> 17U);
+ vb50 +
+ ((va49 + (vc50 ^ (vb50 | ~vd50)) + xk49 + ti50) << 15U |
+ (va49 + (vc50 ^ (vb50 | ~vd50)) + xk49 + ti50) >> 17U);
abcd[2U] = v49;
uint32_t va50 = abcd[1U];
uint32_t vb51 = abcd[2U];
@@ -882,11 +780,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti51 = _t[51U];
uint32_t
v50 =
- vb51
- +
- ((va50 + (vc51 ^ (vb51 | ~vd51)) + xk50 + ti51)
- << 21U
- | (va50 + (vc51 ^ (vb51 | ~vd51)) + xk50 + ti51) >> 11U);
+ vb51 +
+ ((va50 + (vc51 ^ (vb51 | ~vd51)) + xk50 + ti51) << 21U |
+ (va50 + (vc51 ^ (vb51 | ~vd51)) + xk50 + ti51) >> 11U);
abcd[1U] = v50;
uint32_t va51 = abcd[0U];
uint32_t vb52 = abcd[1U];
@@ -898,11 +794,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti52 = _t[52U];
uint32_t
v51 =
- vb52
- +
- ((va51 + (vc52 ^ (vb52 | ~vd52)) + xk51 + ti52)
- << 6U
- | (va51 + (vc52 ^ (vb52 | ~vd52)) + xk51 + ti52) >> 26U);
+ vb52 +
+ ((va51 + (vc52 ^ (vb52 | ~vd52)) + xk51 + ti52) << 6U |
+ (va51 + (vc52 ^ (vb52 | ~vd52)) + xk51 + ti52) >> 26U);
abcd[0U] = v51;
uint32_t va52 = abcd[3U];
uint32_t vb53 = abcd[0U];
@@ -914,11 +808,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti53 = _t[53U];
uint32_t
v52 =
- vb53
- +
- ((va52 + (vc53 ^ (vb53 | ~vd53)) + xk52 + ti53)
- << 10U
- | (va52 + (vc53 ^ (vb53 | ~vd53)) + xk52 + ti53) >> 22U);
+ vb53 +
+ ((va52 + (vc53 ^ (vb53 | ~vd53)) + xk52 + ti53) << 10U |
+ (va52 + (vc53 ^ (vb53 | ~vd53)) + xk52 + ti53) >> 22U);
abcd[3U] = v52;
uint32_t va53 = abcd[2U];
uint32_t vb54 = abcd[3U];
@@ -930,11 +822,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti54 = _t[54U];
uint32_t
v53 =
- vb54
- +
- ((va53 + (vc54 ^ (vb54 | ~vd54)) + xk53 + ti54)
- << 15U
- | (va53 + (vc54 ^ (vb54 | ~vd54)) + xk53 + ti54) >> 17U);
+ vb54 +
+ ((va53 + (vc54 ^ (vb54 | ~vd54)) + xk53 + ti54) << 15U |
+ (va53 + (vc54 ^ (vb54 | ~vd54)) + xk53 + ti54) >> 17U);
abcd[2U] = v53;
uint32_t va54 = abcd[1U];
uint32_t vb55 = abcd[2U];
@@ -946,11 +836,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti55 = _t[55U];
uint32_t
v54 =
- vb55
- +
- ((va54 + (vc55 ^ (vb55 | ~vd55)) + xk54 + ti55)
- << 21U
- | (va54 + (vc55 ^ (vb55 | ~vd55)) + xk54 + ti55) >> 11U);
+ vb55 +
+ ((va54 + (vc55 ^ (vb55 | ~vd55)) + xk54 + ti55) << 21U |
+ (va54 + (vc55 ^ (vb55 | ~vd55)) + xk54 + ti55) >> 11U);
abcd[1U] = v54;
uint32_t va55 = abcd[0U];
uint32_t vb56 = abcd[1U];
@@ -962,11 +850,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti56 = _t[56U];
uint32_t
v55 =
- vb56
- +
- ((va55 + (vc56 ^ (vb56 | ~vd56)) + xk55 + ti56)
- << 6U
- | (va55 + (vc56 ^ (vb56 | ~vd56)) + xk55 + ti56) >> 26U);
+ vb56 +
+ ((va55 + (vc56 ^ (vb56 | ~vd56)) + xk55 + ti56) << 6U |
+ (va55 + (vc56 ^ (vb56 | ~vd56)) + xk55 + ti56) >> 26U);
abcd[0U] = v55;
uint32_t va56 = abcd[3U];
uint32_t vb57 = abcd[0U];
@@ -978,11 +864,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti57 = _t[57U];
uint32_t
v56 =
- vb57
- +
- ((va56 + (vc57 ^ (vb57 | ~vd57)) + xk56 + ti57)
- << 10U
- | (va56 + (vc57 ^ (vb57 | ~vd57)) + xk56 + ti57) >> 22U);
+ vb57 +
+ ((va56 + (vc57 ^ (vb57 | ~vd57)) + xk56 + ti57) << 10U |
+ (va56 + (vc57 ^ (vb57 | ~vd57)) + xk56 + ti57) >> 22U);
abcd[3U] = v56;
uint32_t va57 = abcd[2U];
uint32_t vb58 = abcd[3U];
@@ -994,11 +878,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti58 = _t[58U];
uint32_t
v57 =
- vb58
- +
- ((va57 + (vc58 ^ (vb58 | ~vd58)) + xk57 + ti58)
- << 15U
- | (va57 + (vc58 ^ (vb58 | ~vd58)) + xk57 + ti58) >> 17U);
+ vb58 +
+ ((va57 + (vc58 ^ (vb58 | ~vd58)) + xk57 + ti58) << 15U |
+ (va57 + (vc58 ^ (vb58 | ~vd58)) + xk57 + ti58) >> 17U);
abcd[2U] = v57;
uint32_t va58 = abcd[1U];
uint32_t vb59 = abcd[2U];
@@ -1010,11 +892,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti59 = _t[59U];
uint32_t
v58 =
- vb59
- +
- ((va58 + (vc59 ^ (vb59 | ~vd59)) + xk58 + ti59)
- << 21U
- | (va58 + (vc59 ^ (vb59 | ~vd59)) + xk58 + ti59) >> 11U);
+ vb59 +
+ ((va58 + (vc59 ^ (vb59 | ~vd59)) + xk58 + ti59) << 21U |
+ (va58 + (vc59 ^ (vb59 | ~vd59)) + xk58 + ti59) >> 11U);
abcd[1U] = v58;
uint32_t va59 = abcd[0U];
uint32_t vb60 = abcd[1U];
@@ -1026,11 +906,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti60 = _t[60U];
uint32_t
v59 =
- vb60
- +
- ((va59 + (vc60 ^ (vb60 | ~vd60)) + xk59 + ti60)
- << 6U
- | (va59 + (vc60 ^ (vb60 | ~vd60)) + xk59 + ti60) >> 26U);
+ vb60 +
+ ((va59 + (vc60 ^ (vb60 | ~vd60)) + xk59 + ti60) << 6U |
+ (va59 + (vc60 ^ (vb60 | ~vd60)) + xk59 + ti60) >> 26U);
abcd[0U] = v59;
uint32_t va60 = abcd[3U];
uint32_t vb61 = abcd[0U];
@@ -1042,11 +920,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti61 = _t[61U];
uint32_t
v60 =
- vb61
- +
- ((va60 + (vc61 ^ (vb61 | ~vd61)) + xk60 + ti61)
- << 10U
- | (va60 + (vc61 ^ (vb61 | ~vd61)) + xk60 + ti61) >> 22U);
+ vb61 +
+ ((va60 + (vc61 ^ (vb61 | ~vd61)) + xk60 + ti61) << 10U |
+ (va60 + (vc61 ^ (vb61 | ~vd61)) + xk60 + ti61) >> 22U);
abcd[3U] = v60;
uint32_t va61 = abcd[2U];
uint32_t vb62 = abcd[3U];
@@ -1058,11 +934,9 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti62 = _t[62U];
uint32_t
v61 =
- vb62
- +
- ((va61 + (vc62 ^ (vb62 | ~vd62)) + xk61 + ti62)
- << 15U
- | (va61 + (vc62 ^ (vb62 | ~vd62)) + xk61 + ti62) >> 17U);
+ vb62 +
+ ((va61 + (vc62 ^ (vb62 | ~vd62)) + xk61 + ti62) << 15U |
+ (va61 + (vc62 ^ (vb62 | ~vd62)) + xk61 + ti62) >> 17U);
abcd[2U] = v61;
uint32_t va62 = abcd[1U];
uint32_t vb = abcd[2U];
@@ -1074,11 +948,8 @@ static void update(uint32_t *abcd, uint8_t *x)
uint32_t ti = _t[63U];
uint32_t
v62 =
- vb
- +
- ((va62 + (vc ^ (vb | ~vd)) + xk62 + ti)
- << 21U
- | (va62 + (vc ^ (vb | ~vd)) + xk62 + ti) >> 11U);
+ vb +
+ ((va62 + (vc ^ (vb | ~vd)) + xk62 + ti) << 21U | (va62 + (vc ^ (vb | ~vd)) + xk62 + ti) >> 11U);
abcd[1U] = v62;
uint32_t a = abcd[0U];
uint32_t b = abcd[1U];
@@ -1282,8 +1153,7 @@ Hacl_Hash_MD5_update(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_t
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
@@ -1328,8 +1198,7 @@ Hacl_Hash_MD5_update(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_t
Hacl_Hash_MD5_update_multi(block_state1, data1, data1_len / 64U);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
@@ -1359,8 +1228,7 @@ Hacl_Hash_MD5_update(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_t
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state10,
@@ -1403,8 +1271,7 @@ Hacl_Hash_MD5_update(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_t
Hacl_Hash_MD5_update_multi(block_state1, data1, data1_len / 64U);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
diff --git a/Modules/_hacl/Hacl_Hash_SHA1.c b/Modules/_hacl/Hacl_Hash_SHA1.c
index 508e447bf27..97bd4f2204c 100644
--- a/Modules/_hacl/Hacl_Hash_SHA1.c
+++ b/Modules/_hacl/Hacl_Hash_SHA1.c
@@ -315,8 +315,7 @@ Hacl_Hash_SHA1_update(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
@@ -361,8 +360,7 @@ Hacl_Hash_SHA1_update(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_
Hacl_Hash_SHA1_update_multi(block_state1, data1, data1_len / 64U);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
@@ -392,8 +390,7 @@ Hacl_Hash_SHA1_update(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state10,
@@ -436,8 +433,7 @@ Hacl_Hash_SHA1_update(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_
Hacl_Hash_SHA1_update_multi(block_state1, data1, data1_len / 64U);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
diff --git a/Modules/_hacl/Hacl_Hash_SHA2.c b/Modules/_hacl/Hacl_Hash_SHA2.c
index d612bafa72c..d2ee0c9ef51 100644
--- a/Modules/_hacl/Hacl_Hash_SHA2.c
+++ b/Modules/_hacl/Hacl_Hash_SHA2.c
@@ -100,15 +100,14 @@ static inline void sha256_update(uint8_t *b, uint32_t *hash)
uint32_t k_e_t = k_t;
uint32_t
t1 =
- h02
- + ((e0 << 26U | e0 >> 6U) ^ ((e0 << 21U | e0 >> 11U) ^ (e0 << 7U | e0 >> 25U)))
- + ((e0 & f0) ^ (~e0 & g0))
+ h02 + ((e0 << 26U | e0 >> 6U) ^ ((e0 << 21U | e0 >> 11U) ^ (e0 << 7U | e0 >> 25U))) +
+ ((e0 & f0) ^ (~e0 & g0))
+ k_e_t
+ ws_t;
uint32_t
t2 =
- ((a0 << 30U | a0 >> 2U) ^ ((a0 << 19U | a0 >> 13U) ^ (a0 << 10U | a0 >> 22U)))
- + ((a0 & b0) ^ ((a0 & c0) ^ (b0 & c0)));
+ ((a0 << 30U | a0 >> 2U) ^ ((a0 << 19U | a0 >> 13U) ^ (a0 << 10U | a0 >> 22U))) +
+ ((a0 & b0) ^ ((a0 & c0) ^ (b0 & c0)));
uint32_t a1 = t1 + t2;
uint32_t b1 = a0;
uint32_t c1 = b0;
@@ -301,15 +300,14 @@ static inline void sha512_update(uint8_t *b, uint64_t *hash)
uint64_t k_e_t = k_t;
uint64_t
t1 =
- h02
- + ((e0 << 50U | e0 >> 14U) ^ ((e0 << 46U | e0 >> 18U) ^ (e0 << 23U | e0 >> 41U)))
- + ((e0 & f0) ^ (~e0 & g0))
+ h02 + ((e0 << 50U | e0 >> 14U) ^ ((e0 << 46U | e0 >> 18U) ^ (e0 << 23U | e0 >> 41U))) +
+ ((e0 & f0) ^ (~e0 & g0))
+ k_e_t
+ ws_t;
uint64_t
t2 =
- ((a0 << 36U | a0 >> 28U) ^ ((a0 << 30U | a0 >> 34U) ^ (a0 << 25U | a0 >> 39U)))
- + ((a0 & b0) ^ ((a0 & c0) ^ (b0 & c0)));
+ ((a0 << 36U | a0 >> 28U) ^ ((a0 << 30U | a0 >> 34U) ^ (a0 << 25U | a0 >> 39U))) +
+ ((a0 & b0) ^ ((a0 & c0) ^ (b0 & c0)));
uint64_t a1 = t1 + t2;
uint64_t b1 = a0;
uint64_t c1 = b0;
@@ -639,8 +637,7 @@ update_224_256(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_t chunk
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
@@ -685,8 +682,7 @@ update_224_256(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_t chunk
Hacl_Hash_SHA2_sha256_update_nblocks(data1_len / 64U * 64U, data1, block_state1);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
@@ -716,8 +712,7 @@ update_224_256(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_t chunk
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state10,
@@ -760,8 +755,7 @@ update_224_256(Hacl_Streaming_MD_state_32 *state, uint8_t *chunk, uint32_t chunk
Hacl_Hash_SHA2_sha256_update_nblocks(data1_len / 64U * 64U, data1, block_state1);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_32){
.block_state = block_state1,
@@ -1205,8 +1199,7 @@ update_384_512(Hacl_Streaming_MD_state_64 *state, uint8_t *chunk, uint32_t chunk
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_64){
.block_state = block_state1,
@@ -1251,8 +1244,7 @@ update_384_512(Hacl_Streaming_MD_state_64 *state, uint8_t *chunk, uint32_t chunk
Hacl_Hash_SHA2_sha512_update_nblocks(data1_len / 128U * 128U, data1, block_state1);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_64){
.block_state = block_state1,
@@ -1282,8 +1274,7 @@ update_384_512(Hacl_Streaming_MD_state_64 *state, uint8_t *chunk, uint32_t chunk
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_64){
.block_state = block_state10,
@@ -1326,8 +1317,7 @@ update_384_512(Hacl_Streaming_MD_state_64 *state, uint8_t *chunk, uint32_t chunk
Hacl_Hash_SHA2_sha512_update_nblocks(data1_len / 128U * 128U, data1, block_state1);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_MD_state_64){
.block_state = block_state1,
diff --git a/Modules/_hacl/Hacl_Hash_SHA3.c b/Modules/_hacl/Hacl_Hash_SHA3.c
index 87638df9549..466d2b96c0c 100644
--- a/Modules/_hacl/Hacl_Hash_SHA3.c
+++ b/Modules/_hacl/Hacl_Hash_SHA3.c
@@ -866,8 +866,7 @@ Hacl_Hash_SHA3_update(Hacl_Hash_SHA3_state_t *state, uint8_t *chunk, uint32_t ch
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
((Hacl_Hash_SHA3_state_t){ .block_state = block_state1, .buf = buf, .total_len = total_len2 });
}
else if (sz == 0U)
@@ -910,8 +909,7 @@ Hacl_Hash_SHA3_update(Hacl_Hash_SHA3_state_t *state, uint8_t *chunk, uint32_t ch
Hacl_Hash_SHA3_update_multi_sha3(a1, s2, data1, data1_len / block_len(a1));
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_SHA3_state_t){
.block_state = block_state1,
@@ -941,8 +939,7 @@ Hacl_Hash_SHA3_update(Hacl_Hash_SHA3_state_t *state, uint8_t *chunk, uint32_t ch
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Hash_SHA3_state_t){
.block_state = block_state10,
@@ -972,10 +969,8 @@ Hacl_Hash_SHA3_update(Hacl_Hash_SHA3_state_t *state, uint8_t *chunk, uint32_t ch
uint32_t ite;
if
(
- (uint64_t)(chunk_len - diff)
- % (uint64_t)block_len(i)
- == 0ULL
- && (uint64_t)(chunk_len - diff) > 0ULL
+ (uint64_t)(chunk_len - diff) % (uint64_t)block_len(i) == 0ULL &&
+ (uint64_t)(chunk_len - diff) > 0ULL
)
{
ite = block_len(i);
@@ -994,8 +989,7 @@ Hacl_Hash_SHA3_update(Hacl_Hash_SHA3_state_t *state, uint8_t *chunk, uint32_t ch
Hacl_Hash_SHA3_update_multi_sha3(a1, s2, data1, data1_len / block_len(a1));
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Hash_SHA3_state_t){
.block_state = block_state1,
@@ -2422,9 +2416,7 @@ Hacl_Hash_SHA3_shake128_squeeze_nblocks(
5U,
1U,
_C[i] =
- state[i
- + 0U]
- ^ (state[i + 5U] ^ (state[i + 10U] ^ (state[i + 15U] ^ state[i + 20U]))););
+ state[i + 0U] ^ (state[i + 5U] ^ (state[i + 10U] ^ (state[i + 15U] ^ state[i + 20U]))););
KRML_MAYBE_FOR5(i2,
0U,
5U,
diff --git a/Modules/_hacl/Hacl_Streaming_HMAC.c b/Modules/_hacl/Hacl_Streaming_HMAC.c
index d28b39792af..8dd7e2c0bf3 100644
--- a/Modules/_hacl/Hacl_Streaming_HMAC.c
+++ b/Modules/_hacl/Hacl_Streaming_HMAC.c
@@ -198,8 +198,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- = ((Hacl_Agile_Hash_state_s){ .tag = Hacl_Agile_Hash_MD5_a, { .case_MD5_a = s1 } });
+ st[0U] = ((Hacl_Agile_Hash_state_s){ .tag = Hacl_Agile_Hash_MD5_a, { .case_MD5_a = s1 } });
}
if (st == NULL)
{
@@ -220,8 +219,8 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- = ((Hacl_Agile_Hash_state_s){ .tag = Hacl_Agile_Hash_SHA1_a, { .case_SHA1_a = s1 } });
+ st[0U] =
+ ((Hacl_Agile_Hash_state_s){ .tag = Hacl_Agile_Hash_SHA1_a, { .case_SHA1_a = s1 } });
}
if (st == NULL)
{
@@ -242,8 +241,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_SHA2_224_a,
@@ -270,8 +268,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_SHA2_256_a,
@@ -298,8 +295,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_SHA2_384_a,
@@ -326,8 +322,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_SHA2_512_a,
@@ -354,8 +349,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_SHA3_224_a,
@@ -382,8 +376,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_SHA3_256_a,
@@ -410,8 +403,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_SHA3_384_a,
@@ -438,8 +430,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_SHA3_512_a,
@@ -466,8 +457,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_Blake2S_a,
@@ -495,8 +485,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_Blake2S_128_a,
@@ -531,8 +520,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_Blake2B_a,
@@ -560,8 +548,7 @@ static Hacl_Agile_Hash_state_s *malloc_(Hacl_Agile_Hash_impl a)
*st = (Hacl_Agile_Hash_state_s *)KRML_HOST_MALLOC(sizeof (Hacl_Agile_Hash_state_s));
if (st != NULL)
{
- st[0U]
- =
+ st[0U] =
(
(Hacl_Agile_Hash_state_s){
.tag = Hacl_Agile_Hash_Blake2B_256_a,
@@ -2059,8 +2046,8 @@ Hacl_Streaming_HMAC_update(
Hacl_Streaming_HMAC_Definitions_index i1 = Hacl_Streaming_HMAC_index_of_state(block_state);
if
(
- (uint64_t)chunk_len
- > max_input_len64(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) - total_len
+ (uint64_t)chunk_len >
+ max_input_len64(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) - total_len
)
{
return Hacl_Streaming_Types_MaximumLengthExceeded;
@@ -2068,9 +2055,7 @@ Hacl_Streaming_HMAC_update(
uint32_t sz;
if
(
- total_len
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
- == 0ULL
+ total_len % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) == 0ULL
&& total_len > 0ULL
)
{
@@ -2079,8 +2064,8 @@ Hacl_Streaming_HMAC_update(
else
{
sz =
- (uint32_t)(total_len
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+ (uint32_t)(total_len %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
}
if (chunk_len <= block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) - sz)
{
@@ -2091,9 +2076,7 @@ Hacl_Streaming_HMAC_update(
uint32_t sz1;
if
(
- total_len1
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
- == 0ULL
+ total_len1 % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) == 0ULL
&& total_len1 > 0ULL
)
{
@@ -2102,14 +2085,13 @@ Hacl_Streaming_HMAC_update(
else
{
sz1 =
- (uint32_t)(total_len1
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+ (uint32_t)(total_len1 %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
}
uint8_t *buf2 = buf + sz1;
memcpy(buf2, chunk, chunk_len * sizeof (uint8_t));
uint64_t total_len2 = total_len1 + (uint64_t)chunk_len;
- *state
- =
+ *state =
(
(Hacl_Streaming_HMAC_agile_state){
.block_state = block_state1,
@@ -2127,9 +2109,7 @@ Hacl_Streaming_HMAC_update(
uint32_t sz1;
if
(
- total_len1
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
- == 0ULL
+ total_len1 % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) == 0ULL
&& total_len1 > 0ULL
)
{
@@ -2138,8 +2118,8 @@ Hacl_Streaming_HMAC_update(
else
{
sz1 =
- (uint32_t)(total_len1
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+ (uint32_t)(total_len1 %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
}
if (!(sz1 == 0U))
{
@@ -2153,8 +2133,8 @@ Hacl_Streaming_HMAC_update(
uint32_t ite;
if
(
- (uint64_t)chunk_len
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+ (uint64_t)chunk_len %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
== 0ULL
&& (uint64_t)chunk_len > 0ULL
)
@@ -2164,8 +2144,8 @@ Hacl_Streaming_HMAC_update(
else
{
ite =
- (uint32_t)((uint64_t)chunk_len
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+ (uint32_t)((uint64_t)chunk_len %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
}
uint32_t
n_blocks = (chunk_len - ite) / block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
@@ -2178,8 +2158,7 @@ Hacl_Streaming_HMAC_update(
update_multi(s11, total_len1, data1, data1_len);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_HMAC_agile_state){
.block_state = block_state1,
@@ -2200,9 +2179,8 @@ Hacl_Streaming_HMAC_update(
uint32_t sz10;
if
(
- total_len10
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
- == 0ULL
+ total_len10 % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) ==
+ 0ULL
&& total_len10 > 0ULL
)
{
@@ -2211,14 +2189,13 @@ Hacl_Streaming_HMAC_update(
else
{
sz10 =
- (uint32_t)(total_len10
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+ (uint32_t)(total_len10 %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
}
uint8_t *buf2 = buf0 + sz10;
memcpy(buf2, chunk1, diff * sizeof (uint8_t));
uint64_t total_len2 = total_len10 + (uint64_t)diff;
- *state
- =
+ *state =
(
(Hacl_Streaming_HMAC_agile_state){
.block_state = block_state10,
@@ -2233,9 +2210,7 @@ Hacl_Streaming_HMAC_update(
uint32_t sz1;
if
(
- total_len1
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
- == 0ULL
+ total_len1 % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) == 0ULL
&& total_len1 > 0ULL
)
{
@@ -2244,8 +2219,8 @@ Hacl_Streaming_HMAC_update(
else
{
sz1 =
- (uint32_t)(total_len1
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+ (uint32_t)(total_len1 %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
}
if (!(sz1 == 0U))
{
@@ -2259,8 +2234,8 @@ Hacl_Streaming_HMAC_update(
uint32_t ite;
if
(
- (uint64_t)(chunk_len - diff)
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
+ (uint64_t)(chunk_len - diff) %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
== 0ULL
&& (uint64_t)(chunk_len - diff) > 0ULL
)
@@ -2270,13 +2245,12 @@ Hacl_Streaming_HMAC_update(
else
{
ite =
- (uint32_t)((uint64_t)(chunk_len - diff)
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+ (uint32_t)((uint64_t)(chunk_len - diff) %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
}
uint32_t
n_blocks =
- (chunk_len - diff - ite)
- / block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
+ (chunk_len - diff - ite) / block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
uint32_t
data1_len = n_blocks * block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)));
uint32_t data2_len = chunk_len - diff - data1_len;
@@ -2286,8 +2260,7 @@ Hacl_Streaming_HMAC_update(
update_multi(s11, total_len1, data1, data1_len);
uint8_t *dst = buf;
memcpy(dst, data2, data2_len * sizeof (uint8_t));
- *state
- =
+ *state =
(
(Hacl_Streaming_HMAC_agile_state){
.block_state = block_state1,
@@ -2324,9 +2297,7 @@ Hacl_Streaming_HMAC_digest(
uint32_t r;
if
(
- total_len
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1)))
- == 0ULL
+ total_len % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))) == 0ULL
&& total_len > 0ULL
)
{
@@ -2335,8 +2306,8 @@ Hacl_Streaming_HMAC_digest(
else
{
r =
- (uint32_t)(total_len
- % (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
+ (uint32_t)(total_len %
+ (uint64_t)block_len(alg_of_impl(dfst__Hacl_Agile_Hash_impl_uint32_t(i1))));
}
uint8_t *buf_1 = buf_;
Hacl_Agile_Hash_state_s *s110 = malloc_(dfst__Hacl_Agile_Hash_impl_uint32_t(i1));
diff --git a/Modules/_hacl/Lib_Memzero0.c b/Modules/_hacl/Lib_Memzero0.c
index 28abd1aa4e2..f94e0e2254a 100644
--- a/Modules/_hacl/Lib_Memzero0.c
+++ b/Modules/_hacl/Lib_Memzero0.c
@@ -11,18 +11,18 @@
#if defined(__APPLE__) && defined(__MACH__)
#include <AvailabilityMacros.h>
// memset_s is available from macOS 10.9, iOS 7, watchOS 2, and on all tvOS and visionOS versions.
-# if (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && (MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_9))
-# define APPLE_HAS_MEMSET_S 1
-# elif (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0))
-# define APPLE_HAS_MEMSET_S 1
+# if (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && defined(MAC_OS_X_VERSION_10_9) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9))
+# define APPLE_HAS_MEMSET_S
+# elif (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_7_0) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0))
+# define APPLE_HAS_MEMSET_S
# elif (defined(TARGET_OS_TV) && TARGET_OS_TV)
-# define APPLE_HAS_MEMSET_S 1
-# elif (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && (__WATCH_OS_VERSION_MIN_REQUIRED >= __WATCHOS_2_0))
-# define APPLE_HAS_MEMSET_S 1
+# define APPLE_HAS_MEMSET_S
+# elif (defined(__WATCH_OS_VERSION_MIN_REQUIRED) && defined(__WATCHOS_2_0) && (__WATCH_OS_VERSION_MIN_REQUIRED >= __WATCHOS_2_0))
+# define APPLE_HAS_MEMSET_S
# elif (defined(TARGET_OS_VISION) && TARGET_OS_VISION)
-# define APPLE_HAS_MEMSET_S 1
+# define APPLE_HAS_MEMSET_S
# else
-# define APPLE_HAS_MEMSET_S 0
+# undef APPLE_HAS_MEMSET_S
# endif
#endif
@@ -55,7 +55,7 @@ void Lib_Memzero0_memzero0(void *dst, uint64_t len) {
#ifdef _WIN32
SecureZeroMemory(dst, len_);
- #elif defined(__APPLE__) && defined(__MACH__) && APPLE_HAS_MEMSET_S
+ #elif defined(__APPLE__) && defined(__MACH__) && defined(APPLE_HAS_MEMSET_S)
memset_s(dst, len_, 0, len_);
#elif (defined(__linux__) && !defined(LINUX_NO_EXPLICIT_BZERO)) || defined(__FreeBSD__) || defined(__OpenBSD__)
explicit_bzero(dst, len_);
diff --git a/Modules/_hacl/include/krml/FStar_UInt128_Verified.h b/Modules/_hacl/include/krml/FStar_UInt128_Verified.h
index d4a90220bea..f85982f3373 100644
--- a/Modules/_hacl/include/krml/FStar_UInt128_Verified.h
+++ b/Modules/_hacl/include/krml/FStar_UInt128_Verified.h
@@ -257,11 +257,11 @@ FStar_UInt128_gte_mask(FStar_UInt128_uint128 a, FStar_UInt128_uint128 b)
{
FStar_UInt128_uint128 lit;
lit.low =
- (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high))
- | (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low));
+ (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high)) |
+ (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low));
lit.high =
- (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high))
- | (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low));
+ (FStar_UInt64_gte_mask(a.high, b.high) & ~FStar_UInt64_eq_mask(a.high, b.high)) |
+ (FStar_UInt64_eq_mask(a.high, b.high) & FStar_UInt64_gte_mask(a.low, b.low));
return lit;
}
@@ -294,14 +294,12 @@ static inline FStar_UInt128_uint128 FStar_UInt128_mul32(uint64_t x, uint32_t y)
{
FStar_UInt128_uint128 lit;
lit.low =
- FStar_UInt128_u32_combine((x >> FStar_UInt128_u32_32)
- * (uint64_t)y
- + (FStar_UInt128_u64_mod_32(x) * (uint64_t)y >> FStar_UInt128_u32_32),
+ FStar_UInt128_u32_combine((x >> FStar_UInt128_u32_32) * (uint64_t)y +
+ (FStar_UInt128_u64_mod_32(x) * (uint64_t)y >> FStar_UInt128_u32_32),
FStar_UInt128_u64_mod_32(FStar_UInt128_u64_mod_32(x) * (uint64_t)y));
lit.high =
- ((x >> FStar_UInt128_u32_32)
- * (uint64_t)y
- + (FStar_UInt128_u64_mod_32(x) * (uint64_t)y >> FStar_UInt128_u32_32))
+ ((x >> FStar_UInt128_u32_32) * (uint64_t)y +
+ (FStar_UInt128_u64_mod_32(x) * (uint64_t)y >> FStar_UInt128_u32_32))
>> FStar_UInt128_u32_32;
return lit;
}
@@ -315,28 +313,19 @@ static inline FStar_UInt128_uint128 FStar_UInt128_mul_wide(uint64_t x, uint64_t
{
FStar_UInt128_uint128 lit;
lit.low =
- FStar_UInt128_u32_combine_(FStar_UInt128_u64_mod_32(x)
- * (y >> FStar_UInt128_u32_32)
- +
- FStar_UInt128_u64_mod_32((x >> FStar_UInt128_u32_32)
- * FStar_UInt128_u64_mod_32(y)
- + (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32)),
+ FStar_UInt128_u32_combine_(FStar_UInt128_u64_mod_32(x) * (y >> FStar_UInt128_u32_32) +
+ FStar_UInt128_u64_mod_32((x >> FStar_UInt128_u32_32) * FStar_UInt128_u64_mod_32(y) +
+ (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32)),
FStar_UInt128_u64_mod_32(FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y)));
lit.high =
- (x >> FStar_UInt128_u32_32)
- * (y >> FStar_UInt128_u32_32)
- +
- (((x >> FStar_UInt128_u32_32)
- * FStar_UInt128_u64_mod_32(y)
- + (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32))
+ (x >> FStar_UInt128_u32_32) * (y >> FStar_UInt128_u32_32) +
+ (((x >> FStar_UInt128_u32_32) * FStar_UInt128_u64_mod_32(y) +
+ (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32))
>> FStar_UInt128_u32_32)
+
- ((FStar_UInt128_u64_mod_32(x)
- * (y >> FStar_UInt128_u32_32)
- +
- FStar_UInt128_u64_mod_32((x >> FStar_UInt128_u32_32)
- * FStar_UInt128_u64_mod_32(y)
- + (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32)))
+ ((FStar_UInt128_u64_mod_32(x) * (y >> FStar_UInt128_u32_32) +
+ FStar_UInt128_u64_mod_32((x >> FStar_UInt128_u32_32) * FStar_UInt128_u64_mod_32(y) +
+ (FStar_UInt128_u64_mod_32(x) * FStar_UInt128_u64_mod_32(y) >> FStar_UInt128_u32_32)))
>> FStar_UInt128_u32_32);
return lit;
}
diff --git a/Modules/_hacl/refresh.sh b/Modules/_hacl/refresh.sh
index d91650b44bb..a6776282423 100755
--- a/Modules/_hacl/refresh.sh
+++ b/Modules/_hacl/refresh.sh
@@ -22,7 +22,7 @@ fi
# Update this when updating to a new version after verifying that the changes
# the update brings in are good.
-expected_hacl_star_rev=7720f6d4fc0468a99d5ea6120976bcc271e42727
+expected_hacl_star_rev=4ef25b547b377dcef855db4289c6a00580e7221c
hacl_dir="$(realpath "$1")"
cd "$(dirname "$0")"
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 48eed5eac97..331275076d7 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -38,6 +38,10 @@
#include <stdbool.h>
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+# define Py_HAS_OPENSSL3_SUPPORT
+#endif
+
#ifndef OPENSSL_THREADS
# error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL"
#endif
@@ -55,7 +59,7 @@
#define PY_OPENSSL_HAS_BLAKE2 1
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#ifdef Py_HAS_OPENSSL3_SUPPORT
#define PY_EVP_MD EVP_MD
#define PY_EVP_MD_fetch(algorithm, properties) EVP_MD_fetch(NULL, algorithm, properties)
#define PY_EVP_MD_up_ref(md) EVP_MD_up_ref(md)
@@ -77,12 +81,12 @@
* py_alias as keys.
*/
-enum Py_hash_type {
- Py_ht_evp, // usedforsecurity=True / default
- Py_ht_evp_nosecurity, // usedforsecurity=False
- Py_ht_mac, // HMAC
- Py_ht_pbkdf2, // PKBDF2
-};
+typedef enum Py_hash_type {
+ Py_ht_evp, // usedforsecurity=True / default
+ Py_ht_evp_nosecurity, // usedforsecurity=False
+ Py_ht_mac, // HMAC
+ Py_ht_pbkdf2, // PKBDF2
+} Py_hash_type;
typedef struct {
const char *py_name;
@@ -255,10 +259,10 @@ py_hashentry_table_new(void) {
static PyModuleDef _hashlibmodule;
typedef struct {
- PyTypeObject *EVPtype;
+ PyTypeObject *HASH_type; // based on EVP_MD
PyTypeObject *HMACtype;
#ifdef PY_OPENSSL_HAS_SHAKE
- PyTypeObject *EVPXOFtype;
+ PyTypeObject *HASHXOF_type; // based on EVP_MD
#endif
PyObject *constructs;
PyObject *unsupported_digestmod_error;
@@ -275,13 +279,13 @@ get_hashlib_state(PyObject *module)
typedef struct {
PyObject_HEAD
- EVP_MD_CTX *ctx; /* OpenSSL message digest context */
+ EVP_MD_CTX *ctx; /* OpenSSL message digest context */
// Prevents undefined behavior via multiple threads entering the C API.
bool use_mutex;
- PyMutex mutex; /* OpenSSL context lock */
-} EVPobject;
+ PyMutex mutex; /* OpenSSL context lock */
+} HASHobject;
-#define EVPobject_CAST(op) ((EVPobject *)(op))
+#define HASHobject_CAST(op) ((HASHobject *)(op))
typedef struct {
PyObject_HEAD
@@ -296,11 +300,11 @@ typedef struct {
#include "clinic/_hashopenssl.c.h"
/*[clinic input]
module _hashlib
-class _hashlib.HASH "EVPobject *" "((_hashlibstate *)PyModule_GetState(module))->EVPtype"
-class _hashlib.HASHXOF "EVPobject *" "((_hashlibstate *)PyModule_GetState(module))->EVPXOFtype"
+class _hashlib.HASH "HASHobject *" "((_hashlibstate *)PyModule_GetState(module))->EVPtype"
+class _hashlib.HASHXOF "HASHobject *" "((_hashlibstate *)PyModule_GetState(module))->EVPXOFtype"
class _hashlib.HMAC "HMACobject *" "((_hashlibstate *)PyModule_GetState(module))->HMACtype"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7df1bcf6f75cb8ef]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4f6b8873ed13d1ff]*/
/* LCOV_EXCL_START */
@@ -364,8 +368,8 @@ notify_ssl_error_occurred(void)
}
/* LCOV_EXCL_STOP */
-static PyObject*
-py_digest_name(const EVP_MD *md)
+static const char *
+get_openssl_evp_md_utf8name(const EVP_MD *md)
{
assert(md != NULL);
int nid = EVP_MD_nid(md);
@@ -388,13 +392,20 @@ py_digest_name(const EVP_MD *md)
if (name == NULL)
name = OBJ_nid2sn(nid);
}
+ return name;
+}
+static PyObject *
+get_openssl_evp_md_name(const EVP_MD *md)
+{
+ const char *name = get_openssl_evp_md_utf8name(md);
return PyUnicode_FromString(name);
}
/* Get EVP_MD by HID and purpose */
-static PY_EVP_MD*
-py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht)
+static PY_EVP_MD *
+get_openssl_evp_md_by_utf8name(PyObject *module, const char *name,
+ Py_hash_type py_ht)
{
PY_EVP_MD *digest = NULL;
PY_EVP_MD *other_digest = NULL;
@@ -460,15 +471,17 @@ py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht)
return digest;
}
-/* Get digest EVP from object
+/* Get digest EVP_MD from object
*
* * string
* * _hashopenssl builtin function
*
* on error returns NULL with exception set.
*/
-static PY_EVP_MD*
-py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type py_ht) {
+static PY_EVP_MD *
+get_openssl_evp_md(PyObject *module, PyObject *digestmod,
+ Py_hash_type py_ht)
+{
PyObject *name_obj = NULL;
const char *name;
@@ -494,13 +507,13 @@ py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type
return NULL;
}
- return py_digest_by_name(module, name, py_ht);
+ return get_openssl_evp_md_by_utf8name(module, name, py_ht);
}
-static EVPobject *
-newEVPobject(PyTypeObject *type)
+static HASHobject *
+new_hash_object(PyTypeObject *type)
{
- EVPobject *retval = PyObject_New(EVPobject, type);
+ HASHobject *retval = PyObject_New(HASHobject, type);
if (retval == NULL) {
return NULL;
}
@@ -517,7 +530,7 @@ newEVPobject(PyTypeObject *type)
}
static int
-EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
+_hashlib_HASH_hash(HASHobject *self, const void *vp, Py_ssize_t len)
{
unsigned int process;
const unsigned char *cp = (const unsigned char *)vp;
@@ -539,9 +552,9 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
/* Internal methods for a hash object */
static void
-EVP_dealloc(PyObject *op)
+_hashlib_HASH_dealloc(PyObject *op)
{
- EVPobject *self = EVPobject_CAST(op);
+ HASHobject *self = HASHobject_CAST(op);
PyTypeObject *tp = Py_TYPE(self);
EVP_MD_CTX_free(self->ctx);
PyObject_Free(self);
@@ -549,7 +562,7 @@ EVP_dealloc(PyObject *op)
}
static int
-locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
+_hashlib_HASH_copy_locked(HASHobject *self, EVP_MD_CTX *new_ctx_p)
{
int result;
ENTER_HASHLIB(self);
@@ -561,21 +574,21 @@ locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
/* External methods for a hash object */
/*[clinic input]
-_hashlib.HASH.copy as EVP_copy
+_hashlib.HASH.copy
Return a copy of the hash object.
[clinic start generated code]*/
static PyObject *
-EVP_copy_impl(EVPobject *self)
-/*[clinic end generated code: output=b370c21cdb8ca0b4 input=31455b6a3e638069]*/
+_hashlib_HASH_copy_impl(HASHobject *self)
+/*[clinic end generated code: output=2545541af18d53d7 input=814b19202cd08a26]*/
{
- EVPobject *newobj;
+ HASHobject *newobj;
- if ((newobj = newEVPobject(Py_TYPE(self))) == NULL)
+ if ((newobj = new_hash_object(Py_TYPE(self))) == NULL)
return NULL;
- if (!locked_EVP_MD_CTX_copy(newobj->ctx, self)) {
+ if (!_hashlib_HASH_copy_locked(self, newobj->ctx)) {
Py_DECREF(newobj);
notify_ssl_error_occurred();
return NULL;
@@ -584,14 +597,14 @@ EVP_copy_impl(EVPobject *self)
}
/*[clinic input]
-_hashlib.HASH.digest as EVP_digest
+_hashlib.HASH.digest
Return the digest value as a bytes object.
[clinic start generated code]*/
static PyObject *
-EVP_digest_impl(EVPobject *self)
-/*[clinic end generated code: output=0f6a3a0da46dc12d input=03561809a419bf00]*/
+_hashlib_HASH_digest_impl(HASHobject *self)
+/*[clinic end generated code: output=3fc6f9671d712850 input=d8d528d6e50af0de]*/
{
unsigned char digest[EVP_MAX_MD_SIZE];
EVP_MD_CTX *temp_ctx;
@@ -604,7 +617,7 @@ EVP_digest_impl(EVPobject *self)
return NULL;
}
- if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
+ if (!_hashlib_HASH_copy_locked(self, temp_ctx)) {
goto error;
}
digest_size = EVP_MD_CTX_size(temp_ctx);
@@ -623,14 +636,14 @@ error:
}
/*[clinic input]
-_hashlib.HASH.hexdigest as EVP_hexdigest
+_hashlib.HASH.hexdigest
Return the digest value as a string of hexadecimal digits.
[clinic start generated code]*/
static PyObject *
-EVP_hexdigest_impl(EVPobject *self)
-/*[clinic end generated code: output=18e6decbaf197296 input=aff9cf0e4c741a9a]*/
+_hashlib_HASH_hexdigest_impl(HASHobject *self)
+/*[clinic end generated code: output=1b8e60d9711e7f4d input=ae7553f78f8372d8]*/
{
unsigned char digest[EVP_MAX_MD_SIZE];
EVP_MD_CTX *temp_ctx;
@@ -643,7 +656,7 @@ EVP_hexdigest_impl(EVPobject *self)
}
/* Get the raw (binary) digest value */
- if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
+ if (!_hashlib_HASH_copy_locked(self, temp_ctx)) {
goto error;
}
digest_size = EVP_MD_CTX_size(temp_ctx);
@@ -662,7 +675,7 @@ error:
}
/*[clinic input]
-_hashlib.HASH.update as EVP_update
+_hashlib.HASH.update
obj: object
/
@@ -671,8 +684,8 @@ Update this hash object's state with the provided string.
[clinic start generated code]*/
static PyObject *
-EVP_update_impl(EVPobject *self, PyObject *obj)
-/*[clinic end generated code: output=d56f91c68348f95f input=9b30ec848f015501]*/
+_hashlib_HASH_update_impl(HASHobject *self, PyObject *obj)
+/*[clinic end generated code: output=62ad989754946b86 input=aa1ce20e3f92ceb6]*/
{
int result;
Py_buffer view;
@@ -685,11 +698,11 @@ EVP_update_impl(EVPobject *self, PyObject *obj)
if (self->use_mutex) {
Py_BEGIN_ALLOW_THREADS
PyMutex_Lock(&self->mutex);
- result = EVP_hash(self, view.buf, view.len);
+ result = _hashlib_HASH_hash(self, view.buf, view.len);
PyMutex_Unlock(&self->mutex);
Py_END_ALLOW_THREADS
} else {
- result = EVP_hash(self, view.buf, view.len);
+ result = _hashlib_HASH_hash(self, view.buf, view.len);
}
PyBuffer_Release(&view);
@@ -699,54 +712,54 @@ EVP_update_impl(EVPobject *self, PyObject *obj)
Py_RETURN_NONE;
}
-static PyMethodDef EVP_methods[] = {
- EVP_UPDATE_METHODDEF
- EVP_DIGEST_METHODDEF
- EVP_HEXDIGEST_METHODDEF
- EVP_COPY_METHODDEF
+static PyMethodDef HASH_methods[] = {
+ _HASHLIB_HASH_COPY_METHODDEF
+ _HASHLIB_HASH_DIGEST_METHODDEF
+ _HASHLIB_HASH_HEXDIGEST_METHODDEF
+ _HASHLIB_HASH_UPDATE_METHODDEF
{NULL, NULL} /* sentinel */
};
static PyObject *
-EVP_get_block_size(PyObject *op, void *Py_UNUSED(closure))
+_hashlib_HASH_get_blocksize(PyObject *op, void *Py_UNUSED(closure))
{
- EVPobject *self = EVPobject_CAST(op);
+ HASHobject *self = HASHobject_CAST(op);
long block_size = EVP_MD_CTX_block_size(self->ctx);
return PyLong_FromLong(block_size);
}
static PyObject *
-EVP_get_digest_size(PyObject *op, void *Py_UNUSED(closure))
+_hashlib_HASH_get_digestsize(PyObject *op, void *Py_UNUSED(closure))
{
- EVPobject *self = EVPobject_CAST(op);
+ HASHobject *self = HASHobject_CAST(op);
long size = EVP_MD_CTX_size(self->ctx);
return PyLong_FromLong(size);
}
static PyObject *
-EVP_get_name(PyObject *op, void *Py_UNUSED(closure))
+_hashlib_HASH_get_name(PyObject *op, void *Py_UNUSED(closure))
{
- EVPobject *self = EVPobject_CAST(op);
+ HASHobject *self = HASHobject_CAST(op);
const EVP_MD *md = EVP_MD_CTX_md(self->ctx);
if (md == NULL) {
notify_ssl_error_occurred();
return NULL;
}
- return py_digest_name(md);
+ return get_openssl_evp_md_name(md);
}
-static PyGetSetDef EVP_getseters[] = {
- {"digest_size", EVP_get_digest_size, NULL, NULL, NULL},
- {"block_size", EVP_get_block_size, NULL, NULL, NULL},
- {"name", EVP_get_name, NULL, NULL, PyDoc_STR("algorithm name.")},
+static PyGetSetDef HASH_getsets[] = {
+ {"digest_size", _hashlib_HASH_get_digestsize, NULL, NULL, NULL},
+ {"block_size", _hashlib_HASH_get_blocksize, NULL, NULL, NULL},
+ {"name", _hashlib_HASH_get_name, NULL, NULL, PyDoc_STR("algorithm name.")},
{NULL} /* Sentinel */
};
static PyObject *
-EVP_repr(PyObject *self)
+_hashlib_HASH_repr(PyObject *self)
{
- PyObject *name = EVP_get_name(self, NULL);
+ PyObject *name = _hashlib_HASH_get_name(self, NULL);
if (name == NULL) {
return NULL;
}
@@ -756,7 +769,7 @@ EVP_repr(PyObject *self)
return repr;
}
-PyDoc_STRVAR(hashtype_doc,
+PyDoc_STRVAR(HASHobject_type_doc,
"HASH(name, string=b\'\')\n"
"--\n"
"\n"
@@ -774,27 +787,31 @@ PyDoc_STRVAR(hashtype_doc,
"name -- the hash algorithm being used by this object\n"
"digest_size -- number of bytes in this hashes output");
-static PyType_Slot EVPtype_slots[] = {
- {Py_tp_dealloc, EVP_dealloc},
- {Py_tp_repr, EVP_repr},
- {Py_tp_doc, (char *)hashtype_doc},
- {Py_tp_methods, EVP_methods},
- {Py_tp_getset, EVP_getseters},
+static PyType_Slot HASHobject_type_slots[] = {
+ {Py_tp_dealloc, _hashlib_HASH_dealloc},
+ {Py_tp_repr, _hashlib_HASH_repr},
+ {Py_tp_doc, (char *)HASHobject_type_doc},
+ {Py_tp_methods, HASH_methods},
+ {Py_tp_getset, HASH_getsets},
{0, 0},
};
-static PyType_Spec EVPtype_spec = {
- "_hashlib.HASH", /*tp_name*/
- sizeof(EVPobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
- EVPtype_slots
+static PyType_Spec HASHobject_type_spec = {
+ .name = "_hashlib.HASH",
+ .basicsize = sizeof(HASHobject),
+ .flags = (
+ Py_TPFLAGS_DEFAULT
+ | Py_TPFLAGS_BASETYPE
+ | Py_TPFLAGS_DISALLOW_INSTANTIATION
+ | Py_TPFLAGS_IMMUTABLETYPE
+ ),
+ .slots = HASHobject_type_slots
};
#ifdef PY_OPENSSL_HAS_SHAKE
/*[clinic input]
-_hashlib.HASHXOF.digest as EVPXOF_digest
+_hashlib.HASHXOF.digest
length: Py_ssize_t
@@ -802,8 +819,8 @@ Return the digest value as a bytes object.
[clinic start generated code]*/
static PyObject *
-EVPXOF_digest_impl(EVPobject *self, Py_ssize_t length)
-/*[clinic end generated code: output=ef9320c23280efad input=816a6537cea3d1db]*/
+_hashlib_HASHXOF_digest_impl(HASHobject *self, Py_ssize_t length)
+/*[clinic end generated code: output=dcb09335dd2fe908 input=3eb034ce03c55b21]*/
{
EVP_MD_CTX *temp_ctx;
PyObject *retval = PyBytes_FromStringAndSize(NULL, length);
@@ -819,7 +836,7 @@ EVPXOF_digest_impl(EVPobject *self, Py_ssize_t length)
return NULL;
}
- if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
+ if (!_hashlib_HASH_copy_locked(self, temp_ctx)) {
goto error;
}
if (!EVP_DigestFinalXOF(temp_ctx,
@@ -840,7 +857,7 @@ error:
}
/*[clinic input]
-_hashlib.HASHXOF.hexdigest as EVPXOF_hexdigest
+_hashlib.HASHXOF.hexdigest
length: Py_ssize_t
@@ -848,8 +865,8 @@ Return the digest value as a string of hexadecimal digits.
[clinic start generated code]*/
static PyObject *
-EVPXOF_hexdigest_impl(EVPobject *self, Py_ssize_t length)
-/*[clinic end generated code: output=eb3e6ee7788bf5b2 input=5f9d6a8f269e34df]*/
+_hashlib_HASHXOF_hexdigest_impl(HASHobject *self, Py_ssize_t length)
+/*[clinic end generated code: output=519431cafa014f39 input=0e58f7238adb7ab8]*/
{
unsigned char *digest;
EVP_MD_CTX *temp_ctx;
@@ -869,7 +886,7 @@ EVPXOF_hexdigest_impl(EVPobject *self, Py_ssize_t length)
}
/* Get the raw (binary) digest value */
- if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) {
+ if (!_hashlib_HASH_copy_locked(self, temp_ctx)) {
goto error;
}
if (!EVP_DigestFinalXOF(temp_ctx, digest, length)) {
@@ -889,25 +906,26 @@ error:
return NULL;
}
-static PyMethodDef EVPXOF_methods[] = {
- EVPXOF_DIGEST_METHODDEF
- EVPXOF_HEXDIGEST_METHODDEF
+static PyMethodDef HASHXOFobject_methods[] = {
+ _HASHLIB_HASHXOF_DIGEST_METHODDEF
+ _HASHLIB_HASHXOF_HEXDIGEST_METHODDEF
{NULL, NULL} /* sentinel */
};
static PyObject *
-EVPXOF_get_digest_size(PyObject *Py_UNUSED(self), void *Py_UNUSED(closure))
+_hashlib_HASHXOF_digest_size(PyObject *Py_UNUSED(self),
+ void *Py_UNUSED(closure))
{
return PyLong_FromLong(0);
}
-static PyGetSetDef EVPXOF_getseters[] = {
- {"digest_size", EVPXOF_get_digest_size, NULL, NULL, NULL},
+static PyGetSetDef HASHXOFobject_getsets[] = {
+ {"digest_size", _hashlib_HASHXOF_digest_size, NULL, NULL, NULL},
{NULL} /* Sentinel */
};
-PyDoc_STRVAR(hashxoftype_doc,
+PyDoc_STRVAR(HASHXOFobject_type_doc,
"HASHXOF(name, string=b\'\')\n"
"--\n"
"\n"
@@ -925,38 +943,42 @@ PyDoc_STRVAR(hashxoftype_doc,
"name -- the hash algorithm being used by this object\n"
"digest_size -- number of bytes in this hashes output");
-static PyType_Slot EVPXOFtype_slots[] = {
- {Py_tp_doc, (char *)hashxoftype_doc},
- {Py_tp_methods, EVPXOF_methods},
- {Py_tp_getset, EVPXOF_getseters},
+static PyType_Slot HASHXOFobject_type_slots[] = {
+ {Py_tp_doc, (char *)HASHXOFobject_type_doc},
+ {Py_tp_methods, HASHXOFobject_methods},
+ {Py_tp_getset, HASHXOFobject_getsets},
{0, 0},
};
-static PyType_Spec EVPXOFtype_spec = {
- "_hashlib.HASHXOF", /*tp_name*/
- sizeof(EVPobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
- EVPXOFtype_slots
+static PyType_Spec HASHXOFobject_type_spec = {
+ .name = "_hashlib.HASHXOF",
+ .basicsize = sizeof(HASHobject),
+ .flags = (
+ Py_TPFLAGS_DEFAULT
+ | Py_TPFLAGS_BASETYPE
+ | Py_TPFLAGS_DISALLOW_INSTANTIATION
+ | Py_TPFLAGS_IMMUTABLETYPE
+ ),
+ .slots = HASHXOFobject_type_slots
};
#endif
-static PyObject*
-py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj,
- int usedforsecurity)
+static PyObject *
+_hashlib_HASH(PyObject *module, const char *digestname, PyObject *data_obj,
+ int usedforsecurity)
{
Py_buffer view = { 0 };
PY_EVP_MD *digest = NULL;
PyTypeObject *type;
- EVPobject *self = NULL;
+ HASHobject *self = NULL;
if (data_obj != NULL) {
GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view);
}
- digest = py_digest_by_name(
+ digest = get_openssl_evp_md_by_utf8name(
module, digestname, usedforsecurity ? Py_ht_evp : Py_ht_evp_nosecurity
);
if (digest == NULL) {
@@ -964,12 +986,12 @@ py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj,
}
if ((EVP_MD_flags(digest) & EVP_MD_FLAG_XOF) == EVP_MD_FLAG_XOF) {
- type = get_hashlib_state(module)->EVPXOFtype;
+ type = get_hashlib_state(module)->HASHXOF_type;
} else {
- type = get_hashlib_state(module)->EVPtype;
+ type = get_hashlib_state(module)->HASH_type;
}
- self = newEVPobject(type);
+ self = new_hash_object(type);
if (self == NULL) {
goto exit;
}
@@ -994,10 +1016,10 @@ py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj,
/* We do not initialize self->lock here as this is the constructor
* where it is not yet possible to have concurrent access. */
Py_BEGIN_ALLOW_THREADS
- result = EVP_hash(self, view.buf, view.len);
+ result = _hashlib_HASH_hash(self, view.buf, view.len);
Py_END_ALLOW_THREADS
} else {
- result = EVP_hash(self, view.buf, view.len);
+ result = _hashlib_HASH_hash(self, view.buf, view.len);
}
if (result == -1) {
assert(PyErr_Occurred());
@@ -1017,16 +1039,25 @@ exit:
return (PyObject *)self;
}
+#define CALL_HASHLIB_NEW(MODULE, NAME, DATA, STRING, USEDFORSECURITY) \
+ do { \
+ PyObject *data_obj; \
+ if (_Py_hashlib_data_argument(&data_obj, DATA, STRING) < 0) { \
+ return NULL; \
+ } \
+ return _hashlib_HASH(MODULE, NAME, data_obj, USEDFORSECURITY); \
+ } while (0)
/* The module-level function: new() */
/*[clinic input]
-_hashlib.new as EVP_new
+_hashlib.new as _hashlib_HASH_new
- name as name_obj: object
- string as data_obj: object(c_default="NULL") = b''
+ name: str
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Return a new hash object using the named algorithm.
@@ -1037,136 +1068,137 @@ The MD5 and SHA1 algorithms are always supported.
[clinic start generated code]*/
static PyObject *
-EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=ddd5053f92dffe90 input=c24554d0337be1b0]*/
+_hashlib_HASH_new_impl(PyObject *module, const char *name, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=b905aaf9840c1bbd input=c34af6c6e696d44e]*/
{
- char *name;
- if (!PyArg_Parse(name_obj, "s", &name)) {
- PyErr_SetString(PyExc_TypeError, "name must be a string");
- return NULL;
- }
- return py_evp_fromname(module, name, data_obj, usedforsecurity);
+ CALL_HASHLIB_NEW(module, name, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_md5
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a md5 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=87b0186440a44f8c input=990e36d5e689b16e]*/
+_hashlib_openssl_md5_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=ca8cf184d90f7432 input=e7c0adbd6a867db1]*/
{
- return py_evp_fromname(module, Py_hash_md5, data_obj, usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_md5, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_sha1
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha1 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=6813024cf690670d input=948f2f4b6deabc10]*/
+_hashlib_openssl_sha1_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=1736fb7b310d64be input=f7e5bb1711e952d8]*/
{
- return py_evp_fromname(module, Py_hash_sha1, data_obj, usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha1, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_sha224
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha224 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=a2dfe7cc4eb14ebb input=f9272821fadca505]*/
+_hashlib_openssl_sha224_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=0d6ff57be5e5c140 input=3820fff7ed3a53b8]*/
{
- return py_evp_fromname(module, Py_hash_sha224, data_obj, usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha224, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_sha256
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha256 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=1f874a34870f0a68 input=549fad9d2930d4c5]*/
+_hashlib_openssl_sha256_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=412ea7111555b6e7 input=9a2f115cf1f7e0eb]*/
{
- return py_evp_fromname(module, Py_hash_sha256, data_obj, usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha256, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_sha384
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha384 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=58529eff9ca457b2 input=48601a6e3bf14ad7]*/
+_hashlib_openssl_sha384_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=2e0dc395b59ed726 input=1ea48f6f01e77cfb]*/
{
- return py_evp_fromname(module, Py_hash_sha384, data_obj, usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha384, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_sha512
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha512 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=2c744c9e4a40d5f6 input=c5c46a2a817aa98f]*/
+_hashlib_openssl_sha512_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=4bdd760388dbfc0f input=3cf56903e07d1f5c]*/
{
- return py_evp_fromname(module, Py_hash_sha512, data_obj, usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha512, data, string, usedforsecurity);
}
@@ -1175,77 +1207,81 @@ _hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj,
/*[clinic input]
_hashlib.openssl_sha3_224
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha3-224 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=144641c1d144b974 input=e3a01b2888916157]*/
+_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=6d8dc2a924f3ba35 input=7f14f16a9f6a3158]*/
{
- return py_evp_fromname(module, Py_hash_sha3_224, data_obj, usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha3_224, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_sha3_256
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha3-256 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=c61f1ab772d06668 input=e2908126c1b6deed]*/
+_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=9e520f537b3a4622 input=7987150939d5e352]*/
{
- return py_evp_fromname(module, Py_hash_sha3_256, data_obj , usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha3_256, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_sha3_384
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha3-384 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=f68e4846858cf0ee input=ec0edf5c792f8252]*/
+_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=d239ba0463fd6138 input=fc943401f67e3b81]*/
{
- return py_evp_fromname(module, Py_hash_sha3_384, data_obj , usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha3_384, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_sha3_512
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a sha3-512 hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=2eede478c159354a input=64e2cc0c094d56f4]*/
+_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=17662f21038c2278 input=6601ddd2c6c1516d]*/
{
- return py_evp_fromname(module, Py_hash_sha3_512, data_obj , usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_sha3_512, data, string, usedforsecurity);
}
#endif /* PY_OPENSSL_HAS_SHA3 */
@@ -1253,42 +1289,46 @@ _hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj,
/*[clinic input]
_hashlib.openssl_shake_128
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a shake-128 variable hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=bc49cdd8ada1fa97 input=6c9d67440eb33ec8]*/
+_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=4e6afed8d18980ad input=373c3f1c93d87b37]*/
{
- return py_evp_fromname(module, Py_hash_shake_128, data_obj , usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_shake_128, data, string, usedforsecurity);
}
/*[clinic input]
_hashlib.openssl_shake_256
- string as data_obj: object(py_default="b''") = NULL
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Returns a shake-256 variable hash object; optionally initialized with a string
[clinic start generated code]*/
static PyObject *
-_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity)
-/*[clinic end generated code: output=358d213be8852df7 input=479cbe9fefd4a9f8]*/
+_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string)
+/*[clinic end generated code: output=62481bce4a77d16c input=101c139ea2ddfcbf]*/
{
- return py_evp_fromname(module, Py_hash_shake_256, data_obj , usedforsecurity);
+ CALL_HASHLIB_NEW(module, Py_hash_shake_256, data, string, usedforsecurity);
}
#endif /* PY_OPENSSL_HAS_SHAKE */
+#undef CALL_HASHLIB_NEW
+
/*[clinic input]
_hashlib.pbkdf2_hmac as pbkdf2_hmac
@@ -1312,7 +1352,7 @@ pbkdf2_hmac_impl(PyObject *module, const char *hash_name,
long dklen;
int retval;
- PY_EVP_MD *digest = py_digest_by_name(module, hash_name, Py_ht_pbkdf2);
+ PY_EVP_MD *digest = get_openssl_evp_md_by_utf8name(module, hash_name, Py_ht_pbkdf2);
if (digest == NULL) {
goto end;
}
@@ -1514,7 +1554,7 @@ _hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key,
return NULL;
}
- evp = py_digest_by_digestmod(module, digest, Py_ht_mac);
+ evp = get_openssl_evp_md(module, digest, Py_ht_mac);
if (evp == NULL) {
return NULL;
}
@@ -1583,7 +1623,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj,
return NULL;
}
- digest = py_digest_by_digestmod(module, digestmod, Py_ht_mac);
+ digest = get_openssl_evp_md(module, digestmod, Py_ht_mac);
if (digest == NULL) {
return NULL;
}
@@ -1740,7 +1780,7 @@ _hmac_repr(PyObject *op)
if (md == NULL) {
return NULL;
}
- PyObject *digest_name = py_digest_name(md);
+ PyObject *digest_name = get_openssl_evp_md_name(md);
if (digest_name == NULL) {
return NULL;
}
@@ -1860,7 +1900,7 @@ _hashlib_hmac_get_name(PyObject *op, void *Py_UNUSED(closure))
if (md == NULL) {
return NULL;
}
- PyObject *digest_name = py_digest_name(md);
+ PyObject *digest_name = get_openssl_evp_md_name(md);
if (digest_name == NULL) {
return NULL;
}
@@ -1926,7 +1966,7 @@ typedef struct _internal_name_mapper_state {
/* A callback function to pass to OpenSSL's OBJ_NAME_do_all(...) */
static void
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#ifdef Py_HAS_OPENSSL3_SUPPORT
_openssl_hash_name_mapper(EVP_MD *md, void *arg)
#else
_openssl_hash_name_mapper(const EVP_MD *md, const char *from,
@@ -1942,7 +1982,7 @@ _openssl_hash_name_mapper(const EVP_MD *md, const char *from,
return;
}
- py_name = py_digest_name(md);
+ py_name = get_openssl_evp_md_name(md);
if (py_name == NULL) {
state->error = 1;
} else {
@@ -1966,7 +2006,7 @@ hashlib_md_meth_names(PyObject *module)
return -1;
}
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#ifdef Py_HAS_OPENSSL3_SUPPORT
// get algorithms from all activated providers in default context
EVP_MD_do_all_provided(NULL, &_openssl_hash_name_mapper, &state);
#else
@@ -1999,7 +2039,7 @@ _hashlib_get_fips_mode_impl(PyObject *module)
/*[clinic end generated code: output=87eece1bab4d3fa9 input=2db61538c41c6fef]*/
{
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+#ifdef Py_HAS_OPENSSL3_SUPPORT
return EVP_default_properties_is_fips_enabled(NULL);
#else
ERR_clear_error();
@@ -2134,7 +2174,7 @@ _hashlib_compare_digest_impl(PyObject *module, PyObject *a, PyObject *b)
/* List of functions exported by this module */
static struct PyMethodDef EVP_functions[] = {
- EVP_NEW_METHODDEF
+ _HASHLIB_HASH_NEW_METHODDEF
PBKDF2_HMAC_METHODDEF
_HASHLIB_SCRYPT_METHODDEF
_HASHLIB_GET_FIPS_MODE_METHODDEF
@@ -2163,10 +2203,10 @@ static int
hashlib_traverse(PyObject *m, visitproc visit, void *arg)
{
_hashlibstate *state = get_hashlib_state(m);
- Py_VISIT(state->EVPtype);
+ Py_VISIT(state->HASH_type);
Py_VISIT(state->HMACtype);
#ifdef PY_OPENSSL_HAS_SHAKE
- Py_VISIT(state->EVPXOFtype);
+ Py_VISIT(state->HASHXOF_type);
#endif
Py_VISIT(state->constructs);
Py_VISIT(state->unsupported_digestmod_error);
@@ -2177,10 +2217,10 @@ static int
hashlib_clear(PyObject *m)
{
_hashlibstate *state = get_hashlib_state(m);
- Py_CLEAR(state->EVPtype);
+ Py_CLEAR(state->HASH_type);
Py_CLEAR(state->HMACtype);
#ifdef PY_OPENSSL_HAS_SHAKE
- Py_CLEAR(state->EVPXOFtype);
+ Py_CLEAR(state->HASHXOF_type);
#endif
Py_CLEAR(state->constructs);
Py_CLEAR(state->unsupported_digestmod_error);
@@ -2214,37 +2254,37 @@ hashlib_init_hashtable(PyObject *module)
}
static int
-hashlib_init_evptype(PyObject *module)
+hashlib_init_HASH_type(PyObject *module)
{
_hashlibstate *state = get_hashlib_state(module);
- state->EVPtype = (PyTypeObject *)PyType_FromSpec(&EVPtype_spec);
- if (state->EVPtype == NULL) {
+ state->HASH_type = (PyTypeObject *)PyType_FromSpec(&HASHobject_type_spec);
+ if (state->HASH_type == NULL) {
return -1;
}
- if (PyModule_AddType(module, state->EVPtype) < 0) {
+ if (PyModule_AddType(module, state->HASH_type) < 0) {
return -1;
}
return 0;
}
static int
-hashlib_init_evpxoftype(PyObject *module)
+hashlib_init_HASHXOF_type(PyObject *module)
{
#ifdef PY_OPENSSL_HAS_SHAKE
_hashlibstate *state = get_hashlib_state(module);
- if (state->EVPtype == NULL) {
+ if (state->HASH_type == NULL) {
return -1;
}
- state->EVPXOFtype = (PyTypeObject *)PyType_FromSpecWithBases(
- &EVPXOFtype_spec, (PyObject *)state->EVPtype
+ state->HASHXOF_type = (PyTypeObject *)PyType_FromSpecWithBases(
+ &HASHXOFobject_type_spec, (PyObject *)state->HASH_type
);
- if (state->EVPXOFtype == NULL) {
+ if (state->HASHXOF_type == NULL) {
return -1;
}
- if (PyModule_AddType(module, state->EVPXOFtype) < 0) {
+ if (PyModule_AddType(module, state->HASHXOF_type) < 0) {
return -1;
}
#endif
@@ -2341,8 +2381,8 @@ hashlib_constants(PyObject *module)
static PyModuleDef_Slot hashlib_slots[] = {
{Py_mod_exec, hashlib_init_hashtable},
- {Py_mod_exec, hashlib_init_evptype},
- {Py_mod_exec, hashlib_init_evpxoftype},
+ {Py_mod_exec, hashlib_init_HASH_type},
+ {Py_mod_exec, hashlib_init_HASHXOF_type},
{Py_mod_exec, hashlib_init_hmactype},
{Py_mod_exec, hashlib_md_meth_names},
{Py_mod_exec, hashlib_init_constructors},
diff --git a/Modules/_interpchannelsmodule.c b/Modules/_interpchannelsmodule.c
index 172cebcaa48..ea2e5f99dfa 100644
--- a/Modules/_interpchannelsmodule.c
+++ b/Modules/_interpchannelsmodule.c
@@ -20,9 +20,11 @@
#endif
#define REGISTERS_HEAP_TYPES
+#define HAS_FALLBACK
#define HAS_UNBOUND_ITEMS
#include "_interpreters_common.h"
#undef HAS_UNBOUND_ITEMS
+#undef HAS_FALLBACK
#undef REGISTERS_HEAP_TYPES
@@ -252,10 +254,10 @@ _get_current_module_state(void)
{
PyObject *mod = _get_current_module();
if (mod == NULL) {
- // XXX import it?
- PyErr_SetString(PyExc_RuntimeError,
- MODULE_NAME_STR " module not imported yet");
- return NULL;
+ mod = PyImport_ImportModule(MODULE_NAME_STR);
+ if (mod == NULL) {
+ return NULL;
+ }
}
module_state *state = get_module_state(mod);
Py_DECREF(mod);
@@ -523,7 +525,7 @@ typedef struct _channelitem {
int64_t interpid;
_PyXIData_t *data;
_waiting_t *waiting;
- int unboundop;
+ unboundop_t unboundop;
struct _channelitem *next;
} _channelitem;
@@ -536,7 +538,7 @@ _channelitem_ID(_channelitem *item)
static void
_channelitem_init(_channelitem *item,
int64_t interpid, _PyXIData_t *data,
- _waiting_t *waiting, int unboundop)
+ _waiting_t *waiting, unboundop_t unboundop)
{
if (interpid < 0) {
interpid = _get_interpid(data);
@@ -583,7 +585,7 @@ _channelitem_clear(_channelitem *item)
static _channelitem *
_channelitem_new(int64_t interpid, _PyXIData_t *data,
- _waiting_t *waiting, int unboundop)
+ _waiting_t *waiting, unboundop_t unboundop)
{
_channelitem *item = GLOBAL_MALLOC(_channelitem);
if (item == NULL) {
@@ -694,7 +696,7 @@ _channelqueue_free(_channelqueue *queue)
static int
_channelqueue_put(_channelqueue *queue,
int64_t interpid, _PyXIData_t *data,
- _waiting_t *waiting, int unboundop)
+ _waiting_t *waiting, unboundop_t unboundop)
{
_channelitem *item = _channelitem_new(interpid, data, waiting, unboundop);
if (item == NULL) {
@@ -798,7 +800,7 @@ _channelqueue_remove(_channelqueue *queue, _channelitem_id_t itemid,
}
queue->count -= 1;
- int unboundop;
+ unboundop_t unboundop;
_channelitem_popped(item, p_data, p_waiting, &unboundop);
}
@@ -1083,16 +1085,18 @@ typedef struct _channel {
PyThread_type_lock mutex;
_channelqueue *queue;
_channelends *ends;
- struct {
- int unboundop;
+ struct _channeldefaults {
+ unboundop_t unboundop;
+ xidata_fallback_t fallback;
} defaults;
int open;
struct _channel_closing *closing;
} _channel_state;
static _channel_state *
-_channel_new(PyThread_type_lock mutex, int unboundop)
+_channel_new(PyThread_type_lock mutex, struct _channeldefaults defaults)
{
+ assert(check_unbound(defaults.unboundop));
_channel_state *chan = GLOBAL_MALLOC(_channel_state);
if (chan == NULL) {
return NULL;
@@ -1109,7 +1113,7 @@ _channel_new(PyThread_type_lock mutex, int unboundop)
GLOBAL_FREE(chan);
return NULL;
}
- chan->defaults.unboundop = unboundop;
+ chan->defaults = defaults;
chan->open = 1;
chan->closing = NULL;
return chan;
@@ -1130,7 +1134,7 @@ _channel_free(_channel_state *chan)
static int
_channel_add(_channel_state *chan, int64_t interpid,
- _PyXIData_t *data, _waiting_t *waiting, int unboundop)
+ _PyXIData_t *data, _waiting_t *waiting, unboundop_t unboundop)
{
int res = -1;
PyThread_acquire_lock(chan->mutex, WAIT_LOCK);
@@ -1611,7 +1615,7 @@ done:
struct channel_id_and_info {
int64_t id;
- int unboundop;
+ struct _channeldefaults defaults;
};
static struct channel_id_and_info *
@@ -1628,7 +1632,7 @@ _channels_list_all(_channels *channels, int64_t *count)
for (int64_t i=0; ref != NULL; ref = ref->next, i++) {
ids[i] = (struct channel_id_and_info){
.id = ref->cid,
- .unboundop = ref->chan->defaults.unboundop,
+ .defaults = ref->chan->defaults,
};
}
*count = channels->numopen;
@@ -1714,13 +1718,13 @@ _channel_finish_closing(_channel_state *chan) {
// Create a new channel.
static int64_t
-channel_create(_channels *channels, int unboundop)
+channel_create(_channels *channels, struct _channeldefaults defaults)
{
PyThread_type_lock mutex = PyThread_allocate_lock();
if (mutex == NULL) {
return ERR_CHANNEL_MUTEX_INIT;
}
- _channel_state *chan = _channel_new(mutex, unboundop);
+ _channel_state *chan = _channel_new(mutex, defaults);
if (chan == NULL) {
PyThread_free_lock(mutex);
return -1;
@@ -1752,7 +1756,7 @@ channel_destroy(_channels *channels, int64_t cid)
// Optionally request to be notified when it is received.
static int
channel_send(_channels *channels, int64_t cid, PyObject *obj,
- _waiting_t *waiting, int unboundop)
+ _waiting_t *waiting, unboundop_t unboundop, xidata_fallback_t fallback)
{
PyThreadState *tstate = _PyThreadState_GET();
PyInterpreterState *interp = tstate->interp;
@@ -1779,7 +1783,7 @@ channel_send(_channels *channels, int64_t cid, PyObject *obj,
PyThread_release_lock(mutex);
return -1;
}
- if (_PyObject_GetXIData(tstate, obj, data) != 0) {
+ if (_PyObject_GetXIData(tstate, obj, fallback, data) != 0) {
PyThread_release_lock(mutex);
GLOBAL_FREE(data);
return -1;
@@ -1823,7 +1827,8 @@ channel_clear_sent(_channels *channels, int64_t cid, _waiting_t *waiting)
// Like channel_send(), but strictly wait for the object to be received.
static int
channel_send_wait(_channels *channels, int64_t cid, PyObject *obj,
- int unboundop, PY_TIMEOUT_T timeout)
+ unboundop_t unboundop, PY_TIMEOUT_T timeout,
+ xidata_fallback_t fallback)
{
// We use a stack variable here, so we must ensure that &waiting
// is not held by any channel item at the point this function exits.
@@ -1834,7 +1839,7 @@ channel_send_wait(_channels *channels, int64_t cid, PyObject *obj,
}
/* Queue up the object. */
- int res = channel_send(channels, cid, obj, &waiting, unboundop);
+ int res = channel_send(channels, cid, obj, &waiting, unboundop, fallback);
if (res < 0) {
assert(waiting.status == WAITING_NO_STATUS);
goto finally;
@@ -2006,6 +2011,20 @@ channel_is_associated(_channels *channels, int64_t cid, int64_t interpid,
}
static int
+channel_get_defaults(_channels *channels, int64_t cid, struct _channeldefaults *defaults)
+{
+ PyThread_type_lock mutex = NULL;
+ _channel_state *channel = NULL;
+ int err = _channels_lookup(channels, cid, &mutex, &channel);
+ if (err != 0) {
+ return err;
+ }
+ *defaults = channel->defaults;
+ PyThread_release_lock(mutex);
+ return 0;
+}
+
+static int
_channel_get_count(_channels *channels, int64_t cid, Py_ssize_t *p_count)
{
PyThread_type_lock mutex = NULL;
@@ -2694,7 +2713,7 @@ add_channelid_type(PyObject *mod)
Py_DECREF(cls);
return NULL;
}
- if (ensure_xid_class(cls, _channelid_shared) < 0) {
+ if (ensure_xid_class(cls, GETDATA(_channelid_shared)) < 0) {
Py_DECREF(cls);
return NULL;
}
@@ -2797,12 +2816,12 @@ set_channelend_types(PyObject *mod, PyTypeObject *send, PyTypeObject *recv)
// Add and register the types.
state->send_channel_type = (PyTypeObject *)Py_NewRef(send);
state->recv_channel_type = (PyTypeObject *)Py_NewRef(recv);
- if (ensure_xid_class(send, _channelend_shared) < 0) {
+ if (ensure_xid_class(send, GETDATA(_channelend_shared)) < 0) {
Py_CLEAR(state->send_channel_type);
Py_CLEAR(state->recv_channel_type);
return -1;
}
- if (ensure_xid_class(recv, _channelend_shared) < 0) {
+ if (ensure_xid_class(recv, GETDATA(_channelend_shared)) < 0) {
(void)clear_xid_class(state->send_channel_type);
Py_CLEAR(state->send_channel_type);
Py_CLEAR(state->recv_channel_type);
@@ -2881,20 +2900,27 @@ clear_interpreter(void *data)
static PyObject *
channelsmod_create(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"unboundop", NULL};
- int unboundop;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "i:create", kwlist,
- &unboundop))
+ static char *kwlist[] = {"unboundop", "fallback", NULL};
+ int unboundarg = -1;
+ int fallbackarg = -1;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:create", kwlist,
+ &unboundarg, &fallbackarg))
+ {
+ return NULL;
+ }
+ struct _channeldefaults defaults = {0};
+ if (resolve_unboundop(unboundarg, UNBOUND_REPLACE,
+ &defaults.unboundop) < 0)
{
return NULL;
}
- if (!check_unbound(unboundop)) {
- PyErr_Format(PyExc_ValueError,
- "unsupported unboundop %d", unboundop);
+ if (resolve_fallback(fallbackarg, _PyXIDATA_FULL_FALLBACK,
+ &defaults.fallback) < 0)
+ {
return NULL;
}
- int64_t cid = channel_create(&_globals.channels, unboundop);
+ int64_t cid = channel_create(&_globals.channels, defaults);
if (cid < 0) {
(void)handle_channel_error(-1, self, cid);
return NULL;
@@ -2987,7 +3013,9 @@ channelsmod_list_all(PyObject *self, PyObject *Py_UNUSED(ignored))
}
assert(cidobj != NULL);
- PyObject *item = Py_BuildValue("Oi", cidobj, cur->unboundop);
+ PyObject *item = Py_BuildValue("Oii", cidobj,
+ cur->defaults.unboundop,
+ cur->defaults.fallback);
Py_DECREF(cidobj);
if (item == NULL) {
Py_SETREF(ids, NULL);
@@ -3075,40 +3103,54 @@ receive end.");
static PyObject *
channelsmod_send(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"cid", "obj", "unboundop", "blocking", "timeout",
- NULL};
+ static char *kwlist[] = {"cid", "obj", "unboundop", "fallback",
+ "blocking", "timeout", NULL};
struct channel_id_converter_data cid_data = {
.module = self,
};
PyObject *obj;
- int unboundop = UNBOUND_REPLACE;
+ int unboundarg = -1;
+ int fallbackarg = -1;
int blocking = 1;
PyObject *timeout_obj = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O|i$pO:channel_send", kwlist,
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ "O&O|ii$pO:channel_send", kwlist,
channel_id_converter, &cid_data, &obj,
- &unboundop, &blocking, &timeout_obj))
+ &unboundarg, &fallbackarg,
+ &blocking, &timeout_obj))
{
return NULL;
}
- if (!check_unbound(unboundop)) {
- PyErr_Format(PyExc_ValueError,
- "unsupported unboundop %d", unboundop);
- return NULL;
- }
-
int64_t cid = cid_data.cid;
PY_TIMEOUT_T timeout;
if (PyThread_ParseTimeoutArg(timeout_obj, blocking, &timeout) < 0) {
return NULL;
}
+ struct _channeldefaults defaults = {-1, -1};
+ if (unboundarg < 0 || fallbackarg < 0) {
+ int err = channel_get_defaults(&_globals.channels, cid, &defaults);
+ if (handle_channel_error(err, self, cid)) {
+ return NULL;
+ }
+ }
+ unboundop_t unboundop;
+ if (resolve_unboundop(unboundarg, defaults.unboundop, &unboundop) < 0) {
+ return NULL;
+ }
+ xidata_fallback_t fallback;
+ if (resolve_fallback(fallbackarg, defaults.fallback, &fallback) < 0) {
+ return NULL;
+ }
/* Queue up the object. */
int err = 0;
if (blocking) {
- err = channel_send_wait(&_globals.channels, cid, obj, unboundop, timeout);
+ err = channel_send_wait(
+ &_globals.channels, cid, obj, unboundop, timeout, fallback);
}
else {
- err = channel_send(&_globals.channels, cid, obj, NULL, unboundop);
+ err = channel_send(
+ &_globals.channels, cid, obj, NULL, unboundop, fallback);
}
if (handle_channel_error(err, self, cid)) {
return NULL;
@@ -3126,32 +3168,44 @@ By default this waits for the object to be received.");
static PyObject *
channelsmod_send_buffer(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"cid", "obj", "unboundop", "blocking", "timeout",
- NULL};
+ static char *kwlist[] = {"cid", "obj", "unboundop", "fallback",
+ "blocking", "timeout", NULL};
struct channel_id_converter_data cid_data = {
.module = self,
};
PyObject *obj;
- int unboundop = UNBOUND_REPLACE;
- int blocking = 1;
+ int unboundarg = -1;
+ int fallbackarg = -1;
+ int blocking = -1;
PyObject *timeout_obj = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds,
- "O&O|i$pO:channel_send_buffer", kwlist,
+ "O&O|ii$pO:channel_send_buffer", kwlist,
channel_id_converter, &cid_data, &obj,
- &unboundop, &blocking, &timeout_obj)) {
- return NULL;
- }
- if (!check_unbound(unboundop)) {
- PyErr_Format(PyExc_ValueError,
- "unsupported unboundop %d", unboundop);
+ &unboundarg, &fallbackarg,
+ &blocking, &timeout_obj))
+ {
return NULL;
}
-
int64_t cid = cid_data.cid;
PY_TIMEOUT_T timeout;
if (PyThread_ParseTimeoutArg(timeout_obj, blocking, &timeout) < 0) {
return NULL;
}
+ struct _channeldefaults defaults = {-1, -1};
+ if (unboundarg < 0 || fallbackarg < 0) {
+ int err = channel_get_defaults(&_globals.channels, cid, &defaults);
+ if (handle_channel_error(err, self, cid)) {
+ return NULL;
+ }
+ }
+ unboundop_t unboundop;
+ if (resolve_unboundop(unboundarg, defaults.unboundop, &unboundop) < 0) {
+ return NULL;
+ }
+ xidata_fallback_t fallback;
+ if (resolve_fallback(fallbackarg, defaults.fallback, &fallback) < 0) {
+ return NULL;
+ }
PyObject *tempobj = PyMemoryView_FromObject(obj);
if (tempobj == NULL) {
@@ -3162,10 +3216,11 @@ channelsmod_send_buffer(PyObject *self, PyObject *args, PyObject *kwds)
int err = 0;
if (blocking) {
err = channel_send_wait(
- &_globals.channels, cid, tempobj, unboundop, timeout);
+ &_globals.channels, cid, tempobj, unboundop, timeout, fallback);
}
else {
- err = channel_send(&_globals.channels, cid, tempobj, NULL, unboundop);
+ err = channel_send(
+ &_globals.channels, cid, tempobj, NULL, unboundop, fallback);
}
Py_DECREF(tempobj);
if (handle_channel_error(err, self, cid)) {
@@ -3197,7 +3252,7 @@ channelsmod_recv(PyObject *self, PyObject *args, PyObject *kwds)
cid = cid_data.cid;
PyObject *obj = NULL;
- int unboundop = 0;
+ unboundop_t unboundop = 0;
int err = channel_recv(&_globals.channels, cid, &obj, &unboundop);
if (err == ERR_CHANNEL_EMPTY && dflt != NULL) {
// Use the default.
@@ -3388,17 +3443,14 @@ channelsmod_get_channel_defaults(PyObject *self, PyObject *args, PyObject *kwds)
}
int64_t cid = cid_data.cid;
- PyThread_type_lock mutex = NULL;
- _channel_state *channel = NULL;
- int err = _channels_lookup(&_globals.channels, cid, &mutex, &channel);
+ struct _channeldefaults defaults = {0};
+ int err = channel_get_defaults(&_globals.channels, cid, &defaults);
if (handle_channel_error(err, self, cid)) {
return NULL;
}
- int unboundop = channel->defaults.unboundop;
- PyThread_release_lock(mutex);
- PyObject *defaults = Py_BuildValue("i", unboundop);
- return defaults;
+ PyObject *res = Py_BuildValue("ii", defaults.unboundop, defaults.fallback);
+ return res;
}
PyDoc_STRVAR(channelsmod_get_channel_defaults_doc,
diff --git a/Modules/_interpqueuesmodule.c b/Modules/_interpqueuesmodule.c
index 526249a0e1a..71d8fd8716c 100644
--- a/Modules/_interpqueuesmodule.c
+++ b/Modules/_interpqueuesmodule.c
@@ -9,9 +9,11 @@
#include "pycore_crossinterp.h" // _PyXIData_t
#define REGISTERS_HEAP_TYPES
+#define HAS_FALLBACK
#define HAS_UNBOUND_ITEMS
#include "_interpreters_common.h"
#undef HAS_UNBOUND_ITEMS
+#undef HAS_FALLBACK
#undef REGISTERS_HEAP_TYPES
@@ -401,14 +403,13 @@ typedef struct _queueitem {
meaning the interpreter has been destroyed. */
int64_t interpid;
_PyXIData_t *data;
- int fmt;
- int unboundop;
+ unboundop_t unboundop;
struct _queueitem *next;
} _queueitem;
static void
_queueitem_init(_queueitem *item,
- int64_t interpid, _PyXIData_t *data, int fmt, int unboundop)
+ int64_t interpid, _PyXIData_t *data, unboundop_t unboundop)
{
if (interpid < 0) {
interpid = _get_interpid(data);
@@ -422,7 +423,6 @@ _queueitem_init(_queueitem *item,
*item = (_queueitem){
.interpid = interpid,
.data = data,
- .fmt = fmt,
.unboundop = unboundop,
};
}
@@ -446,14 +446,14 @@ _queueitem_clear(_queueitem *item)
}
static _queueitem *
-_queueitem_new(int64_t interpid, _PyXIData_t *data, int fmt, int unboundop)
+_queueitem_new(int64_t interpid, _PyXIData_t *data, int unboundop)
{
_queueitem *item = GLOBAL_MALLOC(_queueitem);
if (item == NULL) {
PyErr_NoMemory();
return NULL;
}
- _queueitem_init(item, interpid, data, fmt, unboundop);
+ _queueitem_init(item, interpid, data, unboundop);
return item;
}
@@ -476,10 +476,9 @@ _queueitem_free_all(_queueitem *item)
static void
_queueitem_popped(_queueitem *item,
- _PyXIData_t **p_data, int *p_fmt, int *p_unboundop)
+ _PyXIData_t **p_data, unboundop_t *p_unboundop)
{
*p_data = item->data;
- *p_fmt = item->fmt;
*p_unboundop = item->unboundop;
// We clear them here, so they won't be released in _queueitem_clear().
item->data = NULL;
@@ -527,16 +526,16 @@ typedef struct _queue {
_queueitem *first;
_queueitem *last;
} items;
- struct {
- int fmt;
+ struct _queuedefaults {
+ xidata_fallback_t fallback;
int unboundop;
} defaults;
} _queue;
static int
-_queue_init(_queue *queue, Py_ssize_t maxsize, int fmt, int unboundop)
+_queue_init(_queue *queue, Py_ssize_t maxsize, struct _queuedefaults defaults)
{
- assert(check_unbound(unboundop));
+ assert(check_unbound(defaults.unboundop));
PyThread_type_lock mutex = PyThread_allocate_lock();
if (mutex == NULL) {
return ERR_QUEUE_ALLOC;
@@ -547,10 +546,7 @@ _queue_init(_queue *queue, Py_ssize_t maxsize, int fmt, int unboundop)
.items = {
.maxsize = maxsize,
},
- .defaults = {
- .fmt = fmt,
- .unboundop = unboundop,
- },
+ .defaults = defaults,
};
return 0;
}
@@ -631,8 +627,7 @@ _queue_unlock(_queue *queue)
}
static int
-_queue_add(_queue *queue, int64_t interpid, _PyXIData_t *data,
- int fmt, int unboundop)
+_queue_add(_queue *queue, int64_t interpid, _PyXIData_t *data, int unboundop)
{
int err = _queue_lock(queue);
if (err < 0) {
@@ -648,7 +643,7 @@ _queue_add(_queue *queue, int64_t interpid, _PyXIData_t *data,
return ERR_QUEUE_FULL;
}
- _queueitem *item = _queueitem_new(interpid, data, fmt, unboundop);
+ _queueitem *item = _queueitem_new(interpid, data, unboundop);
if (item == NULL) {
_queue_unlock(queue);
return -1;
@@ -668,8 +663,7 @@ _queue_add(_queue *queue, int64_t interpid, _PyXIData_t *data,
}
static int
-_queue_next(_queue *queue,
- _PyXIData_t **p_data, int *p_fmt, int *p_unboundop)
+_queue_next(_queue *queue, _PyXIData_t **p_data, int *p_unboundop)
{
int err = _queue_lock(queue);
if (err < 0) {
@@ -688,7 +682,7 @@ _queue_next(_queue *queue,
}
queue->items.count -= 1;
- _queueitem_popped(item, p_data, p_fmt, p_unboundop);
+ _queueitem_popped(item, p_data, p_unboundop);
_queue_unlock(queue);
return 0;
@@ -1035,8 +1029,7 @@ finally:
struct queue_id_and_info {
int64_t id;
- int fmt;
- int unboundop;
+ struct _queuedefaults defaults;
};
static struct queue_id_and_info *
@@ -1053,8 +1046,7 @@ _queues_list_all(_queues *queues, int64_t *p_count)
for (int64_t i=0; ref != NULL; ref = ref->next, i++) {
ids[i].id = ref->qid;
assert(ref->queue != NULL);
- ids[i].fmt = ref->queue->defaults.fmt;
- ids[i].unboundop = ref->queue->defaults.unboundop;
+ ids[i].defaults = ref->queue->defaults;
}
*p_count = queues->count;
@@ -1090,13 +1082,14 @@ _queue_free(_queue *queue)
// Create a new queue.
static int64_t
-queue_create(_queues *queues, Py_ssize_t maxsize, int fmt, int unboundop)
+queue_create(_queues *queues, Py_ssize_t maxsize,
+ struct _queuedefaults defaults)
{
_queue *queue = GLOBAL_MALLOC(_queue);
if (queue == NULL) {
return ERR_QUEUE_ALLOC;
}
- int err = _queue_init(queue, maxsize, fmt, unboundop);
+ int err = _queue_init(queue, maxsize, defaults);
if (err < 0) {
GLOBAL_FREE(queue);
return (int64_t)err;
@@ -1125,7 +1118,8 @@ queue_destroy(_queues *queues, int64_t qid)
// Push an object onto the queue.
static int
-queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
+queue_put(_queues *queues, int64_t qid, PyObject *obj, unboundop_t unboundop,
+ xidata_fallback_t fallback)
{
PyThreadState *tstate = PyThreadState_Get();
@@ -1138,27 +1132,27 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
assert(queue != NULL);
// Convert the object to cross-interpreter data.
- _PyXIData_t *data = _PyXIData_New();
- if (data == NULL) {
+ _PyXIData_t *xidata = _PyXIData_New();
+ if (xidata == NULL) {
_queue_unmark_waiter(queue, queues->mutex);
return -1;
}
- if (_PyObject_GetXIData(tstate, obj, data) != 0) {
+ if (_PyObject_GetXIData(tstate, obj, fallback, xidata) != 0) {
_queue_unmark_waiter(queue, queues->mutex);
- GLOBAL_FREE(data);
+ GLOBAL_FREE(xidata);
return -1;
}
- assert(_PyXIData_INTERPID(data) ==
+ assert(_PyXIData_INTERPID(xidata) ==
PyInterpreterState_GetID(tstate->interp));
// Add the data to the queue.
int64_t interpid = -1; // _queueitem_init() will set it.
- int res = _queue_add(queue, interpid, data, fmt, unboundop);
+ int res = _queue_add(queue, interpid, xidata, unboundop);
_queue_unmark_waiter(queue, queues->mutex);
if (res != 0) {
// We may chain an exception here:
- (void)_release_xid_data(data, 0);
- GLOBAL_FREE(data);
+ (void)_release_xid_data(xidata, 0);
+ GLOBAL_FREE(xidata);
return res;
}
@@ -1169,7 +1163,7 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
// XXX Support a "wait" mutex?
static int
queue_get(_queues *queues, int64_t qid,
- PyObject **res, int *p_fmt, int *p_unboundop)
+ PyObject **res, int *p_unboundop)
{
int err;
*res = NULL;
@@ -1185,7 +1179,7 @@ queue_get(_queues *queues, int64_t qid,
// Pop off the next item from the queue.
_PyXIData_t *data = NULL;
- err = _queue_next(queue, &data, p_fmt, p_unboundop);
+ err = _queue_next(queue, &data, p_unboundop);
_queue_unmark_waiter(queue, queues->mutex);
if (err != 0) {
return err;
@@ -1217,6 +1211,20 @@ queue_get(_queues *queues, int64_t qid,
}
static int
+queue_get_defaults(_queues *queues, int64_t qid,
+ struct _queuedefaults *p_defaults)
+{
+ _queue *queue = NULL;
+ int err = _queues_lookup(queues, qid, &queue);
+ if (err != 0) {
+ return err;
+ }
+ *p_defaults = queue->defaults;
+ _queue_unmark_waiter(queue, queues->mutex);
+ return 0;
+}
+
+static int
queue_get_maxsize(_queues *queues, int64_t qid, Py_ssize_t *p_maxsize)
{
_queue *queue = NULL;
@@ -1270,7 +1278,7 @@ set_external_queue_type(module_state *state, PyTypeObject *queue_type)
}
// Add and register the new type.
- if (ensure_xid_class(queue_type, _queueobj_shared) < 0) {
+ if (ensure_xid_class(queue_type, GETDATA(_queueobj_shared)) < 0) {
return -1;
}
state->queue_type = (PyTypeObject *)Py_NewRef(queue_type);
@@ -1348,10 +1356,10 @@ _queueobj_from_xid(_PyXIData_t *data)
PyObject *mod = _get_current_module();
if (mod == NULL) {
- // XXX import it?
- PyErr_SetString(PyExc_RuntimeError,
- MODULE_NAME_STR " module not imported yet");
- return NULL;
+ mod = PyImport_ImportModule(MODULE_NAME_STR);
+ if (mod == NULL) {
+ return NULL;
+ }
}
PyTypeObject *cls = get_external_queue_type(mod);
@@ -1474,22 +1482,28 @@ qidarg_converter(PyObject *arg, void *ptr)
static PyObject *
queuesmod_create(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"maxsize", "fmt", "unboundop", NULL};
+ static char *kwlist[] = {"maxsize", "unboundop", "fallback", NULL};
Py_ssize_t maxsize;
- int fmt;
- int unboundop;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "nii:create", kwlist,
- &maxsize, &fmt, &unboundop))
+ int unboundarg = -1;
+ int fallbackarg = -1;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "n|ii:create", kwlist,
+ &maxsize, &unboundarg, &fallbackarg))
{
return NULL;
}
- if (!check_unbound(unboundop)) {
- PyErr_Format(PyExc_ValueError,
- "unsupported unboundop %d", unboundop);
+ struct _queuedefaults defaults = {0};
+ if (resolve_unboundop(unboundarg, UNBOUND_REPLACE,
+ &defaults.unboundop) < 0)
+ {
+ return NULL;
+ }
+ if (resolve_fallback(fallbackarg, _PyXIDATA_FULL_FALLBACK,
+ &defaults.fallback) < 0)
+ {
return NULL;
}
- int64_t qid = queue_create(&_globals.queues, maxsize, fmt, unboundop);
+ int64_t qid = queue_create(&_globals.queues, maxsize, defaults);
if (qid < 0) {
(void)handle_queue_error((int)qid, self, qid);
return NULL;
@@ -1511,7 +1525,7 @@ queuesmod_create(PyObject *self, PyObject *args, PyObject *kwds)
}
PyDoc_STRVAR(queuesmod_create_doc,
-"create(maxsize, fmt, unboundop) -> qid\n\
+"create(maxsize, unboundop, fallback) -> qid\n\
\n\
Create a new cross-interpreter queue and return its unique generated ID.\n\
It is a new reference as though bind() had been called on the queue.\n\
@@ -1560,8 +1574,9 @@ queuesmod_list_all(PyObject *self, PyObject *Py_UNUSED(ignored))
}
struct queue_id_and_info *cur = qids;
for (int64_t i=0; i < count; cur++, i++) {
- PyObject *item = Py_BuildValue("Lii", cur->id, cur->fmt,
- cur->unboundop);
+ PyObject *item = Py_BuildValue("Lii", cur->id,
+ cur->defaults.unboundop,
+ cur->defaults.fallback);
if (item == NULL) {
Py_SETREF(ids, NULL);
break;
@@ -1575,34 +1590,44 @@ finally:
}
PyDoc_STRVAR(queuesmod_list_all_doc,
-"list_all() -> [(qid, fmt)]\n\
+"list_all() -> [(qid, unboundop, fallback)]\n\
\n\
Return the list of IDs for all queues.\n\
-Each corresponding default format is also included.");
+Each corresponding default unbound op and fallback is also included.");
static PyObject *
queuesmod_put(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"qid", "obj", "fmt", "unboundop", NULL};
+ static char *kwlist[] = {"qid", "obj", "unboundop", "fallback", NULL};
qidarg_converter_data qidarg = {0};
PyObject *obj;
- int fmt;
- int unboundop;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&Oii:put", kwlist,
- qidarg_converter, &qidarg, &obj, &fmt,
- &unboundop))
+ int unboundarg = -1;
+ int fallbackarg = -1;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O|ii$p:put", kwlist,
+ qidarg_converter, &qidarg, &obj,
+ &unboundarg, &fallbackarg))
{
return NULL;
}
int64_t qid = qidarg.id;
- if (!check_unbound(unboundop)) {
- PyErr_Format(PyExc_ValueError,
- "unsupported unboundop %d", unboundop);
+ struct _queuedefaults defaults = {-1, -1};
+ if (unboundarg < 0 || fallbackarg < 0) {
+ int err = queue_get_defaults(&_globals.queues, qid, &defaults);
+ if (handle_queue_error(err, self, qid)) {
+ return NULL;
+ }
+ }
+ unboundop_t unboundop;
+ if (resolve_unboundop(unboundarg, defaults.unboundop, &unboundop) < 0) {
+ return NULL;
+ }
+ xidata_fallback_t fallback;
+ if (resolve_fallback(fallbackarg, defaults.fallback, &fallback) < 0) {
return NULL;
}
/* Queue up the object. */
- int err = queue_put(&_globals.queues, qid, obj, fmt, unboundop);
+ int err = queue_put(&_globals.queues, qid, obj, unboundop, fallback);
// This is the only place that raises QueueFull.
if (handle_queue_error(err, self, qid)) {
return NULL;
@@ -1612,7 +1637,7 @@ queuesmod_put(PyObject *self, PyObject *args, PyObject *kwds)
}
PyDoc_STRVAR(queuesmod_put_doc,
-"put(qid, obj, fmt)\n\
+"put(qid, obj)\n\
\n\
Add the object's data to the queue.");
@@ -1628,27 +1653,26 @@ queuesmod_get(PyObject *self, PyObject *args, PyObject *kwds)
int64_t qid = qidarg.id;
PyObject *obj = NULL;
- int fmt = 0;
int unboundop = 0;
- int err = queue_get(&_globals.queues, qid, &obj, &fmt, &unboundop);
+ int err = queue_get(&_globals.queues, qid, &obj, &unboundop);
// This is the only place that raises QueueEmpty.
if (handle_queue_error(err, self, qid)) {
return NULL;
}
if (obj == NULL) {
- return Py_BuildValue("Oii", Py_None, fmt, unboundop);
+ return Py_BuildValue("Oi", Py_None, unboundop);
}
- PyObject *res = Py_BuildValue("OiO", obj, fmt, Py_None);
+ PyObject *res = Py_BuildValue("OO", obj, Py_None);
Py_DECREF(obj);
return res;
}
PyDoc_STRVAR(queuesmod_get_doc,
-"get(qid) -> (obj, fmt)\n\
+"get(qid) -> (obj, unboundop)\n\
\n\
Return a new object from the data at the front of the queue.\n\
-The object's format is also returned.\n\
+The unbound op is also returned.\n\
\n\
If there is nothing to receive then raise QueueEmpty.");
@@ -1748,17 +1772,14 @@ queuesmod_get_queue_defaults(PyObject *self, PyObject *args, PyObject *kwds)
}
int64_t qid = qidarg.id;
- _queue *queue = NULL;
- int err = _queues_lookup(&_globals.queues, qid, &queue);
+ struct _queuedefaults defaults = {0};
+ int err = queue_get_defaults(&_globals.queues, qid, &defaults);
if (handle_queue_error(err, self, qid)) {
return NULL;
}
- int fmt = queue->defaults.fmt;
- int unboundop = queue->defaults.unboundop;
- _queue_unmark_waiter(queue, _globals.queues.mutex);
- PyObject *defaults = Py_BuildValue("ii", fmt, unboundop);
- return defaults;
+ PyObject *res = Py_BuildValue("ii", defaults.unboundop, defaults.fallback);
+ return res;
}
PyDoc_STRVAR(queuesmod_get_queue_defaults_doc,
diff --git a/Modules/_interpreters_common.h b/Modules/_interpreters_common.h
index edd65577284..40fd51d752e 100644
--- a/Modules/_interpreters_common.h
+++ b/Modules/_interpreters_common.h
@@ -5,8 +5,10 @@
_RESOLVE_MODINIT_FUNC_NAME(NAME)
+#define GETDATA(FUNC) ((_PyXIData_getdata_t){.basic=FUNC})
+
static int
-ensure_xid_class(PyTypeObject *cls, xidatafunc getdata)
+ensure_xid_class(PyTypeObject *cls, _PyXIData_getdata_t getdata)
{
PyThreadState *tstate = PyThreadState_Get();
return _PyXIData_RegisterClass(tstate, cls, getdata);
@@ -37,10 +39,37 @@ _get_interpid(_PyXIData_t *data)
}
+#ifdef HAS_FALLBACK
+static int
+resolve_fallback(int arg, xidata_fallback_t dflt,
+ xidata_fallback_t *p_fallback)
+{
+ if (arg < 0) {
+ *p_fallback = dflt;
+ return 0;
+ }
+ xidata_fallback_t fallback;
+ if (arg == _PyXIDATA_XIDATA_ONLY) {
+ fallback =_PyXIDATA_XIDATA_ONLY;
+ }
+ else if (arg == _PyXIDATA_FULL_FALLBACK) {
+ fallback = _PyXIDATA_FULL_FALLBACK;
+ }
+ else {
+ PyErr_Format(PyExc_ValueError, "unsupported fallback %d", arg);
+ return -1;
+ }
+ *p_fallback = fallback;
+ return 0;
+}
+#endif
+
+
/* unbound items ************************************************************/
#ifdef HAS_UNBOUND_ITEMS
+typedef int unboundop_t;
#define UNBOUND_REMOVE 1
#define UNBOUND_ERROR 2
#define UNBOUND_REPLACE 3
@@ -51,6 +80,7 @@ _get_interpid(_PyXIData_t *data)
// object is released but the underlying data is copied (with the "raw"
// allocator) and used when the item is popped off the queue.
+#ifndef NDEBUG
static int
check_unbound(int unboundop)
{
@@ -63,5 +93,31 @@ check_unbound(int unboundop)
return 0;
}
}
+#endif
+
+static int
+resolve_unboundop(int arg, unboundop_t dflt, unboundop_t *p_unboundop)
+{
+ if (arg < 0) {
+ *p_unboundop = dflt;
+ return 0;
+ }
+ unboundop_t op;
+ if (arg == UNBOUND_REMOVE) {
+ op = UNBOUND_REMOVE;
+ }
+ else if (arg == UNBOUND_ERROR) {
+ op = UNBOUND_ERROR;
+ }
+ else if (arg == UNBOUND_REPLACE) {
+ op = UNBOUND_REPLACE;
+ }
+ else {
+ PyErr_Format(PyExc_ValueError, "unsupported unboundop %d", arg);
+ return -1;
+ }
+ *p_unboundop = op;
+ return 0;
+}
#endif
diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c
index 77678f7c126..037e9544543 100644
--- a/Modules/_interpretersmodule.c
+++ b/Modules/_interpretersmodule.c
@@ -8,6 +8,7 @@
#include "Python.h"
#include "pycore_code.h" // _PyCode_HAS_EXECUTORS()
#include "pycore_crossinterp.h" // _PyXIData_t
+#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
#include "pycore_interp.h" // _PyInterpreterState_IDIncref()
#include "pycore_modsupport.h" // _PyArg_BadArgument()
#include "pycore_namespace.h" // _PyNamespace_New()
@@ -71,6 +72,32 @@ is_running_main(PyInterpreterState *interp)
}
+static inline int
+is_notshareable_raised(PyThreadState *tstate)
+{
+ PyObject *exctype = _PyXIData_GetNotShareableErrorType(tstate);
+ return _PyErr_ExceptionMatches(tstate, exctype);
+}
+
+static void
+unwrap_not_shareable(PyThreadState *tstate)
+{
+ if (!is_notshareable_raised(tstate)) {
+ return;
+ }
+ PyObject *exc = _PyErr_GetRaisedException(tstate);
+ PyObject *cause = PyException_GetCause(exc);
+ if (cause != NULL) {
+ Py_DECREF(exc);
+ exc = cause;
+ }
+ else {
+ assert(PyException_GetContext(exc) == NULL);
+ }
+ _PyErr_SetRaisedException(tstate, exc);
+}
+
+
/* Cross-interpreter Buffer Views *******************************************/
/* When a memoryview object is "shared" between interpreters,
@@ -286,7 +313,7 @@ register_memoryview_xid(PyObject *mod, PyTypeObject **p_state)
*p_state = cls;
// Register XID for the builtin memoryview type.
- if (ensure_xid_class(&PyMemoryView_Type, _pybuffer_shared) < 0) {
+ if (ensure_xid_class(&PyMemoryView_Type, GETDATA(_pybuffer_shared)) < 0) {
return -1;
}
// We don't ever bother un-registering memoryview.
@@ -319,10 +346,10 @@ _get_current_module_state(void)
{
PyObject *mod = _get_current_module();
if (mod == NULL) {
- // XXX import it?
- PyErr_SetString(PyExc_RuntimeError,
- MODULE_NAME_STR " module not imported yet");
- return NULL;
+ mod = PyImport_ImportModule(MODULE_NAME_STR);
+ if (mod == NULL) {
+ return NULL;
+ }
}
module_state *state = get_module_state(mod);
Py_DECREF(mod);
@@ -359,96 +386,6 @@ _get_current_xibufferview_type(void)
}
-/* Python code **************************************************************/
-
-static const char *
-check_code_str(PyUnicodeObject *text)
-{
- assert(text != NULL);
- if (PyUnicode_GET_LENGTH(text) == 0) {
- return "too short";
- }
-
- // XXX Verify that it parses?
-
- return NULL;
-}
-
-static const char *
-check_code_object(PyCodeObject *code)
-{
- assert(code != NULL);
- if (code->co_argcount > 0
- || code->co_posonlyargcount > 0
- || code->co_kwonlyargcount > 0
- || code->co_flags & (CO_VARARGS | CO_VARKEYWORDS))
- {
- return "arguments not supported";
- }
- if (code->co_ncellvars > 0) {
- return "closures not supported";
- }
- // We trust that no code objects under co_consts have unbound cell vars.
-
- if (_PyCode_HAS_EXECUTORS(code) || _PyCode_HAS_INSTRUMENTATION(code)) {
- return "only basic functions are supported";
- }
- if (code->_co_monitoring != NULL) {
- return "only basic functions are supported";
- }
- if (code->co_extra != NULL) {
- return "only basic functions are supported";
- }
-
- return NULL;
-}
-
-#define RUN_TEXT 1
-#define RUN_CODE 2
-
-static const char *
-get_code_str(PyObject *arg, Py_ssize_t *len_p, PyObject **bytes_p, int *flags_p)
-{
- const char *codestr = NULL;
- Py_ssize_t len = -1;
- PyObject *bytes_obj = NULL;
- int flags = 0;
-
- if (PyUnicode_Check(arg)) {
- assert(PyUnicode_Check(arg)
- && (check_code_str((PyUnicodeObject *)arg) == NULL));
- codestr = PyUnicode_AsUTF8AndSize(arg, &len);
- if (codestr == NULL) {
- return NULL;
- }
- if (strlen(codestr) != (size_t)len) {
- PyErr_SetString(PyExc_ValueError,
- "source code string cannot contain null bytes");
- return NULL;
- }
- flags = RUN_TEXT;
- }
- else {
- assert(PyCode_Check(arg)
- && (check_code_object((PyCodeObject *)arg) == NULL));
- flags = RUN_CODE;
-
- // Serialize the code object.
- bytes_obj = PyMarshal_WriteObjectToString(arg, Py_MARSHAL_VERSION);
- if (bytes_obj == NULL) {
- return NULL;
- }
- codestr = PyBytes_AS_STRING(bytes_obj);
- len = PyBytes_GET_SIZE(bytes_obj);
- }
-
- *flags_p = flags;
- *bytes_p = bytes_obj;
- *len_p = len;
- return codestr;
-}
-
-
/* interpreter-specific code ************************************************/
static int
@@ -511,73 +448,265 @@ config_from_object(PyObject *configobj, PyInterpreterConfig *config)
}
+struct interp_call {
+ _PyXIData_t *func;
+ _PyXIData_t *args;
+ _PyXIData_t *kwargs;
+ struct {
+ _PyXIData_t func;
+ _PyXIData_t args;
+ _PyXIData_t kwargs;
+ } _preallocated;
+};
+
+static void
+_interp_call_clear(struct interp_call *call)
+{
+ if (call->func != NULL) {
+ _PyXIData_Clear(NULL, call->func);
+ }
+ if (call->args != NULL) {
+ _PyXIData_Clear(NULL, call->args);
+ }
+ if (call->kwargs != NULL) {
+ _PyXIData_Clear(NULL, call->kwargs);
+ }
+ *call = (struct interp_call){0};
+}
+
+static int
+_interp_call_pack(PyThreadState *tstate, struct interp_call *call,
+ PyObject *func, PyObject *args, PyObject *kwargs)
+{
+ xidata_fallback_t fallback = _PyXIDATA_FULL_FALLBACK;
+ assert(call->func == NULL);
+ assert(call->args == NULL);
+ assert(call->kwargs == NULL);
+ // Handle the func.
+ if (!PyCallable_Check(func)) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "expected a callable, got %R", func);
+ return -1;
+ }
+ if (_PyFunction_GetXIData(tstate, func, &call->_preallocated.func) < 0) {
+ PyObject *exc = _PyErr_GetRaisedException(tstate);
+ if (_PyPickle_GetXIData(tstate, func, &call->_preallocated.func) < 0) {
+ _PyErr_SetRaisedException(tstate, exc);
+ return -1;
+ }
+ Py_DECREF(exc);
+ }
+ call->func = &call->_preallocated.func;
+ // Handle the args.
+ if (args == NULL || args == Py_None) {
+ // Leave it empty.
+ }
+ else {
+ assert(PyTuple_Check(args));
+ if (PyTuple_GET_SIZE(args) > 0) {
+ if (_PyObject_GetXIData(
+ tstate, args, fallback, &call->_preallocated.args) < 0)
+ {
+ _interp_call_clear(call);
+ return -1;
+ }
+ call->args = &call->_preallocated.args;
+ }
+ }
+ // Handle the kwargs.
+ if (kwargs == NULL || kwargs == Py_None) {
+ // Leave it empty.
+ }
+ else {
+ assert(PyDict_Check(kwargs));
+ if (PyDict_GET_SIZE(kwargs) > 0) {
+ if (_PyObject_GetXIData(
+ tstate, kwargs, fallback, &call->_preallocated.kwargs) < 0)
+ {
+ _interp_call_clear(call);
+ return -1;
+ }
+ call->kwargs = &call->_preallocated.kwargs;
+ }
+ }
+ return 0;
+}
+
static int
-_run_script(PyObject *ns, const char *codestr, Py_ssize_t codestrlen, int flags)
+_interp_call_unpack(struct interp_call *call,
+ PyObject **p_func, PyObject **p_args, PyObject **p_kwargs)
{
- PyObject *result = NULL;
- if (flags & RUN_TEXT) {
- result = PyRun_StringFlags(codestr, Py_file_input, ns, ns, NULL);
- }
- else if (flags & RUN_CODE) {
- PyObject *code = PyMarshal_ReadObjectFromString(codestr, codestrlen);
- if (code != NULL) {
- result = PyEval_EvalCode(code, ns, ns);
- Py_DECREF(code);
+ // Unpack the func.
+ PyObject *func = _PyXIData_NewObject(call->func);
+ if (func == NULL) {
+ return -1;
+ }
+ // Unpack the args.
+ PyObject *args;
+ if (call->args == NULL) {
+ args = PyTuple_New(0);
+ if (args == NULL) {
+ Py_DECREF(func);
+ return -1;
}
}
else {
- Py_UNREACHABLE();
+ args = _PyXIData_NewObject(call->args);
+ if (args == NULL) {
+ Py_DECREF(func);
+ return -1;
+ }
+ assert(PyTuple_Check(args));
+ }
+ // Unpack the kwargs.
+ PyObject *kwargs = NULL;
+ if (call->kwargs != NULL) {
+ kwargs = _PyXIData_NewObject(call->kwargs);
+ if (kwargs == NULL) {
+ Py_DECREF(func);
+ Py_DECREF(args);
+ return -1;
+ }
+ assert(PyDict_Check(kwargs));
}
+ *p_func = func;
+ *p_args = args;
+ *p_kwargs = kwargs;
+ return 0;
+}
+
+static int
+_make_call(struct interp_call *call,
+ PyObject **p_result, _PyXI_errcode *p_errcode)
+{
+ assert(call != NULL && call->func != NULL);
+ PyThreadState *tstate = _PyThreadState_GET();
+
+ // Get the func and args.
+ PyObject *func = NULL, *args = NULL, *kwargs = NULL;
+ if (_interp_call_unpack(call, &func, &args, &kwargs) < 0) {
+ assert(func == NULL);
+ assert(args == NULL);
+ assert(kwargs == NULL);
+ *p_errcode = is_notshareable_raised(tstate)
+ ? _PyXI_ERR_NOT_SHAREABLE
+ : _PyXI_ERR_OTHER;
+ return -1;
+ }
+ *p_errcode = _PyXI_ERR_NO_ERROR;
+
+ // Make the call.
+ PyObject *resobj = PyObject_Call(func, args, kwargs);
+ Py_DECREF(func);
+ Py_XDECREF(args);
+ Py_XDECREF(kwargs);
+ if (resobj == NULL) {
+ return -1;
+ }
+ *p_result = resobj;
+ return 0;
+}
+
+static int
+_run_script(_PyXIData_t *script, PyObject *ns, _PyXI_errcode *p_errcode)
+{
+ PyObject *code = _PyXIData_NewObject(script);
+ if (code == NULL) {
+ *p_errcode = _PyXI_ERR_NOT_SHAREABLE;
+ return -1;
+ }
+ PyObject *result = PyEval_EvalCode(code, ns, ns);
+ Py_DECREF(code);
if (result == NULL) {
+ *p_errcode = _PyXI_ERR_UNCAUGHT_EXCEPTION;
return -1;
}
+ assert(result == Py_None);
Py_DECREF(result); // We throw away the result.
return 0;
}
+struct run_result {
+ PyObject *result;
+ PyObject *excinfo;
+};
+
+static void
+_run_result_clear(struct run_result *runres)
+{
+ Py_CLEAR(runres->result);
+ Py_CLEAR(runres->excinfo);
+}
+
static int
-_run_in_interpreter(PyInterpreterState *interp,
- const char *codestr, Py_ssize_t codestrlen,
- PyObject *shareables, int flags,
- PyObject **p_excinfo)
+_run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
+ _PyXIData_t *script, struct interp_call *call,
+ PyObject *shareables, struct run_result *runres)
{
- assert(!PyErr_Occurred());
- _PyXI_session session = {0};
+ assert(!_PyErr_Occurred(tstate));
+ _PyXI_session *session = _PyXI_NewSession();
+ if (session == NULL) {
+ return -1;
+ }
+ _PyXI_session_result result = {0};
// Prep and switch interpreters.
- if (_PyXI_Enter(&session, interp, shareables) < 0) {
- if (PyErr_Occurred()) {
- // If an error occured at this step, it means that interp
- // was not prepared and switched.
- return -1;
- }
- // Now, apply the error from another interpreter:
- PyObject *excinfo = _PyXI_ApplyError(session.error);
- if (excinfo != NULL) {
- *p_excinfo = excinfo;
- }
- assert(PyErr_Occurred());
+ if (_PyXI_Enter(session, interp, shareables, &result) < 0) {
+ // If an error occured at this step, it means that interp
+ // was not prepared and switched.
+ _PyXI_FreeSession(session);
+ assert(result.excinfo == NULL);
return -1;
}
- // Run the script.
- int res = _run_script(session.main_ns, codestr, codestrlen, flags);
+ // Run in the interpreter.
+ int res = -1;
+ _PyXI_errcode errcode = _PyXI_ERR_NO_ERROR;
+ if (script != NULL) {
+ assert(call == NULL);
+ PyObject *mainns = _PyXI_GetMainNamespace(session, &errcode);
+ if (mainns == NULL) {
+ goto finally;
+ }
+ res = _run_script(script, mainns, &errcode);
+ }
+ else {
+ assert(call != NULL);
+ PyObject *resobj;
+ res = _make_call(call, &resobj, &errcode);
+ if (res == 0) {
+ res = _PyXI_Preserve(session, "resobj", resobj, &errcode);
+ Py_DECREF(resobj);
+ if (res < 0) {
+ goto finally;
+ }
+ }
+ }
+ int exitres;
+finally:
// Clean up and switch back.
- _PyXI_Exit(&session);
+ exitres = _PyXI_Exit(session, errcode, &result);
+ assert(res == 0 || exitres != 0);
+ _PyXI_FreeSession(session);
- // Propagate any exception out to the caller.
- assert(!PyErr_Occurred());
- if (res < 0) {
- PyObject *excinfo = _PyXI_ApplyCapturedException(&session);
- if (excinfo != NULL) {
- *p_excinfo = excinfo;
- }
+ res = exitres;
+ if (_PyErr_Occurred(tstate)) {
+ assert(res < 0);
+ }
+ else if (res < 0) {
+ assert(result.excinfo != NULL);
+ runres->excinfo = Py_NewRef(result.excinfo);
+ res = -1;
}
else {
- assert(!_PyXI_HasCapturedException(&session));
+ assert(result.excinfo == NULL);
+ runres->result = _PyXI_GetPreserved(&result, "resobj");
+ if (_PyErr_Occurred(tstate)) {
+ res = -1;
+ }
}
-
+ _PyXI_ClearResult(&result);
return res;
}
@@ -922,22 +1051,29 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs)
}
}
- _PyXI_session session = {0};
+ _PyXI_session *session = _PyXI_NewSession();
+ if (session == NULL) {
+ return NULL;
+ }
// Prep and switch interpreters, including apply the updates.
- if (_PyXI_Enter(&session, interp, updates) < 0) {
- if (!PyErr_Occurred()) {
- _PyXI_ApplyCapturedException(&session);
- assert(PyErr_Occurred());
- }
- else {
- assert(!_PyXI_HasCapturedException(&session));
- }
+ if (_PyXI_Enter(session, interp, updates, NULL) < 0) {
+ _PyXI_FreeSession(session);
return NULL;
}
// Clean up and switch back.
- _PyXI_Exit(&session);
+ assert(!PyErr_Occurred());
+ int res = _PyXI_Exit(session, _PyXI_ERR_NO_ERROR, NULL);
+ _PyXI_FreeSession(session);
+ assert(res == 0);
+ if (res < 0) {
+ // unreachable
+ if (!PyErr_Occurred()) {
+ PyErr_SetString(PyExc_RuntimeError, "unresolved error");
+ }
+ return NULL;
+ }
Py_RETURN_NONE;
}
@@ -948,122 +1084,31 @@ PyDoc_STRVAR(set___main___attrs_doc,
Bind the given attributes in the interpreter's __main__ module.");
-static PyUnicodeObject *
-convert_script_arg(PyObject *arg, const char *fname, const char *displayname,
- const char *expected)
-{
- PyUnicodeObject *str = NULL;
- if (PyUnicode_CheckExact(arg)) {
- str = (PyUnicodeObject *)Py_NewRef(arg);
- }
- else if (PyUnicode_Check(arg)) {
- // XXX str = PyUnicode_FromObject(arg);
- str = (PyUnicodeObject *)Py_NewRef(arg);
- }
- else {
- _PyArg_BadArgument(fname, displayname, expected, arg);
- return NULL;
- }
-
- const char *err = check_code_str(str);
- if (err != NULL) {
- Py_DECREF(str);
- PyErr_Format(PyExc_ValueError,
- "%.200s(): bad script text (%s)", fname, err);
- return NULL;
- }
-
- return str;
-}
-
-static PyCodeObject *
-convert_code_arg(PyObject *arg, const char *fname, const char *displayname,
- const char *expected)
+static PyObject *
+_handle_script_error(struct run_result *runres)
{
- const char *kind = NULL;
- PyCodeObject *code = NULL;
- if (PyFunction_Check(arg)) {
- if (PyFunction_GetClosure(arg) != NULL) {
- PyErr_Format(PyExc_ValueError,
- "%.200s(): closures not supported", fname);
- return NULL;
- }
- code = (PyCodeObject *)PyFunction_GetCode(arg);
- if (code == NULL) {
- if (PyErr_Occurred()) {
- // This chains.
- PyErr_Format(PyExc_ValueError,
- "%.200s(): bad func", fname);
- }
- else {
- PyErr_Format(PyExc_ValueError,
- "%.200s(): func.__code__ missing", fname);
- }
- return NULL;
- }
- Py_INCREF(code);
- kind = "func";
- }
- else if (PyCode_Check(arg)) {
- code = (PyCodeObject *)Py_NewRef(arg);
- kind = "code object";
- }
- else {
- _PyArg_BadArgument(fname, displayname, expected, arg);
- return NULL;
- }
-
- const char *err = check_code_object(code);
- if (err != NULL) {
- Py_DECREF(code);
- PyErr_Format(PyExc_ValueError,
- "%.200s(): bad %s (%s)", fname, kind, err);
+ assert(runres->result == NULL);
+ if (runres->excinfo == NULL) {
+ assert(PyErr_Occurred());
return NULL;
}
-
- return code;
-}
-
-static int
-_interp_exec(PyObject *self, PyInterpreterState *interp,
- PyObject *code_arg, PyObject *shared_arg, PyObject **p_excinfo)
-{
- if (shared_arg != NULL && !PyDict_CheckExact(shared_arg)) {
- PyErr_SetString(PyExc_TypeError, "expected 'shared' to be a dict");
- return -1;
- }
-
- // Extract code.
- Py_ssize_t codestrlen = -1;
- PyObject *bytes_obj = NULL;
- int flags = 0;
- const char *codestr = get_code_str(code_arg,
- &codestrlen, &bytes_obj, &flags);
- if (codestr == NULL) {
- return -1;
- }
-
- // Run the code in the interpreter.
- int res = _run_in_interpreter(interp, codestr, codestrlen,
- shared_arg, flags, p_excinfo);
- Py_XDECREF(bytes_obj);
- if (res < 0) {
- return -1;
- }
-
- return 0;
+ assert(!PyErr_Occurred());
+ return runres->excinfo;
}
static PyObject *
interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
{
+#define FUNCNAME MODULE_NAME_STR ".exec"
+ PyThreadState *tstate = _PyThreadState_GET();
static char *kwlist[] = {"id", "code", "shared", "restrict", NULL};
PyObject *id, *code;
PyObject *shared = NULL;
int restricted = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds,
- "OO|O$p:" MODULE_NAME_STR ".exec", kwlist,
- &id, &code, &shared, &restricted))
+ "OO|O!$p:" FUNCNAME, kwlist,
+ &id, &code, &PyDict_Type, &shared,
+ &restricted))
{
return NULL;
}
@@ -1075,27 +1120,24 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
- const char *expected = "a string, a function, or a code object";
- if (PyUnicode_Check(code)) {
- code = (PyObject *)convert_script_arg(code, MODULE_NAME_STR ".exec",
- "argument 2", expected);
- }
- else {
- code = (PyObject *)convert_code_arg(code, MODULE_NAME_STR ".exec",
- "argument 2", expected);
- }
- if (code == NULL) {
+ // We don't need the script to be "pure", which means it can use
+ // global variables. They will be resolved against __main__.
+ _PyXIData_t xidata = {0};
+ if (_PyCode_GetScriptXIData(tstate, code, &xidata) < 0) {
+ unwrap_not_shareable(tstate);
return NULL;
}
- PyObject *excinfo = NULL;
- int res = _interp_exec(self, interp, code, shared, &excinfo);
- Py_DECREF(code);
+ struct run_result runres = {0};
+ int res = _run_in_interpreter(
+ tstate, interp, &xidata, NULL, shared, &runres);
+ _PyXIData_Release(&xidata);
if (res < 0) {
- assert((excinfo == NULL) != (PyErr_Occurred() == NULL));
- return excinfo;
+ return _handle_script_error(&runres);
}
+ assert(runres.result == NULL);
Py_RETURN_NONE;
+#undef FUNCNAME
}
PyDoc_STRVAR(exec_doc,
@@ -1118,13 +1160,16 @@ is ignored, including its __globals__ dict.");
static PyObject *
interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
{
+#define FUNCNAME MODULE_NAME_STR ".run_string"
+ PyThreadState *tstate = _PyThreadState_GET();
static char *kwlist[] = {"id", "script", "shared", "restrict", NULL};
PyObject *id, *script;
PyObject *shared = NULL;
int restricted = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds,
- "OU|O$p:" MODULE_NAME_STR ".run_string",
- kwlist, &id, &script, &shared, &restricted))
+ "OU|O!$p:" FUNCNAME, kwlist,
+ &id, &script, &PyDict_Type, &shared,
+ &restricted))
{
return NULL;
}
@@ -1136,20 +1181,27 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
- script = (PyObject *)convert_script_arg(script, MODULE_NAME_STR ".run_string",
- "argument 2", "a string");
- if (script == NULL) {
+ if (PyFunction_Check(script) || PyCode_Check(script)) {
+ _PyArg_BadArgument(FUNCNAME, "argument 2", "a string", script);
+ return NULL;
+ }
+
+ _PyXIData_t xidata = {0};
+ if (_PyCode_GetScriptXIData(tstate, script, &xidata) < 0) {
+ unwrap_not_shareable(tstate);
return NULL;
}
- PyObject *excinfo = NULL;
- int res = _interp_exec(self, interp, script, shared, &excinfo);
- Py_DECREF(script);
+ struct run_result runres = {0};
+ int res = _run_in_interpreter(
+ tstate, interp, &xidata, NULL, shared, &runres);
+ _PyXIData_Release(&xidata);
if (res < 0) {
- assert((excinfo == NULL) != (PyErr_Occurred() == NULL));
- return excinfo;
+ return _handle_script_error(&runres);
}
+ assert(runres.result == NULL);
Py_RETURN_NONE;
+#undef FUNCNAME
}
PyDoc_STRVAR(run_string_doc,
@@ -1162,13 +1214,16 @@ Execute the provided string in the identified interpreter.\n\
static PyObject *
interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
{
+#define FUNCNAME MODULE_NAME_STR ".run_func"
+ PyThreadState *tstate = _PyThreadState_GET();
static char *kwlist[] = {"id", "func", "shared", "restrict", NULL};
PyObject *id, *func;
PyObject *shared = NULL;
int restricted = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds,
- "OO|O$p:" MODULE_NAME_STR ".run_func",
- kwlist, &id, &func, &shared, &restricted))
+ "OO|O!$p:" FUNCNAME, kwlist,
+ &id, &func, &PyDict_Type, &shared,
+ &restricted))
{
return NULL;
}
@@ -1180,21 +1235,36 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
- PyCodeObject *code = convert_code_arg(func, MODULE_NAME_STR ".exec",
- "argument 2",
- "a function or a code object");
- if (code == NULL) {
+ // We don't worry about checking globals. They will be resolved
+ // against __main__.
+ PyObject *code;
+ if (PyFunction_Check(func)) {
+ code = PyFunction_GET_CODE(func);
+ }
+ else if (PyCode_Check(func)) {
+ code = func;
+ }
+ else {
+ _PyArg_BadArgument(FUNCNAME, "argument 2", "a function", func);
return NULL;
}
- PyObject *excinfo = NULL;
- int res = _interp_exec(self, interp, (PyObject *)code, shared, &excinfo);
- Py_DECREF(code);
+ _PyXIData_t xidata = {0};
+ if (_PyCode_GetScriptXIData(tstate, code, &xidata) < 0) {
+ unwrap_not_shareable(tstate);
+ return NULL;
+ }
+
+ struct run_result runres = {0};
+ int res = _run_in_interpreter(
+ tstate, interp, &xidata, NULL, shared, &runres);
+ _PyXIData_Release(&xidata);
if (res < 0) {
- assert((excinfo == NULL) != (PyErr_Occurred() == NULL));
- return excinfo;
+ return _handle_script_error(&runres);
}
+ assert(runres.result == NULL);
Py_RETURN_NONE;
+#undef FUNCNAME
}
PyDoc_STRVAR(run_func_doc,
@@ -1209,16 +1279,21 @@ are not supported. Methods and other callables are not supported either.\n\
static PyObject *
interp_call(PyObject *self, PyObject *args, PyObject *kwds)
{
+#define FUNCNAME MODULE_NAME_STR ".call"
+ PyThreadState *tstate = _PyThreadState_GET();
static char *kwlist[] = {"id", "callable", "args", "kwargs",
- "restrict", NULL};
+ "preserve_exc", "restrict", NULL};
PyObject *id, *callable;
PyObject *args_obj = NULL;
PyObject *kwargs_obj = NULL;
+ int preserve_exc = 0;
int restricted = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds,
- "OO|OO$p:" MODULE_NAME_STR ".call", kwlist,
- &id, &callable, &args_obj, &kwargs_obj,
- &restricted))
+ "OO|O!O!$pp:" FUNCNAME, kwlist,
+ &id, &callable,
+ &PyTuple_Type, &args_obj,
+ &PyDict_Type, &kwargs_obj,
+ &preserve_exc, &restricted))
{
return NULL;
}
@@ -1230,42 +1305,37 @@ interp_call(PyObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
- if (args_obj != NULL) {
- PyErr_SetString(PyExc_ValueError, "got unexpected args");
- return NULL;
- }
- if (kwargs_obj != NULL) {
- PyErr_SetString(PyExc_ValueError, "got unexpected kwargs");
+ struct interp_call call = {0};
+ if (_interp_call_pack(tstate, &call, callable, args_obj, kwargs_obj) < 0) {
return NULL;
}
- PyObject *code = (PyObject *)convert_code_arg(callable, MODULE_NAME_STR ".call",
- "argument 2", "a function");
- if (code == NULL) {
- return NULL;
+ PyObject *res_and_exc = NULL;
+ struct run_result runres = {0};
+ if (_run_in_interpreter(tstate, interp, NULL, &call, NULL, &runres) < 0) {
+ if (runres.excinfo == NULL) {
+ assert(_PyErr_Occurred(tstate));
+ goto finally;
+ }
+ assert(!_PyErr_Occurred(tstate));
}
+ assert(runres.result == NULL || runres.excinfo == NULL);
+ res_and_exc = Py_BuildValue("OO",
+ (runres.result ? runres.result : Py_None),
+ (runres.excinfo ? runres.excinfo : Py_None));
- PyObject *excinfo = NULL;
- int res = _interp_exec(self, interp, code, NULL, &excinfo);
- Py_DECREF(code);
- if (res < 0) {
- assert((excinfo == NULL) != (PyErr_Occurred() == NULL));
- return excinfo;
- }
- Py_RETURN_NONE;
+finally:
+ _interp_call_clear(&call);
+ _run_result_clear(&runres);
+ return res_and_exc;
+#undef FUNCNAME
}
PyDoc_STRVAR(call_doc,
"call(id, callable, args=None, kwargs=None, *, restrict=False)\n\
\n\
Call the provided object in the identified interpreter.\n\
-Pass the given args and kwargs, if possible.\n\
-\n\
-\"callable\" may be a plain function with no free vars that takes\n\
-no arguments.\n\
-\n\
-The function's code object is used and all its state\n\
-is ignored, including its __globals__ dict.");
+Pass the given args and kwargs, if possible.");
static PyObject *
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 4cde5f87032..61cfec435fe 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -607,9 +607,9 @@ _io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
len = 0;
}
- memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
assert(self->pos + len < PY_SSIZE_T_MAX);
assert(len >= 0);
+ memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len);
self->pos += len;
return PyLong_FromSsize_t(len);
diff --git a/Modules/_json.c b/Modules/_json.c
index 89b0a41dd10..57678ad595f 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -360,13 +360,6 @@ _build_rval_index_tuple(PyObject *rval, Py_ssize_t idx) {
return tpl;
}
-static inline int
-_PyUnicodeWriter_IsEmpty(PyUnicodeWriter *writer_pub)
-{
- _PyUnicodeWriter *writer = (_PyUnicodeWriter*)writer_pub;
- return (writer->pos == 0);
-}
-
static PyObject *
scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next_end_ptr)
{
@@ -385,10 +378,7 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next
const void *buf;
int kind;
- PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
- if (writer == NULL) {
- goto bail;
- }
+ PyUnicodeWriter *writer = NULL;
len = PyUnicode_GET_LENGTH(pystr);
buf = PyUnicode_DATA(pystr);
@@ -419,12 +409,11 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next
if (c == '"') {
// Fast path for simple case.
- if (_PyUnicodeWriter_IsEmpty(writer)) {
+ if (writer == NULL) {
PyObject *ret = PyUnicode_Substring(pystr, end, next);
if (ret == NULL) {
goto bail;
}
- PyUnicodeWriter_Discard(writer);
*next_end_ptr = next + 1;;
return ret;
}
@@ -432,6 +421,11 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict, Py_ssize_t *next
else if (c != '\\') {
raise_errmsg("Unterminated string starting at", pystr, begin);
goto bail;
+ } else if (writer == NULL) {
+ writer = PyUnicodeWriter_Create(0);
+ if (writer == NULL) {
+ goto bail;
+ }
}
/* Pick up this chunk if it's not zero length */
@@ -1476,13 +1470,13 @@ encoder_listencode_obj(PyEncoderObject *s, PyUnicodeWriter *writer,
int rv;
if (obj == Py_None) {
- return PyUnicodeWriter_WriteUTF8(writer, "null", 4);
+ return PyUnicodeWriter_WriteASCII(writer, "null", 4);
}
else if (obj == Py_True) {
- return PyUnicodeWriter_WriteUTF8(writer, "true", 4);
+ return PyUnicodeWriter_WriteASCII(writer, "true", 4);
}
else if (obj == Py_False) {
- return PyUnicodeWriter_WriteUTF8(writer, "false", 5);
+ return PyUnicodeWriter_WriteASCII(writer, "false", 5);
}
else if (PyUnicode_Check(obj)) {
PyObject *encoded = encoder_encode_string(s, obj);
@@ -1649,7 +1643,7 @@ encoder_listencode_dict(PyEncoderObject *s, PyUnicodeWriter *writer,
if (PyDict_GET_SIZE(dct) == 0) {
/* Fast path */
- return PyUnicodeWriter_WriteUTF8(writer, "{}", 2);
+ return PyUnicodeWriter_WriteASCII(writer, "{}", 2);
}
if (s->markers != Py_None) {
@@ -1753,7 +1747,7 @@ encoder_listencode_list(PyEncoderObject *s, PyUnicodeWriter *writer,
return -1;
if (PySequence_Fast_GET_SIZE(s_fast) == 0) {
Py_DECREF(s_fast);
- return PyUnicodeWriter_WriteUTF8(writer, "[]", 2);
+ return PyUnicodeWriter_WriteASCII(writer, "[]", 2);
}
if (s->markers != Py_None) {
diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c
index ad618398d5b..c1f56008b7c 100644
--- a/Modules/_localemodule.c
+++ b/Modules/_localemodule.c
@@ -692,7 +692,17 @@ _locale_nl_langinfo_impl(PyObject *module, int item)
result = result != NULL ? result : "";
char *oldloc = NULL;
if (langinfo_constants[i].category != LC_CTYPE
- && !is_all_ascii(result)
+ && (
+#ifdef __GLIBC__
+ // gh-133740: Always change the locale for ALT_DIGITS and ERA
+# ifdef ALT_DIGITS
+ item == ALT_DIGITS ||
+# endif
+# ifdef ERA
+ item == ERA ||
+# endif
+#endif
+ !is_all_ascii(result))
&& change_locale(langinfo_constants[i].category, &oldloc) < 0)
{
return NULL;
diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c
index 626c176715b..bbad5eb6903 100644
--- a/Modules/_lsprof.c
+++ b/Modules/_lsprof.c
@@ -782,7 +782,7 @@ _lsprof_Profiler_enable_impl(ProfilerObject *self, int subcalls,
return NULL;
}
- PyObject* monitoring = PyImport_ImportModuleAttrString("sys", "monitoring");
+ PyObject* monitoring = PySys_GetAttrString("monitoring");
if (!monitoring) {
return NULL;
}
@@ -864,7 +864,7 @@ _lsprof_Profiler_disable_impl(ProfilerObject *self)
}
if (self->flags & POF_ENABLED) {
PyObject* result = NULL;
- PyObject* monitoring = PyImport_ImportModuleAttrString("sys", "monitoring");
+ PyObject* monitoring = PySys_GetAttrString("monitoring");
if (!monitoring) {
return NULL;
@@ -983,7 +983,7 @@ profiler_init_impl(ProfilerObject *self, PyObject *timer, double timeunit,
Py_XSETREF(self->externalTimer, Py_XNewRef(timer));
self->tool_id = PY_MONITORING_PROFILER_ID;
- PyObject* monitoring = PyImport_ImportModuleAttrString("sys", "monitoring");
+ PyObject* monitoring = PySys_GetAttrString("monitoring");
if (!monitoring) {
return -1;
}
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index d260f1a68f8..86d8b38620c 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -1879,6 +1879,10 @@ _checkmodule(PyObject *module_name, PyObject *module,
_PyUnicode_EqualToASCIIString(module_name, "__main__")) {
return -1;
}
+ if (PyUnicode_Check(module_name) &&
+ _PyUnicode_EqualToASCIIString(module_name, "__mp_main__")) {
+ return -1;
+ }
PyObject *candidate = getattribute(module, dotted_path, 0);
if (candidate == NULL) {
@@ -1911,7 +1915,7 @@ whichmodule(PickleState *st, PyObject *global, PyObject *global_name, PyObject *
__module__ can be None. If it is so, then search sys.modules for
the module of global. */
Py_CLEAR(module_name);
- modules = _PySys_GetRequiredAttr(&_Py_ID(modules));
+ modules = PySys_GetAttr(&_Py_ID(modules));
if (modules == NULL) {
return NULL;
}
diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c
index d5bac2f5b78..2f4f388ce11 100644
--- a/Modules/_randommodule.c
+++ b/Modules/_randommodule.c
@@ -497,34 +497,32 @@ _random_Random_setstate_impl(RandomObject *self, PyObject *state)
_random.Random.getrandbits
self: self(type="RandomObject *")
- k: int
+ k: uint64
/
getrandbits(k) -> x. Generates an int with k random bits.
[clinic start generated code]*/
static PyObject *
-_random_Random_getrandbits_impl(RandomObject *self, int k)
-/*[clinic end generated code: output=b402f82a2158887f input=87603cd60f79f730]*/
+_random_Random_getrandbits_impl(RandomObject *self, uint64_t k)
+/*[clinic end generated code: output=c30ef8435f3433cf input=64226ac13bb4d2a3]*/
{
- int i, words;
+ Py_ssize_t i, words;
uint32_t r;
uint32_t *wordarray;
PyObject *result;
- if (k < 0) {
- PyErr_SetString(PyExc_ValueError,
- "number of bits must be non-negative");
- return NULL;
- }
-
if (k == 0)
return PyLong_FromLong(0);
if (k <= 32) /* Fast path */
return PyLong_FromUnsignedLong(genrand_uint32(self) >> (32 - k));
- words = (k - 1) / 32 + 1;
+ if ((k - 1u) / 32u + 1u > PY_SSIZE_T_MAX / 4u) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ words = (k - 1u) / 32u + 1u;
wordarray = (uint32_t *)PyMem_Malloc(words * 4);
if (wordarray == NULL) {
PyErr_NoMemory();
diff --git a/Modules/_remote_debugging_module.c b/Modules/_remote_debugging_module.c
index 9314ddd9bed..ea58f38006e 100644
--- a/Modules/_remote_debugging_module.c
+++ b/Modules/_remote_debugging_module.c
@@ -1,5 +1,16 @@
+/******************************************************************************
+ * Python Remote Debugging Module
+ *
+ * This module provides functionality to debug Python processes remotely by
+ * reading their memory and reconstructing stack traces and asyncio task states.
+ ******************************************************************************/
+
#define _GNU_SOURCE
+/* ============================================================================
+ * HEADERS AND INCLUDES
+ * ============================================================================ */
+
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
@@ -23,6 +34,47 @@
# define HAVE_PROCESS_VM_READV 0
#endif
+/* ============================================================================
+ * TYPE DEFINITIONS AND STRUCTURES
+ * ============================================================================ */
+
+#define GET_MEMBER(type, obj, offset) (*(type*)((char*)(obj) + (offset)))
+
+/* Size macros for opaque buffers */
+#define SIZEOF_BYTES_OBJ sizeof(PyBytesObject)
+#define SIZEOF_CODE_OBJ sizeof(PyCodeObject)
+#define SIZEOF_GEN_OBJ sizeof(PyGenObject)
+#define SIZEOF_INTERP_FRAME sizeof(_PyInterpreterFrame)
+#define SIZEOF_LLIST_NODE sizeof(struct llist_node)
+#define SIZEOF_PAGE_CACHE_ENTRY sizeof(page_cache_entry_t)
+#define SIZEOF_PYOBJECT sizeof(PyObject)
+#define SIZEOF_SET_OBJ sizeof(PySetObject)
+#define SIZEOF_TASK_OBJ 4096
+#define SIZEOF_THREAD_STATE sizeof(PyThreadState)
+#define SIZEOF_TYPE_OBJ sizeof(PyTypeObject)
+#define SIZEOF_UNICODE_OBJ sizeof(PyUnicodeObject)
+#define SIZEOF_LONG_OBJ sizeof(PyLongObject)
+
+// Calculate the minimum buffer size needed to read interpreter state fields
+// We need to read code_object_generation and potentially tlbc_generation
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifdef Py_GIL_DISABLED
+#define INTERP_STATE_MIN_SIZE MAX(MAX(offsetof(PyInterpreterState, _code_object_generation) + sizeof(uint64_t), \
+ offsetof(PyInterpreterState, tlbc_indices.tlbc_generation) + sizeof(uint32_t)), \
+ offsetof(PyInterpreterState, threads.head) + sizeof(void*))
+#else
+#define INTERP_STATE_MIN_SIZE MAX(offsetof(PyInterpreterState, _code_object_generation) + sizeof(uint64_t), \
+ offsetof(PyInterpreterState, threads.head) + sizeof(void*))
+#endif
+#define INTERP_STATE_BUFFER_SIZE MAX(INTERP_STATE_MIN_SIZE, 256)
+
+
+
+// Copied from Modules/_asynciomodule.c because it's not exported
+
struct _Py_AsyncioModuleDebugOffsets {
struct _asyncio_task_object {
uint64_t size;
@@ -45,147 +97,299 @@ struct _Py_AsyncioModuleDebugOffsets {
} asyncio_thread_state;
};
-// Helper to chain exceptions and avoid repetitions
-static void
-chain_exceptions(PyObject *exception, const char *string)
-{
- PyObject *exc = PyErr_GetRaisedException();
- PyErr_SetString(exception, string);
- _PyErr_ChainExceptions1(exc);
-}
+typedef struct {
+ PyObject_HEAD
+ proc_handle_t handle;
+ uintptr_t runtime_start_address;
+ struct _Py_DebugOffsets debug_offsets;
+ int async_debug_offsets_available;
+ struct _Py_AsyncioModuleDebugOffsets async_debug_offsets;
+ uintptr_t interpreter_addr;
+ uintptr_t tstate_addr;
+ uint64_t code_object_generation;
+ _Py_hashtable_t *code_object_cache;
+ int debug;
+#ifdef Py_GIL_DISABLED
+ // TLBC cache invalidation tracking
+ uint32_t tlbc_generation; // Track TLBC index pool changes
+ _Py_hashtable_t *tlbc_cache; // Cache of TLBC arrays by code object address
+#endif
+} RemoteUnwinderObject;
-// Get the PyAsyncioDebug section address for any platform
-static uintptr_t
-_Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
+typedef struct {
+ PyObject *func_name;
+ PyObject *file_name;
+ int first_lineno;
+ PyObject *linetable; // bytes
+ uintptr_t addr_code_adaptive;
+} CachedCodeMetadata;
+
+typedef struct {
+ /* Types */
+ PyTypeObject *RemoteDebugging_Type;
+} RemoteDebuggingState;
+
+typedef struct
{
- uintptr_t address;
+ int lineno;
+ int end_lineno;
+ int column;
+ int end_column;
+} LocationInfo;
-#ifdef MS_WINDOWS
- // On Windows, search for asyncio debug in executable or DLL
- address = search_windows_map_for_section(handle, "AsyncioD", L"_asyncio");
-#elif defined(__linux__)
- // On Linux, search for asyncio debug in executable or DLL
- address = search_linux_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
-#elif defined(__APPLE__) && TARGET_OS_OSX
- // On macOS, try libpython first, then fall back to python
- address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
- if (address == 0) {
- PyErr_Clear();
- address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
+typedef struct {
+ uintptr_t remote_addr;
+ size_t size;
+ void *local_copy;
+} StackChunkInfo;
+
+typedef struct {
+ StackChunkInfo *chunks;
+ size_t count;
+} StackChunkList;
+
+#include "clinic/_remote_debugging_module.c.h"
+
+/*[clinic input]
+module _remote_debugging
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5f507d5b2e76a7f7]*/
+
+
+/* ============================================================================
+ * FORWARD DECLARATIONS
+ * ============================================================================ */
+
+static int
+parse_tasks_in_set(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t set_addr,
+ PyObject *awaited_by,
+ int recurse_task
+);
+
+static int
+parse_task(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t task_address,
+ PyObject *render_to,
+ int recurse_task
+);
+
+static int
+parse_coro_chain(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t coro_address,
+ PyObject *render_to
+);
+
+/* Forward declarations for task parsing functions */
+static int parse_frame_object(
+ RemoteUnwinderObject *unwinder,
+ PyObject** result,
+ uintptr_t address,
+ uintptr_t* previous_frame
+);
+
+/* ============================================================================
+ * UTILITY FUNCTIONS AND HELPERS
+ * ============================================================================ */
+
+#define set_exception_cause(unwinder, exc_type, message) \
+ if (unwinder->debug) { \
+ _set_debug_exception_cause(exc_type, message); \
}
-#else
- Py_UNREACHABLE();
-#endif
- return address;
+static void
+cached_code_metadata_destroy(void *ptr)
+{
+ CachedCodeMetadata *meta = (CachedCodeMetadata *)ptr;
+ Py_DECREF(meta->func_name);
+ Py_DECREF(meta->file_name);
+ Py_DECREF(meta->linetable);
+ PyMem_RawFree(meta);
}
-static inline int
-read_ptr(proc_handle_t *handle, uintptr_t address, uintptr_t *ptr_addr)
+static inline RemoteDebuggingState *
+RemoteDebugging_GetState(PyObject *module)
{
- int result = _Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(void*), ptr_addr);
- if (result < 0) {
- return -1;
- }
- return 0;
+ void *state = _PyModule_GetState(module);
+ assert(state != NULL);
+ return (RemoteDebuggingState *)state;
}
static inline int
-read_Py_ssize_t(proc_handle_t *handle, uintptr_t address, Py_ssize_t *size)
+RemoteDebugging_InitState(RemoteDebuggingState *st)
{
- int result = _Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(Py_ssize_t), size);
- if (result < 0) {
- return -1;
- }
return 0;
}
static int
-read_py_ptr(proc_handle_t *handle, uintptr_t address, uintptr_t *ptr_addr)
+is_prerelease_version(uint64_t version)
{
- if (read_ptr(handle, address, ptr_addr)) {
+ return (version & 0xF0) != 0xF0;
+}
+
+static inline int
+validate_debug_offsets(struct _Py_DebugOffsets *debug_offsets)
+{
+ if (memcmp(debug_offsets->cookie, _Py_Debug_Cookie, sizeof(debug_offsets->cookie)) != 0) {
+ // The remote is probably running a Python version predating debug offsets.
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "Can't determine the Python version of the remote process");
return -1;
}
- *ptr_addr &= ~Py_TAG_BITS;
+
+ // Assume debug offsets could change from one pre-release version to another,
+ // or one minor version to another, but are stable across patch versions.
+ if (is_prerelease_version(Py_Version) && Py_Version != debug_offsets->version) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "Can't attach from a pre-release Python interpreter"
+ " to a process running a different Python version");
+ return -1;
+ }
+
+ if (is_prerelease_version(debug_offsets->version) && Py_Version != debug_offsets->version) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "Can't attach to a pre-release Python interpreter"
+ " from a process running a different Python version");
+ return -1;
+ }
+
+ unsigned int remote_major = (debug_offsets->version >> 24) & 0xFF;
+ unsigned int remote_minor = (debug_offsets->version >> 16) & 0xFF;
+
+ if (PY_MAJOR_VERSION != remote_major || PY_MINOR_VERSION != remote_minor) {
+ PyErr_Format(
+ PyExc_RuntimeError,
+ "Can't attach from a Python %d.%d process to a Python %d.%d process",
+ PY_MAJOR_VERSION, PY_MINOR_VERSION, remote_major, remote_minor);
+ return -1;
+ }
+
+ // The debug offsets differ between free threaded and non-free threaded builds.
+ if (_Py_Debug_Free_Threaded && !debug_offsets->free_threaded) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "Cannot attach from a free-threaded Python process"
+ " to a process running a non-free-threaded version");
+ return -1;
+ }
+
+ if (!_Py_Debug_Free_Threaded && debug_offsets->free_threaded) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "Cannot attach to a free-threaded Python process"
+ " from a process running a non-free-threaded version");
+ return -1;
+ }
+
return 0;
}
-static int
-read_char(proc_handle_t *handle, uintptr_t address, char *result)
+/* ============================================================================
+ * MEMORY READING FUNCTIONS
+ * ============================================================================ */
+
+static inline int
+read_ptr(RemoteUnwinderObject *unwinder, uintptr_t address, uintptr_t *ptr_addr)
{
- int res = _Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(char), result);
- if (res < 0) {
+ int result = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, address, sizeof(void*), ptr_addr);
+ if (result < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read pointer from remote memory");
return -1;
}
return 0;
}
-static int
-read_sized_int(proc_handle_t *handle, uintptr_t address, void *result, size_t size)
+static inline int
+read_Py_ssize_t(RemoteUnwinderObject *unwinder, uintptr_t address, Py_ssize_t *size)
{
- int res = _Py_RemoteDebug_ReadRemoteMemory(handle, address, size, result);
- if (res < 0) {
+ int result = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, address, sizeof(Py_ssize_t), size);
+ if (result < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read Py_ssize_t from remote memory");
return -1;
}
return 0;
}
static int
-read_unsigned_long(proc_handle_t *handle, uintptr_t address, unsigned long *result)
+read_py_ptr(RemoteUnwinderObject *unwinder, uintptr_t address, uintptr_t *ptr_addr)
{
- int res = _Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(unsigned long), result);
- if (res < 0) {
+ if (read_ptr(unwinder, address, ptr_addr)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read Python pointer");
return -1;
}
+ *ptr_addr &= ~Py_TAG_BITS;
return 0;
}
static int
-read_pyobj(proc_handle_t *handle, uintptr_t address, PyObject *ptr_addr)
+read_char(RemoteUnwinderObject *unwinder, uintptr_t address, char *result)
{
- int res = _Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(PyObject), ptr_addr);
+ int res = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, address, sizeof(char), result);
if (res < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read char from remote memory");
return -1;
}
return 0;
}
+/* ============================================================================
+ * PYTHON OBJECT READING FUNCTIONS
+ * ============================================================================ */
+
static PyObject *
read_py_str(
- proc_handle_t *handle,
- _Py_DebugOffsets* debug_offsets,
+ RemoteUnwinderObject *unwinder,
uintptr_t address,
Py_ssize_t max_len
) {
PyObject *result = NULL;
char *buf = NULL;
- Py_ssize_t len;
- int res = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- address + debug_offsets->unicode_object.length,
- sizeof(Py_ssize_t),
- &len
+ // Read the entire PyUnicodeObject at once
+ char unicode_obj[SIZEOF_UNICODE_OBJ];
+ int res = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ address,
+ SIZEOF_UNICODE_OBJ,
+ unicode_obj
);
if (res < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read PyUnicodeObject");
goto err;
}
+ Py_ssize_t len = GET_MEMBER(Py_ssize_t, unicode_obj, unwinder->debug_offsets.unicode_object.length);
+ if (len < 0 || len > max_len) {
+ PyErr_Format(PyExc_RuntimeError,
+ "Invalid string length (%zd) at 0x%lx", len, address);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid string length in remote Unicode object");
+ return NULL;
+ }
+
buf = (char *)PyMem_RawMalloc(len+1);
if (buf == NULL) {
PyErr_NoMemory();
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate buffer for string reading");
return NULL;
}
- size_t offset = debug_offsets->unicode_object.asciiobject_size;
- res = _Py_RemoteDebug_ReadRemoteMemory(handle, address + offset, len, buf);
+ size_t offset = unwinder->debug_offsets.unicode_object.asciiobject_size;
+ res = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, address + offset, len, buf);
if (res < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read string data from remote memory");
goto err;
}
buf[len] = '\0';
result = PyUnicode_FromStringAndSize(buf, len);
if (result == NULL) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to create PyUnicode from remote string data");
goto err;
}
@@ -202,39 +406,52 @@ err:
static PyObject *
read_py_bytes(
- proc_handle_t *handle,
- _Py_DebugOffsets* debug_offsets,
- uintptr_t address
+ RemoteUnwinderObject *unwinder,
+ uintptr_t address,
+ Py_ssize_t max_len
) {
PyObject *result = NULL;
char *buf = NULL;
- Py_ssize_t len;
- int res = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- address + debug_offsets->bytes_object.ob_size,
- sizeof(Py_ssize_t),
- &len
+ // Read the entire PyBytesObject at once
+ char bytes_obj[SIZEOF_BYTES_OBJ];
+ int res = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ address,
+ SIZEOF_BYTES_OBJ,
+ bytes_obj
);
if (res < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read PyBytesObject");
goto err;
}
+ Py_ssize_t len = GET_MEMBER(Py_ssize_t, bytes_obj, unwinder->debug_offsets.bytes_object.ob_size);
+ if (len < 0 || len > max_len) {
+ PyErr_Format(PyExc_RuntimeError,
+ "Invalid bytes length (%zd) at 0x%lx", len, address);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Invalid bytes length in remote bytes object");
+ return NULL;
+ }
+
buf = (char *)PyMem_RawMalloc(len+1);
if (buf == NULL) {
PyErr_NoMemory();
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate buffer for bytes reading");
return NULL;
}
- size_t offset = debug_offsets->bytes_object.ob_sval;
- res = _Py_RemoteDebug_ReadRemoteMemory(handle, address + offset, len, buf);
+ size_t offset = unwinder->debug_offsets.bytes_object.ob_sval;
+ res = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, address + offset, len, buf);
if (res < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read bytes data from remote memory");
goto err;
}
buf[len] = '\0';
result = PyBytes_FromStringAndSize(buf, len);
if (result == NULL) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to create PyBytes from remote bytes data");
goto err;
}
@@ -249,45 +466,64 @@ err:
return NULL;
}
-
-
static long
-read_py_long(proc_handle_t *handle, _Py_DebugOffsets* offsets, uintptr_t address)
+read_py_long(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t address
+)
{
unsigned int shift = PYLONG_BITS_IN_DIGIT;
- Py_ssize_t size;
- uintptr_t lv_tag;
-
- int bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle, address + offsets->long_object.lv_tag,
- sizeof(uintptr_t),
- &lv_tag);
+ // Read the entire PyLongObject at once
+ char long_obj[SIZEOF_LONG_OBJ];
+ int bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ address,
+ unwinder->debug_offsets.long_object.size,
+ long_obj);
if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read PyLongObject");
return -1;
}
+ uintptr_t lv_tag = GET_MEMBER(uintptr_t, long_obj, unwinder->debug_offsets.long_object.lv_tag);
int negative = (lv_tag & 3) == 2;
- size = lv_tag >> 3;
+ Py_ssize_t size = lv_tag >> 3;
if (size == 0) {
return 0;
}
- digit *digits = (digit *)PyMem_RawMalloc(size * sizeof(digit));
- if (!digits) {
- PyErr_NoMemory();
- return -1;
- }
+ // If the long object has inline digits, use them directly
+ digit *digits;
+ if (size <= _PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS) {
+ // For small integers, digits are inline in the long_value.ob_digit array
+ digits = (digit *)PyMem_RawMalloc(size * sizeof(digit));
+ if (!digits) {
+ PyErr_NoMemory();
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate digits for small PyLong");
+ return -1;
+ }
+ memcpy(digits, long_obj + unwinder->debug_offsets.long_object.ob_digit, size * sizeof(digit));
+ } else {
+ // For larger integers, we need to read the digits separately
+ digits = (digit *)PyMem_RawMalloc(size * sizeof(digit));
+ if (!digits) {
+ PyErr_NoMemory();
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate digits for large PyLong");
+ return -1;
+ }
- bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- address + offsets->long_object.ob_digit,
- sizeof(digit) * size,
- digits
- );
- if (bytes_read < 0) {
- goto error;
+ bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ address + unwinder->debug_offsets.long_object.ob_digit,
+ sizeof(digit) * size,
+ digits
+ );
+ if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read PyLong digits from remote memory");
+ goto error;
+ }
}
long long value = 0;
@@ -310,400 +546,532 @@ error:
return -1;
}
+/* ============================================================================
+ * ASYNCIO DEBUG FUNCTIONS
+ * ============================================================================ */
+
+// Get the PyAsyncioDebug section address for any platform
+static uintptr_t
+_Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle)
+{
+ uintptr_t address;
+
+#ifdef MS_WINDOWS
+ // On Windows, search for asyncio debug in executable or DLL
+ address = search_windows_map_for_section(handle, "AsyncioD", L"_asyncio");
+ if (address == 0) {
+ // Error out: 'python' substring covers both executable and DLL
+ PyObject *exc = PyErr_GetRaisedException();
+ PyErr_SetString(PyExc_RuntimeError, "Failed to find the AsyncioDebug section in the process.");
+ _PyErr_ChainExceptions1(exc);
+ }
+#elif defined(__linux__)
+ // On Linux, search for asyncio debug in executable or DLL
+ address = search_linux_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
+ if (address == 0) {
+ // Error out: 'python' substring covers both executable and DLL
+ PyObject *exc = PyErr_GetRaisedException();
+ PyErr_SetString(PyExc_RuntimeError, "Failed to find the AsyncioDebug section in the process.");
+ _PyErr_ChainExceptions1(exc);
+ }
+#elif defined(__APPLE__) && TARGET_OS_OSX
+ // On macOS, try libpython first, then fall back to python
+ address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
+ if (address == 0) {
+ PyErr_Clear();
+ address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython");
+ }
+ if (address == 0) {
+ // Error out: 'python' substring covers both executable and DLL
+ PyObject *exc = PyErr_GetRaisedException();
+ PyErr_SetString(PyExc_RuntimeError, "Failed to find the AsyncioDebug section in the process.");
+ _PyErr_ChainExceptions1(exc);
+ }
+#else
+ Py_UNREACHABLE();
+#endif
+
+ return address;
+}
+
+static int
+read_async_debug(
+ RemoteUnwinderObject *unwinder
+) {
+ uintptr_t async_debug_addr = _Py_RemoteDebug_GetAsyncioDebugAddress(&unwinder->handle);
+ if (!async_debug_addr) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to get AsyncioDebug address");
+ return -1;
+ }
+
+ size_t size = sizeof(struct _Py_AsyncioModuleDebugOffsets);
+ int result = _Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, async_debug_addr, size, &unwinder->async_debug_offsets);
+ if (result < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read AsyncioDebug offsets");
+ }
+ return result;
+}
+
+/* ============================================================================
+ * ASYNCIO TASK PARSING FUNCTIONS
+ * ============================================================================ */
+
static PyObject *
parse_task_name(
- proc_handle_t *handle,
- _Py_DebugOffsets* offsets,
- struct _Py_AsyncioModuleDebugOffsets* async_offsets,
+ RemoteUnwinderObject *unwinder,
uintptr_t task_address
) {
- uintptr_t task_name_addr;
- int err = read_py_ptr(
- handle,
- task_address + async_offsets->asyncio_task_object.task_name,
- &task_name_addr);
- if (err) {
+ // Read the entire TaskObj at once
+ char task_obj[SIZEOF_TASK_OBJ];
+ int err = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ task_address,
+ unwinder->async_debug_offsets.asyncio_task_object.size,
+ task_obj);
+ if (err < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read task object");
return NULL;
}
- // The task name can be a long or a string so we need to check the type
+ uintptr_t task_name_addr = GET_MEMBER(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_name);
+ task_name_addr &= ~Py_TAG_BITS;
- PyObject task_name_obj;
- err = read_pyobj(
- handle,
+ // The task name can be a long or a string so we need to check the type
+ char task_name_obj[SIZEOF_PYOBJECT];
+ err = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
task_name_addr,
- &task_name_obj);
- if (err) {
+ SIZEOF_PYOBJECT,
+ task_name_obj);
+ if (err < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read task name object");
return NULL;
}
- unsigned long flags;
- err = read_unsigned_long(
- handle,
- (uintptr_t)task_name_obj.ob_type + offsets->type_object.tp_flags,
- &flags);
- if (err) {
+ // Now read the type object to get the flags
+ char type_obj[SIZEOF_TYPE_OBJ];
+ err = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ GET_MEMBER(uintptr_t, task_name_obj, unwinder->debug_offsets.pyobject.ob_type),
+ SIZEOF_TYPE_OBJ,
+ type_obj);
+ if (err < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read task name type object");
return NULL;
}
- if ((flags & Py_TPFLAGS_LONG_SUBCLASS)) {
- long res = read_py_long(handle, offsets, task_name_addr);
+ if ((GET_MEMBER(unsigned long, type_obj, unwinder->debug_offsets.type_object.tp_flags) & Py_TPFLAGS_LONG_SUBCLASS)) {
+ long res = read_py_long(unwinder, task_name_addr);
if (res == -1) {
- chain_exceptions(PyExc_RuntimeError, "Failed to get task name");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Task name PyLong parsing failed");
return NULL;
}
return PyUnicode_FromFormat("Task-%d", res);
}
- if(!(flags & Py_TPFLAGS_UNICODE_SUBCLASS)) {
+ if(!(GET_MEMBER(unsigned long, type_obj, unwinder->debug_offsets.type_object.tp_flags) & Py_TPFLAGS_UNICODE_SUBCLASS)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid task name object");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Task name object is neither long nor unicode");
return NULL;
}
return read_py_str(
- handle,
- offsets,
+ unwinder,
task_name_addr,
255
);
}
-static int
-parse_frame_object(
- proc_handle_t *handle,
- PyObject** result,
- struct _Py_DebugOffsets* offsets,
- uintptr_t address,
- uintptr_t* previous_frame
-);
-
-static int
-parse_coro_chain(
- proc_handle_t *handle,
- struct _Py_DebugOffsets* offsets,
- struct _Py_AsyncioModuleDebugOffsets* async_offsets,
- uintptr_t coro_address,
- PyObject *render_to
+static int parse_task_awaited_by(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t task_address,
+ PyObject *awaited_by,
+ int recurse_task
) {
- assert((void*)coro_address != NULL);
-
- uintptr_t gen_type_addr;
- int err = read_ptr(
- handle,
- coro_address + offsets->pyobject.ob_type,
- &gen_type_addr);
- if (err) {
+ // Read the entire TaskObj at once
+ char task_obj[SIZEOF_TASK_OBJ];
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, task_address,
+ unwinder->async_debug_offsets.asyncio_task_object.size,
+ task_obj) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read task object in awaited_by parsing");
return -1;
}
- PyObject* name = NULL;
- uintptr_t prev_frame;
- if (parse_frame_object(
- handle,
- &name,
- offsets,
- coro_address + offsets->gen_object.gi_iframe,
- &prev_frame)
- < 0)
- {
- return -1;
- }
+ uintptr_t task_ab_addr = GET_MEMBER(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_awaited_by);
+ task_ab_addr &= ~Py_TAG_BITS;
- if (PyList_Append(render_to, name)) {
- Py_DECREF(name);
- return -1;
+ if ((void*)task_ab_addr == NULL) {
+ return 0;
}
- Py_DECREF(name);
- int8_t gi_frame_state;
- err = read_sized_int(
- handle,
- coro_address + offsets->gen_object.gi_frame_state,
- &gi_frame_state,
- sizeof(int8_t)
- );
- if (err) {
- return -1;
- }
+ char awaited_by_is_a_set = GET_MEMBER(char, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_awaited_by_is_set);
- if (gi_frame_state == FRAME_SUSPENDED_YIELD_FROM) {
- char owner;
- err = read_char(
- handle,
- coro_address + offsets->gen_object.gi_iframe +
- offsets->interpreter_frame.owner,
- &owner
- );
- if (err) {
+ if (awaited_by_is_a_set) {
+ if (parse_tasks_in_set(unwinder, task_ab_addr, awaited_by, recurse_task)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse tasks in awaited_by set");
return -1;
}
- if (owner != FRAME_OWNED_BY_GENERATOR) {
- PyErr_SetString(
- PyExc_RuntimeError,
- "generator doesn't own its frame \\_o_/");
+ } else {
+ if (parse_task(unwinder, task_ab_addr, awaited_by, recurse_task)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse single awaited_by task");
return -1;
}
+ }
+
+ return 0;
+}
+
+static int
+handle_yield_from_frame(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t gi_iframe_addr,
+ uintptr_t gen_type_addr,
+ PyObject *render_to
+) {
+ // Read the entire interpreter frame at once
+ char iframe[SIZEOF_INTERP_FRAME];
+ int err = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ gi_iframe_addr,
+ SIZEOF_INTERP_FRAME,
+ iframe);
+ if (err < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read interpreter frame in yield_from handler");
+ return -1;
+ }
+
+ if (GET_MEMBER(char, iframe, unwinder->debug_offsets.interpreter_frame.owner) != FRAME_OWNED_BY_GENERATOR) {
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "generator doesn't own its frame \\_o_/");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Frame ownership mismatch in yield_from");
+ return -1;
+ }
+
+ uintptr_t stackpointer_addr = GET_MEMBER(uintptr_t, iframe, unwinder->debug_offsets.interpreter_frame.stackpointer);
+ stackpointer_addr &= ~Py_TAG_BITS;
- uintptr_t stackpointer_addr;
+ if ((void*)stackpointer_addr != NULL) {
+ uintptr_t gi_await_addr;
err = read_py_ptr(
- handle,
- coro_address + offsets->gen_object.gi_iframe +
- offsets->interpreter_frame.stackpointer,
- &stackpointer_addr);
+ unwinder,
+ stackpointer_addr - sizeof(void*),
+ &gi_await_addr);
if (err) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read gi_await address");
return -1;
}
- if ((void*)stackpointer_addr != NULL) {
- uintptr_t gi_await_addr;
- err = read_py_ptr(
- handle,
- stackpointer_addr - sizeof(void*),
- &gi_await_addr);
+ if ((void*)gi_await_addr != NULL) {
+ uintptr_t gi_await_addr_type_addr;
+ err = read_ptr(
+ unwinder,
+ gi_await_addr + unwinder->debug_offsets.pyobject.ob_type,
+ &gi_await_addr_type_addr);
if (err) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read gi_await type address");
return -1;
}
- if ((void*)gi_await_addr != NULL) {
- uintptr_t gi_await_addr_type_addr;
- int err = read_ptr(
- handle,
- gi_await_addr + offsets->pyobject.ob_type,
- &gi_await_addr_type_addr);
+ if (gen_type_addr == gi_await_addr_type_addr) {
+ /* This needs an explanation. We always start with parsing
+ native coroutine / generator frames. Ultimately they
+ are awaiting on something. That something can be
+ a native coroutine frame or... an iterator.
+ If it's the latter -- we can't continue building
+ our chain. So the condition to bail out of this is
+ to do that when the type of the current coroutine
+ doesn't match the type of whatever it points to
+ in its cr_await.
+ */
+ err = parse_coro_chain(unwinder, gi_await_addr, render_to);
if (err) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse coroutine chain in yield_from");
return -1;
}
-
- if (gen_type_addr == gi_await_addr_type_addr) {
- /* This needs an explanation. We always start with parsing
- native coroutine / generator frames. Ultimately they
- are awaiting on something. That something can be
- a native coroutine frame or... an iterator.
- If it's the latter -- we can't continue building
- our chain. So the condition to bail out of this is
- to do that when the type of the current coroutine
- doesn't match the type of whatever it points to
- in its cr_await.
- */
- err = parse_coro_chain(
- handle,
- offsets,
- async_offsets,
- gi_await_addr,
- render_to
- );
- if (err) {
- return -1;
- }
- }
}
}
-
}
return 0;
}
-
static int
-parse_task_awaited_by(
- proc_handle_t *handle,
- struct _Py_DebugOffsets* offsets,
- struct _Py_AsyncioModuleDebugOffsets* async_offsets,
- uintptr_t task_address,
- PyObject *awaited_by,
- int recurse_task
-);
+parse_coro_chain(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t coro_address,
+ PyObject *render_to
+) {
+ assert((void*)coro_address != NULL);
+ // Read the entire generator object at once
+ char gen_object[SIZEOF_GEN_OBJ];
+ int err = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ coro_address,
+ SIZEOF_GEN_OBJ,
+ gen_object);
+ if (err < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read generator object in coro chain");
+ return -1;
+ }
-static int
-parse_task(
- proc_handle_t *handle,
- struct _Py_DebugOffsets* offsets,
- struct _Py_AsyncioModuleDebugOffsets* async_offsets,
+ uintptr_t gen_type_addr = GET_MEMBER(uintptr_t, gen_object, unwinder->debug_offsets.pyobject.ob_type);
+
+ PyObject* name = NULL;
+
+ // Parse the previous frame using the gi_iframe from local copy
+ uintptr_t prev_frame;
+ uintptr_t gi_iframe_addr = coro_address + unwinder->debug_offsets.gen_object.gi_iframe;
+ if (parse_frame_object(unwinder, &name, gi_iframe_addr, &prev_frame) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse frame object in coro chain");
+ return -1;
+ }
+
+ if (PyList_Append(render_to, name)) {
+ Py_DECREF(name);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append frame to coro chain");
+ return -1;
+ }
+ Py_DECREF(name);
+
+ if (GET_MEMBER(int8_t, gen_object, unwinder->debug_offsets.gen_object.gi_frame_state) == FRAME_SUSPENDED_YIELD_FROM) {
+ return handle_yield_from_frame(unwinder, gi_iframe_addr, gen_type_addr, render_to);
+ }
+
+ return 0;
+}
+
+static PyObject*
+create_task_result(
+ RemoteUnwinderObject *unwinder,
uintptr_t task_address,
- PyObject *render_to,
int recurse_task
) {
- char is_task;
- int err = read_char(
- handle,
- task_address + async_offsets->asyncio_task_object.task_is_task,
- &is_task);
- if (err) {
- return -1;
- }
+ PyObject* result = NULL;
+ PyObject *call_stack = NULL;
+ PyObject *tn = NULL;
+ char task_obj[SIZEOF_TASK_OBJ];
+ uintptr_t coro_addr;
- PyObject* result = PyList_New(0);
+ result = PyList_New(0);
if (result == NULL) {
- return -1;
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create task result list");
+ goto error;
}
- PyObject *call_stack = PyList_New(0);
+ call_stack = PyList_New(0);
if (call_stack == NULL) {
- goto err;
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create call stack list");
+ goto error;
}
+
if (PyList_Append(result, call_stack)) {
- Py_DECREF(call_stack);
- goto err;
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append call stack to task result");
+ goto error;
}
- /* we can operate on a borrowed one to simplify cleanup */
- Py_DECREF(call_stack);
+ Py_CLEAR(call_stack);
- if (is_task) {
- PyObject *tn = NULL;
- if (recurse_task) {
- tn = parse_task_name(
- handle, offsets, async_offsets, task_address);
- } else {
- tn = PyLong_FromUnsignedLongLong(task_address);
+ if (recurse_task) {
+ tn = parse_task_name(unwinder, task_address);
+ } else {
+ tn = PyLong_FromUnsignedLongLong(task_address);
+ }
+ if (tn == NULL) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to create task name/address");
+ goto error;
+ }
+
+ if (PyList_Append(result, tn)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append task name to result");
+ goto error;
+ }
+ Py_CLEAR(tn);
+
+ // Parse coroutine chain
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, task_address,
+ unwinder->async_debug_offsets.asyncio_task_object.size,
+ task_obj) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read task object for coro chain");
+ goto error;
+ }
+
+ coro_addr = GET_MEMBER(uintptr_t, task_obj, unwinder->async_debug_offsets.asyncio_task_object.task_coro);
+ coro_addr &= ~Py_TAG_BITS;
+
+ if ((void*)coro_addr != NULL) {
+ call_stack = PyList_New(0);
+ if (call_stack == NULL) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create coro call stack list");
+ goto error;
}
- if (tn == NULL) {
- goto err;
+
+ if (parse_coro_chain(unwinder, coro_addr, call_stack) < 0) {
+ Py_DECREF(call_stack);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse coroutine chain");
+ goto error;
}
- if (PyList_Append(result, tn)) {
- Py_DECREF(tn);
- goto err;
+
+ if (PyList_Reverse(call_stack)) {
+ Py_DECREF(call_stack);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to reverse call stack");
+ goto error;
}
- Py_DECREF(tn);
- uintptr_t coro_addr;
- err = read_py_ptr(
- handle,
- task_address + async_offsets->asyncio_task_object.task_coro,
- &coro_addr);
- if (err) {
- goto err;
+ if (PyList_SetItem(result, 0, call_stack) < 0) {
+ Py_DECREF(call_stack);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to set call stack in result");
+ goto error;
}
+ }
- if ((void*)coro_addr != NULL) {
- err = parse_coro_chain(
- handle,
- offsets,
- async_offsets,
- coro_addr,
- call_stack
- );
- if (err) {
- goto err;
- }
+ return result;
- if (PyList_Reverse(call_stack)) {
- goto err;
- }
+error:
+ Py_XDECREF(result);
+ Py_XDECREF(call_stack);
+ Py_XDECREF(tn);
+ return NULL;
+}
+
+static int
+parse_task(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t task_address,
+ PyObject *render_to,
+ int recurse_task
+) {
+ char is_task;
+ PyObject* result = NULL;
+ PyObject* awaited_by = NULL;
+ int err;
+
+ err = read_char(
+ unwinder,
+ task_address + unwinder->async_debug_offsets.asyncio_task_object.task_is_task,
+ &is_task);
+ if (err) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read is_task flag");
+ goto error;
+ }
+
+ if (is_task) {
+ result = create_task_result(unwinder, task_address, recurse_task);
+ if (!result) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to create task result");
+ goto error;
+ }
+ } else {
+ result = PyList_New(0);
+ if (result == NULL) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create empty task result");
+ goto error;
}
}
if (PyList_Append(render_to, result)) {
- goto err;
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append task result to render list");
+ goto error;
}
if (recurse_task) {
- PyObject *awaited_by = PyList_New(0);
+ awaited_by = PyList_New(0);
if (awaited_by == NULL) {
- goto err;
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create awaited_by list");
+ goto error;
}
+
if (PyList_Append(result, awaited_by)) {
- Py_DECREF(awaited_by);
- goto err;
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append awaited_by to result");
+ goto error;
}
- /* we can operate on a borrowed one to simplify cleanup */
Py_DECREF(awaited_by);
- if (parse_task_awaited_by(handle, offsets, async_offsets,
- task_address, awaited_by, 1)
- ) {
- goto err;
+ /* awaited_by is borrowed from 'result' to simplify cleanup */
+ if (parse_task_awaited_by(unwinder, task_address, awaited_by, 1) < 0) {
+ // Clear the pointer so the cleanup doesn't try to decref it since
+ // it's borrowed from 'result' and will be decrefed when result is
+ // deleted.
+ awaited_by = NULL;
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse task awaited_by relationships");
+ goto error;
}
}
Py_DECREF(result);
return 0;
-err:
- Py_DECREF(result);
+error:
+ Py_XDECREF(result);
+ Py_XDECREF(awaited_by);
return -1;
}
static int
-parse_tasks_in_set(
- proc_handle_t *handle,
- struct _Py_DebugOffsets* offsets,
- struct _Py_AsyncioModuleDebugOffsets* async_offsets,
- uintptr_t set_addr,
+process_set_entry(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t table_ptr,
PyObject *awaited_by,
int recurse_task
) {
- uintptr_t set_obj;
- if (read_py_ptr(
- handle,
- set_addr,
- &set_obj)
- ) {
+ uintptr_t key_addr;
+ if (read_py_ptr(unwinder, table_ptr, &key_addr)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read set entry key");
return -1;
}
- Py_ssize_t num_els;
- if (read_Py_ssize_t(
- handle,
- set_obj + offsets->set_object.used,
- &num_els)
- ) {
- return -1;
- }
+ if ((void*)key_addr != NULL) {
+ Py_ssize_t ref_cnt;
+ if (read_Py_ssize_t(unwinder, table_ptr, &ref_cnt)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read set entry reference count");
+ return -1;
+ }
- Py_ssize_t set_len;
- if (read_Py_ssize_t(
- handle,
- set_obj + offsets->set_object.mask,
- &set_len)
- ) {
- return -1;
+ if (ref_cnt) {
+ // if 'ref_cnt=0' it's a set dummy marker
+ if (parse_task(unwinder, key_addr, awaited_by, recurse_task)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse task in set entry");
+ return -1;
+ }
+ return 1; // Successfully processed a valid entry
+ }
}
- set_len++; // The set contains the `mask+1` element slots.
+ return 0; // Entry was NULL or dummy marker
+}
- uintptr_t table_ptr;
- if (read_ptr(
- handle,
- set_obj + offsets->set_object.table,
- &table_ptr)
- ) {
+static int
+parse_tasks_in_set(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t set_addr,
+ PyObject *awaited_by,
+ int recurse_task
+) {
+ char set_object[SIZEOF_SET_OBJ];
+ int err = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ set_addr,
+ SIZEOF_SET_OBJ,
+ set_object);
+ if (err < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read set object");
return -1;
}
+ Py_ssize_t num_els = GET_MEMBER(Py_ssize_t, set_object, unwinder->debug_offsets.set_object.used);
+ Py_ssize_t set_len = GET_MEMBER(Py_ssize_t, set_object, unwinder->debug_offsets.set_object.mask) + 1; // The set contains the `mask+1` element slots.
+ uintptr_t table_ptr = GET_MEMBER(uintptr_t, set_object, unwinder->debug_offsets.set_object.table);
+
Py_ssize_t i = 0;
Py_ssize_t els = 0;
- while (i < set_len) {
- uintptr_t key_addr;
- if (read_py_ptr(handle, table_ptr, &key_addr)) {
+ while (i < set_len && els < num_els) {
+ int result = process_set_entry(unwinder, table_ptr, awaited_by, recurse_task);
+
+ if (result < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to process set entry");
return -1;
}
-
- if ((void*)key_addr != NULL) {
- Py_ssize_t ref_cnt;
- if (read_Py_ssize_t(handle, table_ptr, &ref_cnt)) {
- return -1;
- }
-
- if (ref_cnt) {
- // if 'ref_cnt=0' it's a set dummy marker
-
- if (parse_task(
- handle,
- offsets,
- async_offsets,
- key_addr,
- awaited_by,
- recurse_task
- )
- ) {
- return -1;
- }
-
- if (++els == num_els) {
- break;
- }
- }
+ if (result > 0) {
+ els++;
}
table_ptr += sizeof(void*) * 2;
@@ -714,81 +1082,244 @@ parse_tasks_in_set(
static int
-parse_task_awaited_by(
- proc_handle_t *handle,
- struct _Py_DebugOffsets* offsets,
- struct _Py_AsyncioModuleDebugOffsets* async_offsets,
- uintptr_t task_address,
- PyObject *awaited_by,
- int recurse_task
+setup_async_result_structure(RemoteUnwinderObject *unwinder, PyObject **result, PyObject **calls)
+{
+ *result = PyList_New(1);
+ if (*result == NULL) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create async result structure");
+ return -1;
+ }
+
+ *calls = PyList_New(0);
+ if (*calls == NULL) {
+ Py_DECREF(*result);
+ *result = NULL;
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create calls list in async result");
+ return -1;
+ }
+
+ if (PyList_SetItem(*result, 0, *calls)) { /* steals ref to 'calls' */
+ Py_DECREF(*calls);
+ Py_DECREF(*result);
+ *result = NULL;
+ *calls = NULL;
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to set calls list in async result");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+add_task_info_to_result(
+ RemoteUnwinderObject *unwinder,
+ PyObject *result,
+ uintptr_t running_task_addr
) {
- uintptr_t task_ab_addr;
- int err = read_py_ptr(
- handle,
- task_address + async_offsets->asyncio_task_object.task_awaited_by,
- &task_ab_addr);
- if (err) {
+ PyObject *tn = parse_task_name(unwinder, running_task_addr);
+ if (tn == NULL) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse task name for result");
return -1;
}
- if ((void*)task_ab_addr == NULL) {
- return 0;
+ if (PyList_Append(result, tn)) {
+ Py_DECREF(tn);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append task name to result");
+ return -1;
}
+ Py_DECREF(tn);
- char awaited_by_is_a_set;
- err = read_char(
- handle,
- task_address + async_offsets->asyncio_task_object.task_awaited_by_is_set,
- &awaited_by_is_a_set);
- if (err) {
+ PyObject* awaited_by = PyList_New(0);
+ if (awaited_by == NULL) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create awaited_by list for result");
return -1;
}
- if (awaited_by_is_a_set) {
- if (parse_tasks_in_set(
- handle,
- offsets,
- async_offsets,
- task_address + async_offsets->asyncio_task_object.task_awaited_by,
- awaited_by,
- recurse_task
- )
- ) {
- return -1;
- }
- } else {
- uintptr_t sub_task;
- if (read_py_ptr(
- handle,
- task_address + async_offsets->asyncio_task_object.task_awaited_by,
- &sub_task)
- ) {
- return -1;
- }
+ if (PyList_Append(result, awaited_by)) {
+ Py_DECREF(awaited_by);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append awaited_by to result");
+ return -1;
+ }
+ Py_DECREF(awaited_by);
- if (parse_task(
- handle,
- offsets,
- async_offsets,
- sub_task,
- awaited_by,
- recurse_task
- )
- ) {
- return -1;
- }
+ if (parse_task_awaited_by(
+ unwinder, running_task_addr, awaited_by, 1) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse awaited_by for result");
+ return -1;
}
return 0;
}
-typedef struct
+static int
+process_single_task_node(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t task_addr,
+ PyObject *result
+) {
+ PyObject *tn = NULL;
+ PyObject *current_awaited_by = NULL;
+ PyObject *task_id = NULL;
+ PyObject *result_item = NULL;
+
+ tn = parse_task_name(unwinder, task_addr);
+ if (tn == NULL) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse task name in single task node");
+ goto error;
+ }
+
+ current_awaited_by = PyList_New(0);
+ if (current_awaited_by == NULL) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create awaited_by list in single task node");
+ goto error;
+ }
+
+ task_id = PyLong_FromUnsignedLongLong(task_addr);
+ if (task_id == NULL) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to create task ID in single task node");
+ goto error;
+ }
+
+ result_item = PyTuple_New(3);
+ if (result_item == NULL) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create result tuple in single task node");
+ goto error;
+ }
+
+ PyTuple_SET_ITEM(result_item, 0, task_id); // steals ref
+ PyTuple_SET_ITEM(result_item, 1, tn); // steals ref
+ PyTuple_SET_ITEM(result_item, 2, current_awaited_by); // steals ref
+
+ // References transferred to tuple
+ task_id = NULL;
+ tn = NULL;
+ current_awaited_by = NULL;
+
+ if (PyList_Append(result, result_item)) {
+ Py_DECREF(result_item);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append result item in single task node");
+ return -1;
+ }
+ Py_DECREF(result_item);
+
+ // Get back current_awaited_by reference for parse_task_awaited_by
+ current_awaited_by = PyTuple_GET_ITEM(result_item, 2);
+ if (parse_task_awaited_by(unwinder, task_addr, current_awaited_by, 0) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse awaited_by in single task node");
+ return -1;
+ }
+
+ return 0;
+
+error:
+ Py_XDECREF(tn);
+ Py_XDECREF(current_awaited_by);
+ Py_XDECREF(task_id);
+ Py_XDECREF(result_item);
+ return -1;
+}
+
+/* ============================================================================
+ * TLBC CACHING FUNCTIONS
+ * ============================================================================ */
+
+#ifdef Py_GIL_DISABLED
+
+typedef struct {
+ void *tlbc_array; // Local copy of the TLBC array
+ Py_ssize_t tlbc_array_size; // Size of the TLBC array
+ uint32_t generation; // Generation when this was cached
+} TLBCCacheEntry;
+
+static void
+tlbc_cache_entry_destroy(void *ptr)
{
- int lineno;
- int end_lineno;
- int column;
- int end_column;
-} LocationInfo;
+ TLBCCacheEntry *entry = (TLBCCacheEntry *)ptr;
+ if (entry->tlbc_array) {
+ PyMem_RawFree(entry->tlbc_array);
+ }
+ PyMem_RawFree(entry);
+}
+
+static TLBCCacheEntry *
+get_tlbc_cache_entry(RemoteUnwinderObject *self, uintptr_t code_addr, uint32_t current_generation)
+{
+ void *key = (void *)code_addr;
+ TLBCCacheEntry *entry = _Py_hashtable_get(self->tlbc_cache, key);
+
+ if (entry && entry->generation != current_generation) {
+ // Entry is stale, remove it by setting to NULL
+ _Py_hashtable_set(self->tlbc_cache, key, NULL);
+ entry = NULL;
+ }
+
+ return entry;
+}
+
+static int
+cache_tlbc_array(RemoteUnwinderObject *unwinder, uintptr_t code_addr, uintptr_t tlbc_array_addr, uint32_t generation)
+{
+ uintptr_t tlbc_array_ptr;
+ void *tlbc_array = NULL;
+ TLBCCacheEntry *entry = NULL;
+
+ // Read the TLBC array pointer
+ if (read_ptr(unwinder, tlbc_array_addr, &tlbc_array_ptr) != 0 || tlbc_array_ptr == 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read TLBC array pointer");
+ return 0; // No TLBC array
+ }
+
+ // Read the TLBC array size
+ Py_ssize_t tlbc_size;
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, tlbc_array_ptr, sizeof(tlbc_size), &tlbc_size) != 0 || tlbc_size <= 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read TLBC array size");
+ return 0; // Invalid size
+ }
+
+ // Allocate and read the entire TLBC array
+ size_t array_data_size = tlbc_size * sizeof(void*);
+ tlbc_array = PyMem_RawMalloc(sizeof(Py_ssize_t) + array_data_size);
+ if (!tlbc_array) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate TLBC array");
+ return 0; // Memory error
+ }
+
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, tlbc_array_ptr, sizeof(Py_ssize_t) + array_data_size, tlbc_array) != 0) {
+ PyMem_RawFree(tlbc_array);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read TLBC array data");
+ return 0; // Read error
+ }
+
+ // Create cache entry
+ entry = PyMem_RawMalloc(sizeof(TLBCCacheEntry));
+ if (!entry) {
+ PyMem_RawFree(tlbc_array);
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate TLBC cache entry");
+ return 0; // Memory error
+ }
+
+ entry->tlbc_array = tlbc_array;
+ entry->tlbc_array_size = tlbc_size;
+ entry->generation = generation;
+
+ // Store in cache
+ void *key = (void *)code_addr;
+ if (_Py_hashtable_set(unwinder->tlbc_cache, key, entry) < 0) {
+ tlbc_cache_entry_destroy(entry);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to store TLBC entry in cache");
+ return 0; // Cache error
+ }
+
+ return 1; // Success
+}
+
+
+
+#endif
+
+/* ============================================================================
+ * LINE TABLE PARSING FUNCTIONS
+ * ============================================================================ */
static int
scan_varint(const uint8_t **ptr)
@@ -818,7 +1349,6 @@ scan_signed_varint(const uint8_t **ptr)
}
}
-
static bool
parse_linetable(const uintptr_t addrq, const char* linetable, int firstlineno, LocationInfo* info)
{
@@ -863,7 +1393,9 @@ parse_linetable(const uintptr_t addrq, const char* linetable, int firstlineno, L
}
default: {
uint8_t second_byte = *(ptr++);
- assert((second_byte & 128) == 0);
+ if ((second_byte & 128) != 0) {
+ return false;
+ }
info->column = code << 3 | (second_byte >> 4);
info->end_column = info->column + (second_byte & 15);
break;
@@ -877,270 +1409,443 @@ parse_linetable(const uintptr_t addrq, const char* linetable, int firstlineno, L
return false;
}
+/* ============================================================================
+ * CODE OBJECT AND FRAME PARSING FUNCTIONS
+ * ============================================================================ */
+
static int
-read_remote_pointer(proc_handle_t *handle, uintptr_t address, uintptr_t *out_ptr, const char *error_message)
+parse_code_object(RemoteUnwinderObject *unwinder,
+ PyObject **result,
+ uintptr_t address,
+ uintptr_t instruction_pointer,
+ uintptr_t *previous_frame,
+ int32_t tlbc_index)
{
- int bytes_read = _Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(void *), out_ptr);
- if (bytes_read < 0) {
- return -1;
+ void *key = (void *)address;
+ CachedCodeMetadata *meta = NULL;
+ PyObject *func = NULL;
+ PyObject *file = NULL;
+ PyObject *linetable = NULL;
+ PyObject *lineno = NULL;
+ PyObject *tuple = NULL;
+
+#ifdef Py_GIL_DISABLED
+ // In free threading builds, code object addresses might have the low bit set
+ // as a flag, so we need to mask it off to get the real address
+ uintptr_t real_address = address & (~1);
+#else
+ uintptr_t real_address = address;
+#endif
+
+ if (unwinder && unwinder->code_object_cache != NULL) {
+ meta = _Py_hashtable_get(unwinder->code_object_cache, key);
}
- if ((void *)(*out_ptr) == NULL) {
- PyErr_SetString(PyExc_RuntimeError, error_message);
- return -1;
+ if (meta == NULL) {
+ char code_object[SIZEOF_CODE_OBJ];
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle, real_address, SIZEOF_CODE_OBJ, code_object) < 0)
+ {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read code object");
+ goto error;
+ }
+
+ func = read_py_str(unwinder,
+ GET_MEMBER(uintptr_t, code_object, unwinder->debug_offsets.code_object.qualname), 1024);
+ if (!func) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read function name from code object");
+ goto error;
+ }
+
+ file = read_py_str(unwinder,
+ GET_MEMBER(uintptr_t, code_object, unwinder->debug_offsets.code_object.filename), 1024);
+ if (!file) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read filename from code object");
+ goto error;
+ }
+
+ linetable = read_py_bytes(unwinder,
+ GET_MEMBER(uintptr_t, code_object, unwinder->debug_offsets.code_object.linetable), 4096);
+ if (!linetable) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read linetable from code object");
+ goto error;
+ }
+
+ meta = PyMem_RawMalloc(sizeof(CachedCodeMetadata));
+ if (!meta) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate cached code metadata");
+ goto error;
+ }
+
+ meta->func_name = func;
+ meta->file_name = file;
+ meta->linetable = linetable;
+ meta->first_lineno = GET_MEMBER(int, code_object, unwinder->debug_offsets.code_object.firstlineno);
+ meta->addr_code_adaptive = real_address + unwinder->debug_offsets.code_object.co_code_adaptive;
+
+ if (unwinder && unwinder->code_object_cache && _Py_hashtable_set(unwinder->code_object_cache, key, meta) < 0) {
+ cached_code_metadata_destroy(meta);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to cache code metadata");
+ goto error;
+ }
+
+ // Ownership transferred to meta
+ func = NULL;
+ file = NULL;
+ linetable = NULL;
+ }
+
+ uintptr_t ip = instruction_pointer;
+ ptrdiff_t addrq;
+
+#ifdef Py_GIL_DISABLED
+ // Handle thread-local bytecode (TLBC) in free threading builds
+ if (tlbc_index == 0 || unwinder->debug_offsets.code_object.co_tlbc == 0 || unwinder == NULL) {
+ // No TLBC or no unwinder - use main bytecode directly
+ addrq = (uint16_t *)ip - (uint16_t *)meta->addr_code_adaptive;
+ goto done_tlbc;
+ }
+
+ // Try to get TLBC data from cache (we'll get generation from the caller)
+ TLBCCacheEntry *tlbc_entry = get_tlbc_cache_entry(unwinder, real_address, unwinder->tlbc_generation);
+
+ if (!tlbc_entry) {
+ // Cache miss - try to read and cache TLBC array
+ if (!cache_tlbc_array(unwinder, real_address, real_address + unwinder->debug_offsets.code_object.co_tlbc, unwinder->tlbc_generation)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to cache TLBC array");
+ goto error;
+ }
+ tlbc_entry = get_tlbc_cache_entry(unwinder, real_address, unwinder->tlbc_generation);
+ }
+
+ if (tlbc_entry && tlbc_index < tlbc_entry->tlbc_array_size) {
+ // Use cached TLBC data
+ uintptr_t *entries = (uintptr_t *)((char *)tlbc_entry->tlbc_array + sizeof(Py_ssize_t));
+ uintptr_t tlbc_bytecode_addr = entries[tlbc_index];
+
+ if (tlbc_bytecode_addr != 0) {
+ // Calculate offset from TLBC bytecode
+ addrq = (uint16_t *)ip - (uint16_t *)tlbc_bytecode_addr;
+ goto done_tlbc;
+ }
}
+ // Fall back to main bytecode
+ addrq = (uint16_t *)ip - (uint16_t *)meta->addr_code_adaptive;
+
+done_tlbc:
+#else
+ // Non-free-threaded build, always use the main bytecode
+ (void)tlbc_index; // Suppress unused parameter warning
+ (void)unwinder; // Suppress unused parameter warning
+ addrq = (uint16_t *)ip - (uint16_t *)meta->addr_code_adaptive;
+#endif
+ ; // Empty statement to avoid C23 extension warning
+ LocationInfo info = {0};
+ bool ok = parse_linetable(addrq, PyBytes_AS_STRING(meta->linetable),
+ meta->first_lineno, &info);
+ if (!ok) {
+ info.lineno = -1;
+ }
+
+ lineno = PyLong_FromLong(info.lineno);
+ if (!lineno) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to create line number object");
+ goto error;
+ }
+
+ tuple = PyTuple_New(3);
+ if (!tuple) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create result tuple for code object");
+ goto error;
+ }
+
+ Py_INCREF(meta->func_name);
+ Py_INCREF(meta->file_name);
+ PyTuple_SET_ITEM(tuple, 0, meta->file_name);
+ PyTuple_SET_ITEM(tuple, 1, lineno);
+ PyTuple_SET_ITEM(tuple, 2, meta->func_name);
+
+ *result = tuple;
return 0;
+
+error:
+ Py_XDECREF(func);
+ Py_XDECREF(file);
+ Py_XDECREF(linetable);
+ Py_XDECREF(lineno);
+ Py_XDECREF(tuple);
+ return -1;
}
-static int
-read_instruction_ptr(proc_handle_t *handle, struct _Py_DebugOffsets *offsets,
- uintptr_t current_frame, uintptr_t *instruction_ptr)
+/* ============================================================================
+ * STACK CHUNK MANAGEMENT FUNCTIONS
+ * ============================================================================ */
+
+static void
+cleanup_stack_chunks(StackChunkList *chunks)
{
- return read_remote_pointer(
- handle,
- current_frame + offsets->interpreter_frame.instr_ptr,
- instruction_ptr,
- "No instruction ptr found"
- );
+ for (size_t i = 0; i < chunks->count; ++i) {
+ PyMem_RawFree(chunks->chunks[i].local_copy);
+ }
+ PyMem_RawFree(chunks->chunks);
}
static int
-parse_code_object(proc_handle_t *handle,
- PyObject **result,
- struct _Py_DebugOffsets *offsets,
- uintptr_t address,
- uintptr_t current_frame,
- uintptr_t *previous_frame)
-{
- uintptr_t addr_func_name, addr_file_name, addr_linetable, instruction_ptr;
+process_single_stack_chunk(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t chunk_addr,
+ StackChunkInfo *chunk_info
+) {
+ // Start with default size assumption
+ size_t current_size = _PY_DATA_STACK_CHUNK_SIZE;
- if (read_remote_pointer(handle, address + offsets->code_object.qualname, &addr_func_name, "No function name found") < 0 ||
- read_remote_pointer(handle, address + offsets->code_object.filename, &addr_file_name, "No file name found") < 0 ||
- read_remote_pointer(handle, address + offsets->code_object.linetable, &addr_linetable, "No linetable found") < 0 ||
- read_instruction_ptr(handle, offsets, current_frame, &instruction_ptr) < 0) {
+ char *this_chunk = PyMem_RawMalloc(current_size);
+ if (!this_chunk) {
+ PyErr_NoMemory();
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate stack chunk buffer");
return -1;
}
- int firstlineno;
- if (_Py_RemoteDebug_ReadRemoteMemory(handle,
- address + offsets->code_object.firstlineno,
- sizeof(int),
- &firstlineno) < 0) {
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, chunk_addr, current_size, this_chunk) < 0) {
+ PyMem_RawFree(this_chunk);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read stack chunk");
return -1;
}
- PyObject *py_linetable = read_py_bytes(handle, offsets, addr_linetable);
- if (!py_linetable) {
- return -1;
+ // Check actual size and reread if necessary
+ size_t actual_size = GET_MEMBER(size_t, this_chunk, offsetof(_PyStackChunk, size));
+ if (actual_size != current_size) {
+ this_chunk = PyMem_RawRealloc(this_chunk, actual_size);
+ if (!this_chunk) {
+ PyErr_NoMemory();
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to reallocate stack chunk buffer");
+ return -1;
+ }
+
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, chunk_addr, actual_size, this_chunk) < 0) {
+ PyMem_RawFree(this_chunk);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to reread stack chunk with correct size");
+ return -1;
+ }
+ current_size = actual_size;
}
- uintptr_t addr_code_adaptive = address + offsets->code_object.co_code_adaptive;
- ptrdiff_t addrq = (uint16_t *)instruction_ptr - (uint16_t *)addr_code_adaptive;
+ chunk_info->remote_addr = chunk_addr;
+ chunk_info->size = current_size;
+ chunk_info->local_copy = this_chunk;
+ return 0;
+}
- LocationInfo info;
- parse_linetable(addrq, PyBytes_AS_STRING(py_linetable), firstlineno, &info);
- Py_DECREF(py_linetable); // Done with linetable
+static int
+copy_stack_chunks(RemoteUnwinderObject *unwinder,
+ uintptr_t tstate_addr,
+ StackChunkList *out_chunks)
+{
+ uintptr_t chunk_addr;
+ StackChunkInfo *chunks = NULL;
+ size_t count = 0;
+ size_t max_chunks = 16;
- PyObject *py_line = PyLong_FromLong(info.lineno);
- if (!py_line) {
+ if (read_ptr(unwinder, tstate_addr + unwinder->debug_offsets.thread_state.datastack_chunk, &chunk_addr)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read initial stack chunk address");
return -1;
}
- PyObject *py_func_name = read_py_str(handle, offsets, addr_func_name, 256);
- if (!py_func_name) {
- Py_DECREF(py_line);
+ chunks = PyMem_RawMalloc(max_chunks * sizeof(StackChunkInfo));
+ if (!chunks) {
+ PyErr_NoMemory();
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to allocate stack chunks array");
return -1;
}
- PyObject *py_file_name = read_py_str(handle, offsets, addr_file_name, 256);
- if (!py_file_name) {
- Py_DECREF(py_line);
- Py_DECREF(py_func_name);
- return -1;
+ while (chunk_addr != 0) {
+ // Grow array if needed
+ if (count >= max_chunks) {
+ max_chunks *= 2;
+ StackChunkInfo *new_chunks = PyMem_RawRealloc(chunks, max_chunks * sizeof(StackChunkInfo));
+ if (!new_chunks) {
+ PyErr_NoMemory();
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to grow stack chunks array");
+ goto error;
+ }
+ chunks = new_chunks;
+ }
+
+ // Process this chunk
+ if (process_single_stack_chunk(unwinder, chunk_addr, &chunks[count]) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to process stack chunk");
+ goto error;
+ }
+
+ // Get next chunk address and increment count
+ chunk_addr = GET_MEMBER(uintptr_t, chunks[count].local_copy, offsetof(_PyStackChunk, previous));
+ count++;
}
- PyObject *result_tuple = PyTuple_New(3);
- if (!result_tuple) {
- Py_DECREF(py_line);
- Py_DECREF(py_func_name);
- Py_DECREF(py_file_name);
- return -1;
+ out_chunks->chunks = chunks;
+ out_chunks->count = count;
+ return 0;
+
+error:
+ for (size_t i = 0; i < count; ++i) {
+ PyMem_RawFree(chunks[i].local_copy);
}
+ PyMem_RawFree(chunks);
+ return -1;
+}
- PyTuple_SET_ITEM(result_tuple, 0, py_func_name); // steals ref
- PyTuple_SET_ITEM(result_tuple, 1, py_file_name); // steals ref
- PyTuple_SET_ITEM(result_tuple, 2, py_line); // steals ref
+static void *
+find_frame_in_chunks(StackChunkList *chunks, uintptr_t remote_ptr)
+{
+ for (size_t i = 0; i < chunks->count; ++i) {
+ uintptr_t base = chunks->chunks[i].remote_addr + offsetof(_PyStackChunk, data);
+ size_t payload = chunks->chunks[i].size - offsetof(_PyStackChunk, data);
- *result = result_tuple;
- return 0;
+ if (remote_ptr >= base && remote_ptr < base + payload) {
+ return (char *)chunks->chunks[i].local_copy + (remote_ptr - chunks->chunks[i].remote_addr);
+ }
+ }
+ return NULL;
}
static int
-parse_frame_object(
- proc_handle_t *handle,
- PyObject** result,
- struct _Py_DebugOffsets* offsets,
+parse_frame_from_chunks(
+ RemoteUnwinderObject *unwinder,
+ PyObject **result,
uintptr_t address,
- uintptr_t* previous_frame
+ uintptr_t *previous_frame,
+ StackChunkList *chunks
) {
- int err;
-
- Py_ssize_t bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- address + offsets->interpreter_frame.previous,
- sizeof(void*),
- previous_frame
- );
- if (bytes_read < 0) {
+ void *frame_ptr = find_frame_in_chunks(chunks, address);
+ if (!frame_ptr) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Frame not found in stack chunks");
return -1;
}
- char owner;
- if (read_char(handle, address + offsets->interpreter_frame.owner, &owner)) {
- return -1;
- }
+ char *frame = (char *)frame_ptr;
+ *previous_frame = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.previous);
- if (owner >= FRAME_OWNED_BY_INTERPRETER) {
+ if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) >= FRAME_OWNED_BY_INTERPRETER ||
+ !GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable)) {
return 0;
}
- uintptr_t address_of_code_object;
- err = read_py_ptr(
- handle,
- address + offsets->interpreter_frame.executable,
- &address_of_code_object
- );
- if (err) {
- return -1;
- }
+ uintptr_t instruction_pointer = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.instr_ptr);
- if ((void*)address_of_code_object == NULL) {
- return 0;
+ // Get tlbc_index for free threading builds
+ int32_t tlbc_index = 0;
+#ifdef Py_GIL_DISABLED
+ if (unwinder->debug_offsets.interpreter_frame.tlbc_index != 0) {
+ tlbc_index = GET_MEMBER(int32_t, frame, unwinder->debug_offsets.interpreter_frame.tlbc_index);
}
+#endif
return parse_code_object(
- handle, result, offsets, address_of_code_object, address, previous_frame);
+ unwinder, result, GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable),
+ instruction_pointer, previous_frame, tlbc_index);
}
+/* ============================================================================
+ * INTERPRETER STATE AND THREAD DISCOVERY FUNCTIONS
+ * ============================================================================ */
+
static int
-parse_async_frame_object(
- proc_handle_t *handle,
- PyObject** result,
- struct _Py_DebugOffsets* offsets,
- uintptr_t address,
- uintptr_t* previous_frame,
- uintptr_t* code_object
+populate_initial_state_data(
+ int all_threads,
+ RemoteUnwinderObject *unwinder,
+ uintptr_t runtime_start_address,
+ uintptr_t *interpreter_state,
+ uintptr_t *tstate
) {
- int err;
-
- Py_ssize_t bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- address + offsets->interpreter_frame.previous,
- sizeof(void*),
- previous_frame
- );
- if (bytes_read < 0) {
- return -1;
- }
+ uint64_t interpreter_state_list_head =
+ unwinder->debug_offsets.runtime_state.interpreters_head;
- char owner;
- bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle, address + offsets->interpreter_frame.owner, sizeof(char), &owner);
+ uintptr_t address_of_interpreter_state;
+ int bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ runtime_start_address + interpreter_state_list_head,
+ sizeof(void*),
+ &address_of_interpreter_state);
if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read interpreter state address");
return -1;
}
- if (owner == FRAME_OWNED_BY_CSTACK || owner == FRAME_OWNED_BY_INTERPRETER) {
- return 0; // C frame
- }
-
- if (owner != FRAME_OWNED_BY_GENERATOR
- && owner != FRAME_OWNED_BY_THREAD) {
- PyErr_Format(PyExc_RuntimeError, "Unhandled frame owner %d.\n", owner);
+ if (address_of_interpreter_state == 0) {
+ PyErr_SetString(PyExc_RuntimeError, "No interpreter state found");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Interpreter state is NULL");
return -1;
}
- err = read_py_ptr(
- handle,
- address + offsets->interpreter_frame.executable,
- code_object
- );
- if (err) {
- return -1;
- }
+ *interpreter_state = address_of_interpreter_state;
- assert(code_object != NULL);
- if ((void*)*code_object == NULL) {
+ if (all_threads) {
+ *tstate = 0;
return 0;
}
- if (parse_code_object(
- handle, result, offsets, *code_object, address, previous_frame)) {
- return -1;
- }
+ uintptr_t address_of_thread = address_of_interpreter_state +
+ unwinder->debug_offsets.interpreter_state.threads_main;
- return 1;
-}
-
-static int
-read_async_debug(
- proc_handle_t *handle,
- struct _Py_AsyncioModuleDebugOffsets* async_debug
-) {
- uintptr_t async_debug_addr = _Py_RemoteDebug_GetAsyncioDebugAddress(handle);
- if (!async_debug_addr) {
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ address_of_thread,
+ sizeof(void*),
+ tstate) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read main thread state address");
return -1;
}
- size_t size = sizeof(struct _Py_AsyncioModuleDebugOffsets);
- int result = _Py_RemoteDebug_ReadRemoteMemory(handle, async_debug_addr, size, async_debug);
- return result;
+ return 0;
}
static int
find_running_frame(
- proc_handle_t *handle,
+ RemoteUnwinderObject *unwinder,
uintptr_t runtime_start_address,
- _Py_DebugOffsets* local_debug_offsets,
uintptr_t *frame
) {
uint64_t interpreter_state_list_head =
- local_debug_offsets->runtime_state.interpreters_head;
+ unwinder->debug_offsets.runtime_state.interpreters_head;
uintptr_t address_of_interpreter_state;
- int bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
+ int bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
runtime_start_address + interpreter_state_list_head,
sizeof(void*),
&address_of_interpreter_state);
if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read interpreter state for running frame");
return -1;
}
if (address_of_interpreter_state == 0) {
PyErr_SetString(PyExc_RuntimeError, "No interpreter state found");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Interpreter state is NULL in running frame search");
return -1;
}
uintptr_t address_of_thread;
- bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
+ bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
address_of_interpreter_state +
- local_debug_offsets->interpreter_state.threads_main,
+ unwinder->debug_offsets.interpreter_state.threads_main,
sizeof(void*),
&address_of_thread);
if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read thread address for running frame");
return -1;
}
// No Python frames are available for us (can happen at tear-down).
if ((void*)address_of_thread != NULL) {
int err = read_ptr(
- handle,
- address_of_thread + local_debug_offsets->thread_state.current_frame,
+ unwinder,
+ address_of_thread + unwinder->debug_offsets.thread_state.current_frame,
frame);
if (err) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read current frame pointer");
return -1;
}
return 0;
@@ -1152,40 +1857,40 @@ find_running_frame(
static int
find_running_task(
- proc_handle_t *handle,
- uintptr_t runtime_start_address,
- _Py_DebugOffsets *local_debug_offsets,
- struct _Py_AsyncioModuleDebugOffsets *async_offsets,
+ RemoteUnwinderObject *unwinder,
uintptr_t *running_task_addr
) {
*running_task_addr = (uintptr_t)NULL;
uint64_t interpreter_state_list_head =
- local_debug_offsets->runtime_state.interpreters_head;
+ unwinder->debug_offsets.runtime_state.interpreters_head;
uintptr_t address_of_interpreter_state;
- int bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- runtime_start_address + interpreter_state_list_head,
+ int bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ unwinder->runtime_start_address + interpreter_state_list_head,
sizeof(void*),
&address_of_interpreter_state);
if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read interpreter state for running task");
return -1;
}
if (address_of_interpreter_state == 0) {
PyErr_SetString(PyExc_RuntimeError, "No interpreter state found");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Interpreter state is NULL in running task search");
return -1;
}
uintptr_t address_of_thread;
- bytes_read = _Py_RemoteDebug_ReadRemoteMemory(
- handle,
+ bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
address_of_interpreter_state +
- local_debug_offsets->interpreter_state.threads_head,
+ unwinder->debug_offsets.interpreter_state.threads_head,
sizeof(void*),
&address_of_thread);
if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read thread head for running task");
return -1;
}
@@ -1196,11 +1901,12 @@ find_running_task(
}
bytes_read = read_py_ptr(
- handle,
+ unwinder,
address_of_thread
- + async_offsets->asyncio_thread_state.asyncio_running_loop,
+ + unwinder->async_debug_offsets.asyncio_thread_state.asyncio_running_loop,
&address_of_running_loop);
if (bytes_read == -1) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read running loop address");
return -1;
}
@@ -1210,11 +1916,12 @@ find_running_task(
}
int err = read_ptr(
- handle,
+ unwinder,
address_of_thread
- + async_offsets->asyncio_thread_state.asyncio_running_task,
+ + unwinder->async_debug_offsets.asyncio_thread_state.asyncio_running_task,
running_task_addr);
if (err) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read running task address");
return -1;
}
@@ -1222,94 +1929,269 @@ find_running_task(
}
static int
-append_awaited_by_for_thread(
- proc_handle_t *handle,
- uintptr_t head_addr,
- struct _Py_DebugOffsets *debug_offsets,
- struct _Py_AsyncioModuleDebugOffsets *async_offsets,
- PyObject *result
+find_running_task_and_coro(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t *running_task_addr,
+ uintptr_t *running_coro_addr,
+ uintptr_t *running_task_code_obj
) {
- struct llist_node task_node;
+ *running_task_addr = (uintptr_t)NULL;
+ if (find_running_task(
+ unwinder, running_task_addr) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Running task search failed");
+ return -1;
+ }
- if (0 > _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- head_addr,
- sizeof(task_node),
- &task_node))
- {
+ if ((void*)*running_task_addr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "No running task found");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Running task address is NULL");
return -1;
}
- size_t iteration_count = 0;
- const size_t MAX_ITERATIONS = 2 << 15; // A reasonable upper bound
- while ((uintptr_t)task_node.next != head_addr) {
- if (++iteration_count > MAX_ITERATIONS) {
- PyErr_SetString(PyExc_RuntimeError, "Task list appears corrupted");
- return -1;
- }
+ if (read_py_ptr(
+ unwinder,
+ *running_task_addr + unwinder->async_debug_offsets.asyncio_task_object.task_coro,
+ running_coro_addr) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Running task coro read failed");
+ return -1;
+ }
- if (task_node.next == NULL) {
- PyErr_SetString(
- PyExc_RuntimeError,
- "Invalid linked list structure reading remote memory");
- return -1;
- }
+ if ((void*)*running_coro_addr == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Running task coro is NULL");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Running task coro address is NULL");
+ return -1;
+ }
- uintptr_t task_addr = (uintptr_t)task_node.next
- - async_offsets->asyncio_task_object.task_node;
+ // note: genobject's gi_iframe is an embedded struct so the address to
+ // the offset leads directly to its first field: f_executable
+ if (read_py_ptr(
+ unwinder,
+ *running_coro_addr + unwinder->debug_offsets.gen_object.gi_iframe,
+ running_task_code_obj) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read running task code object");
+ return -1;
+ }
- PyObject *tn = parse_task_name(
- handle,
- debug_offsets,
- async_offsets,
- task_addr);
- if (tn == NULL) {
+ if ((void*)*running_task_code_obj == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Running task code object is NULL");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Running task code object address is NULL");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* ============================================================================
+ * FRAME PARSING FUNCTIONS
+ * ============================================================================ */
+
+static int
+parse_frame_object(
+ RemoteUnwinderObject *unwinder,
+ PyObject** result,
+ uintptr_t address,
+ uintptr_t* previous_frame
+) {
+ char frame[SIZEOF_INTERP_FRAME];
+
+ Py_ssize_t bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ address,
+ SIZEOF_INTERP_FRAME,
+ frame
+ );
+ if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read interpreter frame");
+ return -1;
+ }
+
+ *previous_frame = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.previous);
+
+ if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) >= FRAME_OWNED_BY_INTERPRETER) {
+ return 0;
+ }
+
+ if ((void*)GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable) == NULL) {
+ return 0;
+ }
+
+ uintptr_t instruction_pointer = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.instr_ptr);
+
+ // Get tlbc_index for free threading builds
+ int32_t tlbc_index = 0;
+#ifdef Py_GIL_DISABLED
+ if (unwinder->debug_offsets.interpreter_frame.tlbc_index != 0) {
+ tlbc_index = GET_MEMBER(int32_t, frame, unwinder->debug_offsets.interpreter_frame.tlbc_index);
+ }
+#endif
+
+ return parse_code_object(
+ unwinder, result, GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable),
+ instruction_pointer, previous_frame, tlbc_index);
+}
+
+static int
+parse_async_frame_object(
+ RemoteUnwinderObject *unwinder,
+ PyObject** result,
+ uintptr_t address,
+ uintptr_t* previous_frame,
+ uintptr_t* code_object
+) {
+ char frame[SIZEOF_INTERP_FRAME];
+
+ Py_ssize_t bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ address,
+ SIZEOF_INTERP_FRAME,
+ frame
+ );
+ if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read async frame");
+ return -1;
+ }
+
+ *previous_frame = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.previous);
+
+ *code_object = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.executable);
+ // Strip tag bits for consistent comparison
+ *code_object &= ~Py_TAG_BITS;
+ assert(code_object != NULL);
+ if ((void*)*code_object == NULL) {
+ return 0;
+ }
+
+ if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) == FRAME_OWNED_BY_CSTACK ||
+ GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) == FRAME_OWNED_BY_INTERPRETER) {
+ return 0; // C frame
+ }
+
+ if (GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) != FRAME_OWNED_BY_GENERATOR
+ && GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner) != FRAME_OWNED_BY_THREAD) {
+ PyErr_Format(PyExc_RuntimeError, "Unhandled frame owner %d.\n",
+ GET_MEMBER(char, frame, unwinder->debug_offsets.interpreter_frame.owner));
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Unhandled frame owner type in async frame");
+ return -1;
+ }
+
+ uintptr_t instruction_pointer = GET_MEMBER(uintptr_t, frame, unwinder->debug_offsets.interpreter_frame.instr_ptr);
+
+ // Get tlbc_index for free threading builds
+ int32_t tlbc_index = 0;
+#ifdef Py_GIL_DISABLED
+ if (unwinder->debug_offsets.interpreter_frame.tlbc_index != 0) {
+ tlbc_index = GET_MEMBER(int32_t, frame, unwinder->debug_offsets.interpreter_frame.tlbc_index);
+ }
+#endif
+
+ if (parse_code_object(
+ unwinder, result, *code_object, instruction_pointer, previous_frame, tlbc_index)) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse code object in async frame");
+ return -1;
+ }
+
+ return 1;
+}
+
+static int
+parse_async_frame_chain(
+ RemoteUnwinderObject *unwinder,
+ PyObject *calls,
+ uintptr_t running_task_code_obj
+) {
+ uintptr_t address_of_current_frame;
+ if (find_running_frame(unwinder, unwinder->runtime_start_address, &address_of_current_frame) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Running frame search failed in async chain");
+ return -1;
+ }
+
+ uintptr_t address_of_code_object;
+ while ((void*)address_of_current_frame != NULL) {
+ PyObject* frame_info = NULL;
+ int res = parse_async_frame_object(
+ unwinder,
+ &frame_info,
+ address_of_current_frame,
+ &address_of_current_frame,
+ &address_of_code_object
+ );
+
+ if (res < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Async frame object parsing failed in chain");
return -1;
}
- PyObject *current_awaited_by = PyList_New(0);
- if (current_awaited_by == NULL) {
- Py_DECREF(tn);
- return -1;
+ if (!frame_info) {
+ continue;
}
- PyObject* task_id = PyLong_FromUnsignedLongLong(task_addr);
- if (task_id == NULL) {
- Py_DECREF(tn);
- Py_DECREF(current_awaited_by);
+ if (PyList_Append(calls, frame_info) == -1) {
+ Py_DECREF(frame_info);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append frame info to async chain");
return -1;
}
- PyObject *result_item = PyTuple_New(3);
- if (result_item == NULL) {
- Py_DECREF(tn);
- Py_DECREF(current_awaited_by);
- Py_DECREF(task_id);
+ Py_DECREF(frame_info);
+
+ if (address_of_code_object == running_task_code_obj) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* ============================================================================
+ * AWAITED BY PARSING FUNCTIONS
+ * ============================================================================ */
+
+static int
+append_awaited_by_for_thread(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t head_addr,
+ PyObject *result
+) {
+ char task_node[SIZEOF_LLIST_NODE];
+
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(&unwinder->handle, head_addr,
+ sizeof(task_node), task_node) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read task node head");
+ return -1;
+ }
+
+ size_t iteration_count = 0;
+ const size_t MAX_ITERATIONS = 2 << 15; // A reasonable upper bound
+
+ while (GET_MEMBER(uintptr_t, task_node, unwinder->debug_offsets.llist_node.next) != head_addr) {
+ if (++iteration_count > MAX_ITERATIONS) {
+ PyErr_SetString(PyExc_RuntimeError, "Task list appears corrupted");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Task list iteration limit exceeded");
return -1;
}
- PyTuple_SET_ITEM(result_item, 0, task_id); // steals ref
- PyTuple_SET_ITEM(result_item, 1, tn); // steals ref
- PyTuple_SET_ITEM(result_item, 2, current_awaited_by); // steals ref
- if (PyList_Append(result, result_item)) {
- Py_DECREF(result_item);
+ if (GET_MEMBER(uintptr_t, task_node, unwinder->debug_offsets.llist_node.next) == 0) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Invalid linked list structure reading remote memory");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "NULL pointer in task linked list");
return -1;
}
- Py_DECREF(result_item);
- if (parse_task_awaited_by(handle, debug_offsets, async_offsets,
- task_addr, current_awaited_by, 0))
- {
+ uintptr_t task_addr = (uintptr_t)GET_MEMBER(uintptr_t, task_node, unwinder->debug_offsets.llist_node.next)
+ - unwinder->async_debug_offsets.asyncio_task_object.task_node;
+
+ if (process_single_task_node(unwinder, task_addr, result) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to process task node in awaited_by");
return -1;
}
- // onto the next one...
- if (0 > _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- (uintptr_t)task_node.next,
- sizeof(task_node),
- &task_node))
- {
+ // Read next node
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle,
+ (uintptr_t)GET_MEMBER(uintptr_t, task_node, unwinder->debug_offsets.llist_node.next),
+ sizeof(task_node),
+ task_node) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read next task node in awaited_by");
return -1;
}
}
@@ -1319,21 +2201,21 @@ append_awaited_by_for_thread(
static int
append_awaited_by(
- proc_handle_t *handle,
+ RemoteUnwinderObject *unwinder,
unsigned long tid,
uintptr_t head_addr,
- struct _Py_DebugOffsets *debug_offsets,
- struct _Py_AsyncioModuleDebugOffsets *async_offsets,
PyObject *result)
{
PyObject *tid_py = PyLong_FromUnsignedLong(tid);
if (tid_py == NULL) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to create thread ID object");
return -1;
}
PyObject *result_item = PyTuple_New(2);
if (result_item == NULL) {
Py_DECREF(tid_py);
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create awaited_by result tuple");
return -1;
}
@@ -1341,6 +2223,7 @@ append_awaited_by(
if (awaited_by_for_thread == NULL) {
Py_DECREF(tid_py);
Py_DECREF(result_item);
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create awaited_by thread list");
return -1;
}
@@ -1348,453 +2231,694 @@ append_awaited_by(
PyTuple_SET_ITEM(result_item, 1, awaited_by_for_thread); // steals ref
if (PyList_Append(result, result_item)) {
Py_DECREF(result_item);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append awaited_by result item");
return -1;
}
Py_DECREF(result_item);
- if (append_awaited_by_for_thread(
- handle,
- head_addr,
- debug_offsets,
- async_offsets,
- awaited_by_for_thread))
+ if (append_awaited_by_for_thread(unwinder, head_addr, awaited_by_for_thread))
{
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append awaited_by for thread");
return -1;
}
return 0;
}
+/* ============================================================================
+ * STACK UNWINDING FUNCTIONS
+ * ============================================================================ */
+
+static int
+process_frame_chain(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t initial_frame_addr,
+ StackChunkList *chunks,
+ PyObject *frame_info
+) {
+ uintptr_t frame_addr = initial_frame_addr;
+ uintptr_t prev_frame_addr = 0;
+ const size_t MAX_FRAMES = 1024;
+ size_t frame_count = 0;
+
+ while ((void*)frame_addr != NULL) {
+ PyObject *frame = NULL;
+ uintptr_t next_frame_addr = 0;
+
+ if (++frame_count > MAX_FRAMES) {
+ PyErr_SetString(PyExc_RuntimeError, "Too many stack frames (possible infinite loop)");
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Frame chain iteration limit exceeded");
+ return -1;
+ }
+
+ // Try chunks first, fallback to direct memory read
+ if (parse_frame_from_chunks(unwinder, &frame, frame_addr, &next_frame_addr, chunks) < 0) {
+ PyErr_Clear();
+ if (parse_frame_object(unwinder, &frame, frame_addr, &next_frame_addr) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to parse frame object in chain");
+ return -1;
+ }
+ }
+
+ if (!frame) {
+ break;
+ }
+
+ if (prev_frame_addr && frame_addr != prev_frame_addr) {
+ PyErr_Format(PyExc_RuntimeError,
+ "Broken frame chain: expected frame at 0x%lx, got 0x%lx",
+ prev_frame_addr, frame_addr);
+ Py_DECREF(frame);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Frame chain consistency check failed");
+ return -1;
+ }
+
+ if (PyList_Append(frame_info, frame) == -1) {
+ Py_DECREF(frame);
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to append frame to frame info list");
+ return -1;
+ }
+ Py_DECREF(frame);
+
+ prev_frame_addr = next_frame_addr;
+ frame_addr = next_frame_addr;
+ }
+
+ return 0;
+}
+
static PyObject*
-get_all_awaited_by(PyObject* self, PyObject* args)
-{
-#if (!defined(__linux__) && !defined(__APPLE__)) && !defined(MS_WINDOWS) || \
- (defined(__linux__) && !HAVE_PROCESS_VM_READV)
- PyErr_SetString(
- PyExc_RuntimeError,
- "get_all_awaited_by is not implemented on this platform");
+unwind_stack_for_thread(
+ RemoteUnwinderObject *unwinder,
+ uintptr_t *current_tstate
+) {
+ PyObject *frame_info = NULL;
+ PyObject *thread_id = NULL;
+ PyObject *result = NULL;
+ StackChunkList chunks = {0};
+
+ char ts[SIZEOF_THREAD_STATE];
+ int bytes_read = _Py_RemoteDebug_PagedReadRemoteMemory(
+ &unwinder->handle, *current_tstate, unwinder->debug_offsets.thread_state.size, ts);
+ if (bytes_read < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to read thread state");
+ goto error;
+ }
+
+ uintptr_t frame_addr = GET_MEMBER(uintptr_t, ts, unwinder->debug_offsets.thread_state.current_frame);
+
+ frame_info = PyList_New(0);
+ if (!frame_info) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create frame info list");
+ goto error;
+ }
+
+ if (copy_stack_chunks(unwinder, *current_tstate, &chunks) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to copy stack chunks");
+ goto error;
+ }
+
+ if (process_frame_chain(unwinder, frame_addr, &chunks, frame_info) < 0) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to process frame chain");
+ goto error;
+ }
+
+ *current_tstate = GET_MEMBER(uintptr_t, ts, unwinder->debug_offsets.thread_state.next);
+
+ thread_id = PyLong_FromLongLong(
+ GET_MEMBER(long, ts, unwinder->debug_offsets.thread_state.native_thread_id));
+ if (thread_id == NULL) {
+ set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to create thread ID");
+ goto error;
+ }
+
+ result = PyTuple_New(2);
+ if (result == NULL) {
+ set_exception_cause(unwinder, PyExc_MemoryError, "Failed to create thread unwind result tuple");
+ goto error;
+ }
+
+ PyTuple_SET_ITEM(result, 0, thread_id); // Steals reference
+ PyTuple_SET_ITEM(result, 1, frame_info); // Steals reference
+
+ cleanup_stack_chunks(&chunks);
+ return result;
+
+error:
+ Py_XDECREF(frame_info);
+ Py_XDECREF(thread_id);
+ Py_XDECREF(result);
+ cleanup_stack_chunks(&chunks);
return NULL;
-#endif
+}
- int pid;
- if (!PyArg_ParseTuple(args, "i", &pid)) {
- return NULL;
+
+/* ============================================================================
+ * REMOTEUNWINDER CLASS IMPLEMENTATION
+ * ============================================================================ */
+
+/*[clinic input]
+class _remote_debugging.RemoteUnwinder "RemoteUnwinderObject *" "&RemoteUnwinder_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=55f164d8803318be]*/
+
+/*[clinic input]
+_remote_debugging.RemoteUnwinder.__init__
+ pid: int
+ *
+ all_threads: bool = False
+ debug: bool = False
+
+Initialize a new RemoteUnwinder object for debugging a remote Python process.
+
+Args:
+ pid: Process ID of the target Python process to debug
+ all_threads: If True, initialize state for all threads in the process.
+ If False, only initialize for the main thread.
+ debug: If True, chain exceptions to explain the sequence of events that
+ lead to the exception.
+
+The RemoteUnwinder provides functionality to inspect and debug a running Python
+process, including examining thread states, stack frames and other runtime data.
+
+Raises:
+ PermissionError: If access to the target process is denied
+ OSError: If unable to attach to the target process or access its memory
+ RuntimeError: If unable to read debug information from the target process
+[clinic start generated code]*/
+
+static int
+_remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self,
+ int pid, int all_threads,
+ int debug)
+/*[clinic end generated code: output=3982f2a7eba49334 input=48a762566b828e91]*/
+{
+ self->debug = debug;
+ if (_Py_RemoteDebug_InitProcHandle(&self->handle, pid) < 0) {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to initialize process handle");
+ return -1;
}
- proc_handle_t the_handle;
- proc_handle_t *handle = &the_handle;
- if (_Py_RemoteDebug_InitProcHandle(handle, pid) < 0) {
- return 0;
+ self->runtime_start_address = _Py_RemoteDebug_GetPyRuntimeAddress(&self->handle);
+ if (self->runtime_start_address == 0) {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to get Python runtime address");
+ return -1;
}
- PyObject *result = NULL;
+ if (_Py_RemoteDebug_ReadDebugOffsets(&self->handle,
+ &self->runtime_start_address,
+ &self->debug_offsets) < 0)
+ {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to read debug offsets");
+ return -1;
+ }
- uintptr_t runtime_start_addr = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
- if (runtime_start_addr == 0) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(
- PyExc_RuntimeError, "Failed to get .PyRuntime address");
- }
- goto result_err;
+ // Validate that the debug offsets are valid
+ if(validate_debug_offsets(&self->debug_offsets) == -1) {
+ set_exception_cause(self, PyExc_RuntimeError, "Invalid debug offsets found");
+ return -1;
}
- struct _Py_DebugOffsets local_debug_offsets;
- if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_addr, &local_debug_offsets)) {
- chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
- goto result_err;
+ // Try to read async debug offsets, but don't fail if they're not available
+ self->async_debug_offsets_available = 1;
+ if (read_async_debug(self) < 0) {
+ PyErr_Clear();
+ memset(&self->async_debug_offsets, 0, sizeof(self->async_debug_offsets));
+ self->async_debug_offsets_available = 0;
}
- struct _Py_AsyncioModuleDebugOffsets local_async_debug;
- if (read_async_debug(handle, &local_async_debug)) {
- chain_exceptions(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
- goto result_err;
+ if (populate_initial_state_data(all_threads, self, self->runtime_start_address,
+ &self->interpreter_addr ,&self->tstate_addr) < 0)
+ {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to populate initial state data");
+ return -1;
+ }
+
+ self->code_object_cache = _Py_hashtable_new_full(
+ _Py_hashtable_hash_ptr,
+ _Py_hashtable_compare_direct,
+ NULL, // keys are stable pointers, don't destroy
+ cached_code_metadata_destroy,
+ NULL
+ );
+ if (self->code_object_cache == NULL) {
+ PyErr_NoMemory();
+ set_exception_cause(self, PyExc_MemoryError, "Failed to create code object cache");
+ return -1;
+ }
+
+#ifdef Py_GIL_DISABLED
+ // Initialize TLBC cache
+ self->tlbc_generation = 0;
+ self->tlbc_cache = _Py_hashtable_new_full(
+ _Py_hashtable_hash_ptr,
+ _Py_hashtable_compare_direct,
+ NULL, // keys are stable pointers, don't destroy
+ tlbc_cache_entry_destroy,
+ NULL
+ );
+ if (self->tlbc_cache == NULL) {
+ _Py_hashtable_destroy(self->code_object_cache);
+ PyErr_NoMemory();
+ set_exception_cause(self, PyExc_MemoryError, "Failed to create TLBC cache");
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+/*[clinic input]
+@critical_section
+_remote_debugging.RemoteUnwinder.get_stack_trace
+
+Returns a list of stack traces for all threads in the target process.
+
+Each element in the returned list is a tuple of (thread_id, frame_list), where:
+- thread_id is the OS thread identifier
+- frame_list is a list of tuples (function_name, filename, line_number) representing
+ the Python stack frames for that thread, ordered from most recent to oldest
+
+Example:
+ [
+ (1234, [
+ ('process_data', 'worker.py', 127),
+ ('run_worker', 'worker.py', 45),
+ ('main', 'app.py', 23)
+ ]),
+ (1235, [
+ ('handle_request', 'server.py', 89),
+ ('serve_forever', 'server.py', 52)
+ ])
+ ]
+
+Raises:
+ RuntimeError: If there is an error copying memory from the target process
+ OSError: If there is an error accessing the target process
+ PermissionError: If access to the target process is denied
+ UnicodeDecodeError: If there is an error decoding strings from the target process
+
+[clinic start generated code]*/
+
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self)
+/*[clinic end generated code: output=666192b90c69d567 input=331dbe370578badf]*/
+{
+ PyObject* result = NULL;
+ // Read interpreter state into opaque buffer
+ char interp_state_buffer[INTERP_STATE_BUFFER_SIZE];
+ if (_Py_RemoteDebug_PagedReadRemoteMemory(
+ &self->handle,
+ self->interpreter_addr,
+ INTERP_STATE_BUFFER_SIZE,
+ interp_state_buffer) < 0) {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to read interpreter state buffer");
+ goto exit;
+ }
+
+ // Get code object generation from buffer
+ uint64_t code_object_generation = GET_MEMBER(uint64_t, interp_state_buffer,
+ self->debug_offsets.interpreter_state.code_object_generation);
+
+ if (code_object_generation != self->code_object_generation) {
+ self->code_object_generation = code_object_generation;
+ _Py_hashtable_clear(self->code_object_cache);
+ }
+
+#ifdef Py_GIL_DISABLED
+ // Check TLBC generation and invalidate cache if needed
+ uint32_t current_tlbc_generation = GET_MEMBER(uint32_t, interp_state_buffer,
+ self->debug_offsets.interpreter_state.tlbc_generation);
+ if (current_tlbc_generation != self->tlbc_generation) {
+ self->tlbc_generation = current_tlbc_generation;
+ _Py_hashtable_clear(self->tlbc_cache);
+ }
+#endif
+
+ uintptr_t current_tstate;
+ if (self->tstate_addr == 0) {
+ // Get threads head from buffer
+ current_tstate = GET_MEMBER(uintptr_t, interp_state_buffer,
+ self->debug_offsets.interpreter_state.threads_head);
+ } else {
+ current_tstate = self->tstate_addr;
}
result = PyList_New(0);
- if (result == NULL) {
- goto result_err;
+ if (!result) {
+ set_exception_cause(self, PyExc_MemoryError, "Failed to create stack trace result list");
+ goto exit;
}
- uint64_t interpreter_state_list_head =
- local_debug_offsets.runtime_state.interpreters_head;
+ while (current_tstate != 0) {
+ PyObject* frame_info = unwind_stack_for_thread(self, &current_tstate);
+ if (!frame_info) {
+ Py_CLEAR(result);
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to unwind stack for thread");
+ goto exit;
+ }
- uintptr_t interpreter_state_addr;
- if (0 > _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- runtime_start_addr + interpreter_state_list_head,
- sizeof(void*),
- &interpreter_state_addr))
- {
+ if (PyList_Append(result, frame_info) == -1) {
+ Py_DECREF(frame_info);
+ Py_CLEAR(result);
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to append thread frame info");
+ goto exit;
+ }
+ Py_DECREF(frame_info);
+
+ // We are targeting a single tstate, break here
+ if (self->tstate_addr) {
+ break;
+ }
+ }
+
+exit:
+ _Py_RemoteDebug_ClearCache(&self->handle);
+ return result;
+}
+
+/*[clinic input]
+@critical_section
+_remote_debugging.RemoteUnwinder.get_all_awaited_by
+
+Get all tasks and their awaited_by relationships from the remote process.
+
+This provides a tree structure showing which tasks are waiting for other tasks.
+
+For each task, returns:
+1. The call stack frames leading to where the task is currently executing
+2. The name of the task
+3. A list of tasks that this task is waiting for, with their own frames/names/etc
+
+Returns a list of [frames, task_name, subtasks] where:
+- frames: List of (func_name, filename, lineno) showing the call stack
+- task_name: String identifier for the task
+- subtasks: List of tasks being awaited by this task, in same format
+
+Raises:
+ RuntimeError: If AsyncioDebug section is not available in the remote process
+ MemoryError: If memory allocation fails
+ OSError: If reading from the remote process fails
+
+Example output:
+[
+ # Task c2_root waiting for two subtasks
+ [
+ # Call stack of c2_root
+ [("c5", "script.py", 10), ("c4", "script.py", 14)],
+ "c2_root",
+ [
+ # First subtask (sub_main_2) and what it's waiting for
+ [
+ [("c1", "script.py", 23)],
+ "sub_main_2",
+ [...]
+ ],
+ # Second subtask and its waiters
+ [...]
+ ]
+ ]
+]
+[clinic start generated code]*/
+
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_all_awaited_by_impl(RemoteUnwinderObject *self)
+/*[clinic end generated code: output=6a49cd345e8aec53 input=a452c652bb00701a]*/
+{
+ if (!self->async_debug_offsets_available) {
+ PyErr_SetString(PyExc_RuntimeError, "AsyncioDebug section not available");
+ set_exception_cause(self, PyExc_RuntimeError, "AsyncioDebug section unavailable in get_all_awaited_by");
+ return NULL;
+ }
+
+ PyObject *result = PyList_New(0);
+ if (result == NULL) {
+ set_exception_cause(self, PyExc_MemoryError, "Failed to create awaited_by result list");
goto result_err;
}
uintptr_t thread_state_addr;
unsigned long tid = 0;
- if (0 > _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- interpreter_state_addr
- + local_debug_offsets.interpreter_state.threads_head,
+ if (0 > _Py_RemoteDebug_PagedReadRemoteMemory(
+ &self->handle,
+ self->interpreter_addr
+ + self->debug_offsets.interpreter_state.threads_main,
sizeof(void*),
&thread_state_addr))
{
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to read main thread state in get_all_awaited_by");
goto result_err;
}
uintptr_t head_addr;
while (thread_state_addr != 0) {
- if (0 > _Py_RemoteDebug_ReadRemoteMemory(
- handle,
+ if (0 > _Py_RemoteDebug_PagedReadRemoteMemory(
+ &self->handle,
thread_state_addr
- + local_debug_offsets.thread_state.native_thread_id,
+ + self->debug_offsets.thread_state.native_thread_id,
sizeof(tid),
&tid))
{
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to read thread ID in get_all_awaited_by");
goto result_err;
}
head_addr = thread_state_addr
- + local_async_debug.asyncio_thread_state.asyncio_tasks_head;
+ + self->async_debug_offsets.asyncio_thread_state.asyncio_tasks_head;
- if (append_awaited_by(handle, tid, head_addr, &local_debug_offsets,
- &local_async_debug, result))
+ if (append_awaited_by(self, tid, head_addr, result))
{
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to append awaited_by for thread in get_all_awaited_by");
goto result_err;
}
- if (0 > _Py_RemoteDebug_ReadRemoteMemory(
- handle,
- thread_state_addr + local_debug_offsets.thread_state.next,
+ if (0 > _Py_RemoteDebug_PagedReadRemoteMemory(
+ &self->handle,
+ thread_state_addr + self->debug_offsets.thread_state.next,
sizeof(void*),
&thread_state_addr))
{
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to read next thread state in get_all_awaited_by");
goto result_err;
}
}
- head_addr = interpreter_state_addr
- + local_async_debug.asyncio_interpreter_state.asyncio_tasks_head;
+ head_addr = self->interpreter_addr
+ + self->async_debug_offsets.asyncio_interpreter_state.asyncio_tasks_head;
// On top of a per-thread task lists used by default by asyncio to avoid
// contention, there is also a fallback per-interpreter list of tasks;
// any tasks still pending when a thread is destroyed will be moved to the
// per-interpreter task list. It's unlikely we'll find anything here, but
// interesting for debugging.
- if (append_awaited_by(handle, 0, head_addr, &local_debug_offsets,
- &local_async_debug, result))
+ if (append_awaited_by(self, 0, head_addr, result))
{
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to append interpreter awaited_by in get_all_awaited_by");
goto result_err;
}
- _Py_RemoteDebug_CleanupProcHandle(handle);
+ _Py_RemoteDebug_ClearCache(&self->handle);
return result;
result_err:
+ _Py_RemoteDebug_ClearCache(&self->handle);
Py_XDECREF(result);
- _Py_RemoteDebug_CleanupProcHandle(handle);
return NULL;
}
-static PyObject*
-get_stack_trace(PyObject* self, PyObject* args)
-{
-#if (!defined(__linux__) && !defined(__APPLE__)) && !defined(MS_WINDOWS) || \
- (defined(__linux__) && !HAVE_PROCESS_VM_READV)
- PyErr_SetString(
- PyExc_RuntimeError,
- "get_stack_trace is not supported on this platform");
- return NULL;
-#endif
-
- int pid;
- if (!PyArg_ParseTuple(args, "i", &pid)) {
- return NULL;
- }
+/*[clinic input]
+@critical_section
+_remote_debugging.RemoteUnwinder.get_async_stack_trace
- proc_handle_t the_handle;
- proc_handle_t *handle = &the_handle;
- if (_Py_RemoteDebug_InitProcHandle(handle, pid) < 0) {
- return 0;
- }
+Returns information about the currently running async task and its stack trace.
- PyObject* result = NULL;
+Returns a tuple of (task_info, stack_frames) where:
+- task_info is a tuple of (task_id, task_name) identifying the task
+- stack_frames is a list of tuples (function_name, filename, line_number) representing
+ the Python stack frames for the task, ordered from most recent to oldest
- uintptr_t runtime_start_address = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
- if (runtime_start_address == 0) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(
- PyExc_RuntimeError, "Failed to get .PyRuntime address");
- }
- goto result_err;
- }
- struct _Py_DebugOffsets local_debug_offsets;
+Example:
+ ((4345585712, 'Task-1'), [
+ ('run_echo_server', 'server.py', 127),
+ ('serve_forever', 'server.py', 45),
+ ('main', 'app.py', 23)
+ ])
- if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address, &local_debug_offsets)) {
- chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
- goto result_err;
- }
+Raises:
+ RuntimeError: If AsyncioDebug section is not available in the target process
+ RuntimeError: If there is an error copying memory from the target process
+ OSError: If there is an error accessing the target process
+ PermissionError: If access to the target process is denied
+ UnicodeDecodeError: If there is an error decoding strings from the target process
- uintptr_t address_of_current_frame;
- if (find_running_frame(
- handle, runtime_start_address, &local_debug_offsets,
- &address_of_current_frame)
- ) {
- goto result_err;
- }
-
- result = PyList_New(0);
- if (result == NULL) {
- goto result_err;
- }
-
- while ((void*)address_of_current_frame != NULL) {
- PyObject* frame_info = NULL;
- if (parse_frame_object(
- handle,
- &frame_info,
- &local_debug_offsets,
- address_of_current_frame,
- &address_of_current_frame)
- < 0)
- {
- Py_DECREF(result);
- goto result_err;
- }
-
- if (!frame_info) {
- continue;
- }
+[clinic start generated code]*/
- if (PyList_Append(result, frame_info) == -1) {
- Py_DECREF(result);
- goto result_err;
- }
-
- Py_DECREF(frame_info);
- frame_info = NULL;
-
- }
-
-result_err:
- _Py_RemoteDebug_CleanupProcHandle(handle);
- return result;
-}
-
-static PyObject*
-get_async_stack_trace(PyObject* self, PyObject* args)
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_async_stack_trace_impl(RemoteUnwinderObject *self)
+/*[clinic end generated code: output=6433d52b55e87bbe input=11b7150c59d4c60f]*/
{
-#if (!defined(__linux__) && !defined(__APPLE__)) && !defined(MS_WINDOWS) || \
- (defined(__linux__) && !HAVE_PROCESS_VM_READV)
- PyErr_SetString(
- PyExc_RuntimeError,
- "get_stack_trace is not supported on this platform");
- return NULL;
-#endif
- int pid;
-
- if (!PyArg_ParseTuple(args, "i", &pid)) {
+ if (!self->async_debug_offsets_available) {
+ PyErr_SetString(PyExc_RuntimeError, "AsyncioDebug section not available");
+ set_exception_cause(self, PyExc_RuntimeError, "AsyncioDebug section unavailable in get_async_stack_trace");
return NULL;
}
- proc_handle_t the_handle;
- proc_handle_t *handle = &the_handle;
- if (_Py_RemoteDebug_InitProcHandle(handle, pid) < 0) {
- return 0;
- }
-
PyObject *result = NULL;
+ PyObject *calls = NULL;
- uintptr_t runtime_start_address = _Py_RemoteDebug_GetPyRuntimeAddress(handle);
- if (runtime_start_address == 0) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(
- PyExc_RuntimeError, "Failed to get .PyRuntime address");
- }
- goto result_err;
+ if (setup_async_result_structure(self, &result, &calls) < 0) {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to setup async result structure");
+ goto cleanup;
}
- struct _Py_DebugOffsets local_debug_offsets;
- if (_Py_RemoteDebug_ReadDebugOffsets(handle, &runtime_start_address, &local_debug_offsets)) {
- chain_exceptions(PyExc_RuntimeError, "Failed to read debug offsets");
- goto result_err;
+ uintptr_t running_task_addr, running_coro_addr, running_task_code_obj;
+ if (find_running_task_and_coro(self, &running_task_addr,
+ &running_coro_addr, &running_task_code_obj) < 0) {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to find running task and coro");
+ goto cleanup;
}
- struct _Py_AsyncioModuleDebugOffsets local_async_debug;
- if (read_async_debug(handle, &local_async_debug)) {
- chain_exceptions(PyExc_RuntimeError, "Failed to read asyncio debug offsets");
- goto result_err;
+ if (parse_async_frame_chain(self, calls, running_task_code_obj) < 0) {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to parse async frame chain");
+ goto cleanup;
}
- result = PyList_New(1);
- if (result == NULL) {
- goto result_err;
- }
- PyObject* calls = PyList_New(0);
- if (calls == NULL) {
- goto result_err;
- }
- if (PyList_SetItem(result, 0, calls)) { /* steals ref to 'calls' */
- Py_DECREF(calls);
- goto result_err;
- }
-
- uintptr_t running_task_addr = (uintptr_t)NULL;
- if (find_running_task(
- handle, runtime_start_address, &local_debug_offsets, &local_async_debug,
- &running_task_addr)
- ) {
- chain_exceptions(PyExc_RuntimeError, "Failed to find running task");
- goto result_err;
+ if (add_task_info_to_result(self, result, running_task_addr) < 0) {
+ set_exception_cause(self, PyExc_RuntimeError, "Failed to add task info to result");
+ goto cleanup;
}
- if ((void*)running_task_addr == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "No running task found");
- goto result_err;
- }
+ _Py_RemoteDebug_ClearCache(&self->handle);
+ return result;
- uintptr_t running_coro_addr;
- if (read_py_ptr(
- handle,
- running_task_addr + local_async_debug.asyncio_task_object.task_coro,
- &running_coro_addr
- )) {
- chain_exceptions(PyExc_RuntimeError, "Failed to read running task coro");
- goto result_err;
- }
+cleanup:
+ _Py_RemoteDebug_ClearCache(&self->handle);
+ Py_XDECREF(result);
+ return NULL;
+}
- if ((void*)running_coro_addr == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "Running task coro is NULL");
- goto result_err;
- }
+static PyMethodDef RemoteUnwinder_methods[] = {
+ _REMOTE_DEBUGGING_REMOTEUNWINDER_GET_STACK_TRACE_METHODDEF
+ _REMOTE_DEBUGGING_REMOTEUNWINDER_GET_ALL_AWAITED_BY_METHODDEF
+ _REMOTE_DEBUGGING_REMOTEUNWINDER_GET_ASYNC_STACK_TRACE_METHODDEF
+ {NULL, NULL}
+};
- // note: genobject's gi_iframe is an embedded struct so the address to
- // the offset leads directly to its first field: f_executable
- uintptr_t address_of_running_task_code_obj;
- if (read_py_ptr(
- handle,
- running_coro_addr + local_debug_offsets.gen_object.gi_iframe,
- &address_of_running_task_code_obj
- )) {
- goto result_err;
+static void
+RemoteUnwinder_dealloc(RemoteUnwinderObject *self)
+{
+ PyTypeObject *tp = Py_TYPE(self);
+ if (self->code_object_cache) {
+ _Py_hashtable_destroy(self->code_object_cache);
}
-
- if ((void*)address_of_running_task_code_obj == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "Running task code object is NULL");
- goto result_err;
+#ifdef Py_GIL_DISABLED
+ if (self->tlbc_cache) {
+ _Py_hashtable_destroy(self->tlbc_cache);
}
-
- uintptr_t address_of_current_frame;
- if (find_running_frame(
- handle, runtime_start_address, &local_debug_offsets,
- &address_of_current_frame)
- ) {
- chain_exceptions(PyExc_RuntimeError, "Failed to find running frame");
- goto result_err;
+#endif
+ if (self->handle.pid != 0) {
+ _Py_RemoteDebug_ClearCache(&self->handle);
+ _Py_RemoteDebug_CleanupProcHandle(&self->handle);
}
+ PyObject_Del(self);
+ Py_DECREF(tp);
+}
- uintptr_t address_of_code_object;
- while ((void*)address_of_current_frame != NULL) {
- PyObject* frame_info = NULL;
- int res = parse_async_frame_object(
- handle,
- &frame_info,
- &local_debug_offsets,
- address_of_current_frame,
- &address_of_current_frame,
- &address_of_code_object
- );
-
- if (res < 0) {
- chain_exceptions(PyExc_RuntimeError, "Failed to parse async frame object");
- goto result_err;
- }
-
- if (!frame_info) {
- continue;
- }
+static PyType_Slot RemoteUnwinder_slots[] = {
+ {Py_tp_doc, (void *)"RemoteUnwinder(pid): Inspect stack of a remote Python process."},
+ {Py_tp_methods, RemoteUnwinder_methods},
+ {Py_tp_init, _remote_debugging_RemoteUnwinder___init__},
+ {Py_tp_dealloc, RemoteUnwinder_dealloc},
+ {0, NULL}
+};
- if (PyList_Append(calls, frame_info) == -1) {
- Py_DECREF(calls);
- goto result_err;
- }
+static PyType_Spec RemoteUnwinder_spec = {
+ .name = "_remote_debugging.RemoteUnwinder",
+ .basicsize = sizeof(RemoteUnwinderObject),
+ .flags = Py_TPFLAGS_DEFAULT,
+ .slots = RemoteUnwinder_slots,
+};
- Py_DECREF(frame_info);
- frame_info = NULL;
+/* ============================================================================
+ * MODULE INITIALIZATION
+ * ============================================================================ */
- if (address_of_code_object == address_of_running_task_code_obj) {
- break;
- }
- }
-
- PyObject *tn = parse_task_name(
- handle, &local_debug_offsets, &local_async_debug, running_task_addr);
- if (tn == NULL) {
- goto result_err;
- }
- if (PyList_Append(result, tn)) {
- Py_DECREF(tn);
- goto result_err;
+static int
+_remote_debugging_exec(PyObject *m)
+{
+ RemoteDebuggingState *st = RemoteDebugging_GetState(m);
+#define CREATE_TYPE(mod, type, spec) \
+ do { \
+ type = (PyTypeObject *)PyType_FromMetaclass(NULL, mod, spec, NULL); \
+ if (type == NULL) { \
+ return -1; \
+ } \
+ } while (0)
+
+ CREATE_TYPE(m, st->RemoteDebugging_Type, &RemoteUnwinder_spec);
+
+ if (PyModule_AddType(m, st->RemoteDebugging_Type) < 0) {
+ return -1;
}
- Py_DECREF(tn);
-
- PyObject* awaited_by = PyList_New(0);
- if (awaited_by == NULL) {
- goto result_err;
+#ifdef Py_GIL_DISABLED
+ PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
+#endif
+ int rc = PyModule_AddIntConstant(m, "PROCESS_VM_READV_SUPPORTED", HAVE_PROCESS_VM_READV);
+ if (rc < 0) {
+ return -1;
}
- if (PyList_Append(result, awaited_by)) {
- Py_DECREF(awaited_by);
- goto result_err;
+ if (RemoteDebugging_InitState(st) < 0) {
+ return -1;
}
- Py_DECREF(awaited_by);
+ return 0;
+}
- if (parse_task_awaited_by(
- handle, &local_debug_offsets, &local_async_debug,
- running_task_addr, awaited_by, 1)
- ) {
- goto result_err;
- }
+static int
+remote_debugging_traverse(PyObject *mod, visitproc visit, void *arg)
+{
+ RemoteDebuggingState *state = RemoteDebugging_GetState(mod);
+ Py_VISIT(state->RemoteDebugging_Type);
+ return 0;
+}
- _Py_RemoteDebug_CleanupProcHandle(handle);
- return result;
+static int
+remote_debugging_clear(PyObject *mod)
+{
+ RemoteDebuggingState *state = RemoteDebugging_GetState(mod);
+ Py_CLEAR(state->RemoteDebugging_Type);
+ return 0;
+}
-result_err:
- _Py_RemoteDebug_CleanupProcHandle(handle);
- Py_XDECREF(result);
- return NULL;
+static void
+remote_debugging_free(void *mod)
+{
+ (void)remote_debugging_clear((PyObject *)mod);
}
+static PyModuleDef_Slot remote_debugging_slots[] = {
+ {Py_mod_exec, _remote_debugging_exec},
+ {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
+ {Py_mod_gil, Py_MOD_GIL_NOT_USED},
+ {0, NULL},
+};
-static PyMethodDef methods[] = {
- {"get_stack_trace", get_stack_trace, METH_VARARGS,
- "Get the Python stack from a given pod"},
- {"get_async_stack_trace", get_async_stack_trace, METH_VARARGS,
- "Get the asyncio stack from a given pid"},
- {"get_all_awaited_by", get_all_awaited_by, METH_VARARGS,
- "Get all tasks and their awaited_by from a given pid"},
+static PyMethodDef remote_debugging_methods[] = {
{NULL, NULL, 0, NULL},
};
-static struct PyModuleDef module = {
- .m_base = PyModuleDef_HEAD_INIT,
+static struct PyModuleDef remote_debugging_module = {
+ PyModuleDef_HEAD_INIT,
.m_name = "_remote_debugging",
- .m_size = -1,
- .m_methods = methods,
+ .m_size = sizeof(RemoteDebuggingState),
+ .m_methods = remote_debugging_methods,
+ .m_slots = remote_debugging_slots,
+ .m_traverse = remote_debugging_traverse,
+ .m_clear = remote_debugging_clear,
+ .m_free = remote_debugging_free,
};
PyMODINIT_FUNC
PyInit__remote_debugging(void)
{
- PyObject* mod = PyModule_Create(&module);
- if (mod == NULL) {
- return NULL;
- }
-#ifdef Py_GIL_DISABLED
- PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED);
-#endif
- int rc = PyModule_AddIntConstant(
- mod, "PROCESS_VM_READV_SUPPORTED", HAVE_PROCESS_VM_READV);
- if (rc < 0) {
- Py_DECREF(mod);
- return NULL;
- }
- return mod;
+ return PyModuleDef_Init(&remote_debugging_module);
}
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 976da1340ec..014e624f6c2 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -563,7 +563,7 @@ fill_and_set_sslerror(_sslmodulestate *state,
goto fail;
}
}
- if (PyUnicodeWriter_WriteUTF8(writer, "] ", 2) < 0) {
+ if (PyUnicodeWriter_WriteASCII(writer, "] ", 2) < 0) {
goto fail;
}
}
diff --git a/Modules/_testcapi/unicode.c b/Modules/_testcapi/unicode.c
index b8ecf53f4f8..e70f5c68bc3 100644
--- a/Modules/_testcapi/unicode.c
+++ b/Modules/_testcapi/unicode.c
@@ -333,6 +333,27 @@ writer_write_utf8(PyObject *self_raw, PyObject *args)
static PyObject*
+writer_write_ascii(PyObject *self_raw, PyObject *args)
+{
+ WriterObject *self = (WriterObject *)self_raw;
+ if (writer_check(self) < 0) {
+ return NULL;
+ }
+
+ char *str;
+ Py_ssize_t size;
+ if (!PyArg_ParseTuple(args, "yn", &str, &size)) {
+ return NULL;
+ }
+
+ if (PyUnicodeWriter_WriteASCII(self->writer, str, size) < 0) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+
+static PyObject*
writer_write_widechar(PyObject *self_raw, PyObject *args)
{
WriterObject *self = (WriterObject *)self_raw;
@@ -513,6 +534,7 @@ writer_finish(PyObject *self_raw, PyObject *Py_UNUSED(args))
static PyMethodDef writer_methods[] = {
{"write_char", _PyCFunction_CAST(writer_write_char), METH_VARARGS},
{"write_utf8", _PyCFunction_CAST(writer_write_utf8), METH_VARARGS},
+ {"write_ascii", _PyCFunction_CAST(writer_write_ascii), METH_VARARGS},
{"write_widechar", _PyCFunction_CAST(writer_write_widechar), METH_VARARGS},
{"write_ucs4", _PyCFunction_CAST(writer_write_ucs4), METH_VARARGS},
{"write_str", _PyCFunction_CAST(writer_write_str), METH_VARARGS},
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 3aa6e4c9e43..281c5b41137 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3175,6 +3175,48 @@ create_manual_heap_type(void)
return (PyObject *)type;
}
+typedef struct {
+ PyObject_VAR_HEAD
+} ManagedDictObject;
+
+int ManagedDict_traverse(PyObject *self, visitproc visit, void *arg) {
+ PyObject_VisitManagedDict(self, visit, arg);
+ Py_VISIT(Py_TYPE(self));
+ return 0;
+}
+
+int ManagedDict_clear(PyObject *self) {
+ PyObject_ClearManagedDict(self);
+ return 0;
+}
+
+static PyGetSetDef ManagedDict_getset[] = {
+ {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL},
+ {NULL, NULL, NULL, NULL, NULL},
+};
+
+static PyType_Slot ManagedDict_slots[] = {
+ {Py_tp_new, (void *)PyType_GenericNew},
+ {Py_tp_getset, (void *)ManagedDict_getset},
+ {Py_tp_traverse, (void *)ManagedDict_traverse},
+ {Py_tp_clear, (void *)ManagedDict_clear},
+ {0}
+};
+
+static PyType_Spec ManagedDict_spec = {
+ "_testcapi.ManagedDictType",
+ sizeof(ManagedDictObject),
+ 0, // itemsize
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_MANAGED_DICT | Py_TPFLAGS_HEAPTYPE | Py_TPFLAGS_HAVE_GC,
+ ManagedDict_slots
+};
+
+static PyObject *
+create_managed_dict_type(void)
+{
+ return PyType_FromSpec(&ManagedDict_spec);
+}
+
static struct PyModuleDef _testcapimodule = {
PyModuleDef_HEAD_INIT,
.m_name = "_testcapi",
@@ -3315,6 +3357,13 @@ PyInit__testcapi(void)
return NULL;
}
+ PyObject *managed_dict_type = create_managed_dict_type();
+ if (managed_dict_type == NULL) {
+ return NULL;
+ }
+ if (PyModule_Add(m, "ManagedDictType", managed_dict_type) < 0) {
+ return NULL;
+ }
/* Include tests from the _testcapi/ directory */
if (_PyTestCapi_Init_Vectorcall(m) < 0) {
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 3030f45d72c..845c218e679 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -1045,6 +1045,9 @@ get_code_var_counts(PyObject *self, PyObject *_args, PyObject *_kwargs)
#define SET_COUNT(DICT, STRUCT, NAME) \
do { \
PyObject *count = PyLong_FromLong(STRUCT.NAME); \
+ if (count == NULL) { \
+ goto error; \
+ } \
int res = PyDict_SetItemString(DICT, #NAME, count); \
Py_DECREF(count); \
if (res < 0) { \
@@ -1690,11 +1693,12 @@ create_interpreter(PyObject *self, PyObject *args, PyObject *kwargs)
static PyObject *
destroy_interpreter(PyObject *self, PyObject *args, PyObject *kwargs)
{
- static char *kwlist[] = {"id", NULL};
+ static char *kwlist[] = {"id", "basic", NULL};
PyObject *idobj = NULL;
+ int basic = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O:destroy_interpreter", kwlist,
- &idobj))
+ "O|p:destroy_interpreter", kwlist,
+ &idobj, &basic))
{
return NULL;
}
@@ -1704,7 +1708,27 @@ destroy_interpreter(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
}
- _PyXI_EndInterpreter(interp, NULL, NULL);
+ if (basic)
+ {
+ // Test the basic Py_EndInterpreter with weird out of order thread states
+ PyThreadState *t1, *t2;
+ PyThreadState *prev;
+ t1 = interp->threads.head;
+ if (t1 == NULL) {
+ t1 = PyThreadState_New(interp);
+ }
+ t2 = PyThreadState_New(interp);
+ prev = PyThreadState_Swap(t2);
+ PyThreadState_Clear(t1);
+ PyThreadState_Delete(t1);
+ Py_EndInterpreter(t2);
+ PyThreadState_Swap(prev);
+ }
+ else
+ {
+ // use the cross interpreter _PyXI_EndInterpreter normally
+ _PyXI_EndInterpreter(interp, NULL, NULL);
+ }
Py_RETURN_NONE;
}
@@ -1970,7 +1994,14 @@ get_crossinterp_data(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
}
if (strcmp(mode, "xidata") == 0) {
- if (_PyObject_GetXIData(tstate, obj, xidata) != 0) {
+ if (_PyObject_GetXIDataNoFallback(tstate, obj, xidata) != 0) {
+ goto error;
+ }
+ }
+ else if (strcmp(mode, "fallback") == 0) {
+ xidata_fallback_t fallback = _PyXIDATA_FULL_FALLBACK;
+ if (_PyObject_GetXIData(tstate, obj, fallback, xidata) != 0)
+ {
goto error;
}
}
@@ -1989,6 +2020,11 @@ get_crossinterp_data(PyObject *self, PyObject *args, PyObject *kwargs)
goto error;
}
}
+ else if (strcmp(mode, "func") == 0) {
+ if (_PyFunction_GetXIData(tstate, obj, xidata) != 0) {
+ goto error;
+ }
+ }
else if (strcmp(mode, "script") == 0) {
if (_PyCode_GetScriptXIData(tstate, obj, xidata) != 0) {
goto error;
diff --git a/Modules/_testlimitedcapi/sys.c b/Modules/_testlimitedcapi/sys.c
index 7d8b7a8569e..cec7f8ab612 100644
--- a/Modules/_testlimitedcapi/sys.c
+++ b/Modules/_testlimitedcapi/sys.c
@@ -1,8 +1,77 @@
+#include "pyconfig.h" // Py_GIL_DISABLED
+// Need limited C API version 3.15 for PySys_GetAttr() etc
+#if !defined(Py_GIL_DISABLED) && !defined(Py_LIMITED_API)
+# define Py_LIMITED_API 0x030f0000
+#endif
#include "parts.h"
#include "util.h"
static PyObject *
+sys_getattr(PyObject *Py_UNUSED(module), PyObject *name)
+{
+ NULLABLE(name);
+ return PySys_GetAttr(name);
+}
+
+static PyObject *
+sys_getattrstring(PyObject *Py_UNUSED(module), PyObject *arg)
+{
+ const char *name;
+ Py_ssize_t size;
+ if (!PyArg_Parse(arg, "z#", &name, &size)) {
+ return NULL;
+ }
+ return PySys_GetAttrString(name);
+}
+
+static PyObject *
+sys_getoptionalattr(PyObject *Py_UNUSED(module), PyObject *name)
+{
+ PyObject *value = UNINITIALIZED_PTR;
+ NULLABLE(name);
+
+ switch (PySys_GetOptionalAttr(name, &value)) {
+ case -1:
+ assert(value == NULL);
+ assert(PyErr_Occurred());
+ return NULL;
+ case 0:
+ assert(value == NULL);
+ return Py_NewRef(PyExc_AttributeError);
+ case 1:
+ return value;
+ default:
+ Py_FatalError("PySys_GetOptionalAttr() returned invalid code");
+ }
+}
+
+static PyObject *
+sys_getoptionalattrstring(PyObject *Py_UNUSED(module), PyObject *arg)
+{
+ PyObject *value = UNINITIALIZED_PTR;
+ const char *name;
+ Py_ssize_t size;
+ if (!PyArg_Parse(arg, "z#", &name, &size)) {
+ return NULL;
+ }
+
+ switch (PySys_GetOptionalAttrString(name, &value)) {
+ case -1:
+ assert(value == NULL);
+ assert(PyErr_Occurred());
+ return NULL;
+ case 0:
+ assert(value == NULL);
+ return Py_NewRef(PyExc_AttributeError);
+ case 1:
+ return value;
+ default:
+ Py_FatalError("PySys_GetOptionalAttrString() returned invalid code");
+ }
+}
+
+static PyObject *
sys_getobject(PyObject *Py_UNUSED(module), PyObject *arg)
{
const char *name;
@@ -39,6 +108,10 @@ sys_getxoptions(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(ignored))
static PyMethodDef test_methods[] = {
+ {"sys_getattr", sys_getattr, METH_O},
+ {"sys_getattrstring", sys_getattrstring, METH_O},
+ {"sys_getoptionalattr", sys_getoptionalattr, METH_O},
+ {"sys_getoptionalattrstring", sys_getoptionalattrstring, METH_O},
{"sys_getobject", sys_getobject, METH_O},
{"sys_setobject", sys_setobject, METH_VARARGS},
{"sys_getxoptions", sys_getxoptions, METH_NOARGS},
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 9776a32755d..150a266b521 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -10,7 +10,6 @@
#include "pycore_object_deferred.h" // _PyObject_SetDeferredRefcount()
#include "pycore_pylifecycle.h"
#include "pycore_pystate.h" // _PyThreadState_SetCurrent()
-#include "pycore_sysmodule.h" // _PySys_GetOptionalAttr()
#include "pycore_time.h" // _PyTime_FromSeconds()
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
@@ -19,8 +18,6 @@
# include <signal.h> // SIGINT
#endif
-#include "clinic/_threadmodule.c.h"
-
// ThreadError is just an alias to PyExc_RuntimeError
#define ThreadError PyExc_RuntimeError
@@ -31,6 +28,7 @@ static struct PyModuleDef thread_module;
typedef struct {
PyTypeObject *excepthook_type;
PyTypeObject *lock_type;
+ PyTypeObject *rlock_type;
PyTypeObject *local_type;
PyTypeObject *local_dummy_type;
PyTypeObject *thread_handle_type;
@@ -48,6 +46,17 @@ get_thread_state(PyObject *module)
return (thread_module_state *)state;
}
+static inline thread_module_state*
+get_thread_state_by_cls(PyTypeObject *cls)
+{
+ // Use PyType_GetModuleByDef() to handle (R)Lock subclasses.
+ PyObject *module = PyType_GetModuleByDef(cls, &thread_module);
+ if (module == NULL) {
+ return NULL;
+ }
+ return get_thread_state(module);
+}
+
#ifdef MS_WINDOWS
typedef HRESULT (WINAPI *PF_GET_THREAD_DESCRIPTION)(HANDLE, PCWSTR*);
@@ -59,9 +68,14 @@ static PF_SET_THREAD_DESCRIPTION pSetThreadDescription = NULL;
/*[clinic input]
module _thread
+class _thread.lock "lockobject *" "clinic_state()->lock_type"
+class _thread.RLock "rlockobject *" "clinic_state()->rlock_type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=be8dbe5cc4b16df7]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c5a0f8c492a0c263]*/
+#define clinic_state() get_thread_state_by_cls(type)
+#include "clinic/_threadmodule.c.h"
+#undef clinic_state
// _ThreadHandle type
@@ -281,6 +295,12 @@ _PyThread_AfterFork(struct _pythread_runtime_state *state)
continue;
}
+ // Keep handles for threads that have not been started yet. They are
+ // safe to start in the child process.
+ if (handle->state == THREAD_HANDLE_NOT_STARTED) {
+ continue;
+ }
+
// Mark all threads as done. Any attempts to join or detach the
// underlying OS thread (if any) could crash. We are the only thread;
// it's safe to set this non-atomically.
@@ -916,25 +936,21 @@ lock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(dummy))
}
#endif /* HAVE_FORK */
-static lockobject *newlockobject(PyObject *module);
+/*[clinic input]
+@classmethod
+_thread.lock.__new__ as lock_new
+[clinic start generated code]*/
static PyObject *
-lock_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+lock_new_impl(PyTypeObject *type)
+/*[clinic end generated code: output=eab660d5a4c05c8a input=260208a4e277d250]*/
{
- // convert to AC?
- if (!_PyArg_NoKeywords("lock", kwargs)) {
- goto error;
- }
- if (!_PyArg_CheckPositional("lock", PyTuple_GET_SIZE(args), 0, 0)) {
- goto error;
+ lockobject *self = (lockobject *)type->tp_alloc(type, 0);
+ if (self == NULL) {
+ return NULL;
}
-
- PyObject *module = PyType_GetModuleByDef(type, &thread_module);
- assert(module != NULL);
- return (PyObject *)newlockobject(module);
-
-error:
- return NULL;
+ self->lock = (PyMutex){0};
+ return (PyObject *)self;
}
@@ -1011,6 +1027,11 @@ rlock_traverse(PyObject *self, visitproc visit, void *arg)
return 0;
}
+static int
+rlock_locked_impl(rlockobject *self)
+{
+ return PyMutex_IsLocked(&self->lock.mutex);
+}
static void
rlock_dealloc(PyObject *self)
@@ -1100,7 +1121,7 @@ static PyObject *
rlock_locked(PyObject *op, PyObject *Py_UNUSED(ignored))
{
rlockobject *self = rlockobject_CAST(op);
- int is_locked = _PyRecursiveMutex_IsLockedByCurrentThread(&self->lock);
+ int is_locked = rlock_locked_impl(self);
return PyBool_FromLong(is_locked);
}
@@ -1186,8 +1207,14 @@ PyDoc_STRVAR(rlock_is_owned_doc,
\n\
For internal use by `threading.Condition`.");
+/*[clinic input]
+@classmethod
+_thread.RLock.__new__ as rlock_new
+[clinic start generated code]*/
+
static PyObject *
-rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+rlock_new_impl(PyTypeObject *type)
+/*[clinic end generated code: output=bb4fb1edf6818df5 input=013591361bf1ac6e]*/
{
rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
if (self == NULL) {
@@ -1202,10 +1229,17 @@ rlock_repr(PyObject *op)
{
rlockobject *self = rlockobject_CAST(op);
PyThread_ident_t owner = self->lock.thread;
- size_t count = self->lock.level + 1;
+ int locked = rlock_locked_impl(self);
+ size_t count;
+ if (locked) {
+ count = self->lock.level + 1;
+ }
+ else {
+ count = 0;
+ }
return PyUnicode_FromFormat(
"<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%zu at %p>",
- owner ? "locked" : "unlocked",
+ locked ? "locked" : "unlocked",
Py_TYPE(self)->tp_name, owner,
count, self);
}
@@ -1267,20 +1301,6 @@ static PyType_Spec rlock_type_spec = {
.slots = rlock_type_slots,
};
-static lockobject *
-newlockobject(PyObject *module)
-{
- thread_module_state *state = get_thread_state(module);
-
- PyTypeObject *type = state->lock_type;
- lockobject *self = (lockobject *)type->tp_alloc(type, 0);
- if (self == NULL) {
- return NULL;
- }
- self->lock = (PyMutex){0};
- return self;
-}
-
/* Thread-local objects */
/* Quick overview:
@@ -2035,7 +2055,8 @@ Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``."
static PyObject *
thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
{
- return (PyObject *) newlockobject(module);
+ thread_module_state *state = get_thread_state(module);
+ return lock_new_impl(state->lock_type);
}
PyDoc_STRVAR(allocate_lock_doc,
@@ -2268,7 +2289,7 @@ thread_excepthook(PyObject *module, PyObject *args)
PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
PyObject *file;
- if (_PySys_GetOptionalAttr( &_Py_ID(stderr), &file) < 0) {
+ if (PySys_GetOptionalAttr( &_Py_ID(stderr), &file) < 0) {
return NULL;
}
if (file == NULL || file == Py_None) {
@@ -2645,15 +2666,13 @@ thread_module_exec(PyObject *module)
}
// RLock
- PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
- if (rlock_type == NULL) {
+ state->rlock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &rlock_type_spec, NULL);
+ if (state->rlock_type == NULL) {
return -1;
}
- if (PyModule_AddType(module, rlock_type) < 0) {
- Py_DECREF(rlock_type);
+ if (PyModule_AddType(module, state->rlock_type) < 0) {
return -1;
}
- Py_DECREF(rlock_type);
// Local dummy
state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
@@ -2740,6 +2759,7 @@ thread_module_traverse(PyObject *module, visitproc visit, void *arg)
thread_module_state *state = get_thread_state(module);
Py_VISIT(state->excepthook_type);
Py_VISIT(state->lock_type);
+ Py_VISIT(state->rlock_type);
Py_VISIT(state->local_type);
Py_VISIT(state->local_dummy_type);
Py_VISIT(state->thread_handle_type);
@@ -2752,6 +2772,7 @@ thread_module_clear(PyObject *module)
thread_module_state *state = get_thread_state(module);
Py_CLEAR(state->excepthook_type);
Py_CLEAR(state->lock_type);
+ Py_CLEAR(state->rlock_type);
Py_CLEAR(state->local_type);
Py_CLEAR(state->local_dummy_type);
Py_CLEAR(state->thread_handle_type);
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 77695401919..875840bd6a6 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -31,7 +31,6 @@ Copyright (C) 1994 Steen Lumholt.
#endif
#include "pycore_long.h" // _PyLong_IsNegative()
-#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
#include "pycore_unicodeobject.h" // _PyUnicode_AsUTF8String
#ifdef MS_WINDOWS
@@ -146,7 +145,7 @@ _get_tcl_lib_path(void)
int stat_return_value;
PyObject *prefix;
- (void) _PySys_GetOptionalAttrString("base_prefix", &prefix);
+ (void) PySys_GetOptionalAttrString("base_prefix", &prefix);
if (prefix == NULL) {
return NULL;
}
@@ -3547,7 +3546,7 @@ PyInit__tkinter(void)
/* This helps the dynamic loader; in Unicode aware Tcl versions
it also helps Tcl find its encodings. */
- (void) _PySys_GetOptionalAttrString("executable", &uexe);
+ (void) PySys_GetOptionalAttrString("executable", &uexe);
if (uexe && PyUnicode_Check(uexe)) { // sys.executable can be None
cexe = PyUnicode_EncodeFSDefault(uexe);
Py_DECREF(uexe);
diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c
index c5e78b1510b..c31a7e8fea5 100644
--- a/Modules/_uuidmodule.c
+++ b/Modules/_uuidmodule.c
@@ -78,23 +78,47 @@ py_UuidCreate(PyObject *Py_UNUSED(context),
return NULL;
}
+static int
+py_windows_has_stable_node(void)
+{
+ UUID uuid;
+ RPC_STATUS res;
+ Py_BEGIN_ALLOW_THREADS
+ res = UuidCreateSequential(&uuid);
+ Py_END_ALLOW_THREADS
+ return res == RPC_S_OK;
+}
#endif /* MS_WINDOWS */
static int
-uuid_exec(PyObject *module) {
+uuid_exec(PyObject *module)
+{
+#define ADD_INT(NAME, VALUE) \
+ do { \
+ if (PyModule_AddIntConstant(module, (NAME), (VALUE)) < 0) { \
+ return -1; \
+ } \
+ } while (0)
+
assert(sizeof(uuid_t) == 16);
#if defined(MS_WINDOWS)
- int has_uuid_generate_time_safe = 0;
+ ADD_INT("has_uuid_generate_time_safe", 0);
#elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
- int has_uuid_generate_time_safe = 1;
+ ADD_INT("has_uuid_generate_time_safe", 1);
#else
- int has_uuid_generate_time_safe = 0;
+ ADD_INT("has_uuid_generate_time_safe", 0);
#endif
- if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
- has_uuid_generate_time_safe) < 0) {
- return -1;
- }
+
+#if defined(MS_WINDOWS)
+ ADD_INT("has_stable_extractable_node", py_windows_has_stable_node());
+#elif defined(HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC)
+ ADD_INT("has_stable_extractable_node", 1);
+#else
+ ADD_INT("has_stable_extractable_node", 0);
+#endif
+
+#undef ADD_INT
return 0;
}
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index 02817e09b93..b4cfbebcb1b 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -1573,6 +1573,7 @@ static PyObject *
_winapi_GetLongPathName_impl(PyObject *module, LPCWSTR path)
/*[clinic end generated code: output=c4774b080275a2d0 input=9872e211e3a4a88f]*/
{
+#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
DWORD cchBuffer;
PyObject *result = NULL;
@@ -1596,6 +1597,9 @@ _winapi_GetLongPathName_impl(PyObject *module, LPCWSTR path)
PyErr_SetFromWindowsErr(0);
}
return result;
+#else
+ return PyUnicode_FromWideChar(path, -1);
+#endif
}
/*[clinic input]
@@ -1629,9 +1633,11 @@ _winapi_GetModuleFileName_impl(PyObject *module, HMODULE module_handle)
if (! result)
return PyErr_SetFromWindowsErr(GetLastError());
- return PyUnicode_FromWideChar(filename, wcslen(filename));
+ return PyUnicode_FromWideChar(filename, -1);
}
+#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
+
/*[clinic input]
_winapi.GetShortPathName
@@ -1674,6 +1680,8 @@ _winapi_GetShortPathName_impl(PyObject *module, LPCWSTR path)
return result;
}
+#endif /* MS_WINDOWS_DESKTOP || MS_WINDOWS_SYSTEM */
+
/*[clinic input]
_winapi.GetStdHandle -> HANDLE
@@ -2740,6 +2748,19 @@ _winapi_GetACP_impl(PyObject *module)
}
/*[clinic input]
+_winapi.GetOEMCP
+
+Get the current Windows ANSI code page identifier.
+[clinic start generated code]*/
+
+static PyObject *
+_winapi_GetOEMCP_impl(PyObject *module)
+/*[clinic end generated code: output=4def5b07a8be1b3b input=e8caf4353a28e28e]*/
+{
+ return PyLong_FromUnsignedLong(GetOEMCP());
+}
+
+/*[clinic input]
_winapi.GetFileType -> DWORD
handle: HANDLE
@@ -2883,6 +2904,7 @@ _winapi_NeedCurrentDirectoryForExePath_impl(PyObject *module,
LPCWSTR exe_name)
/*[clinic end generated code: output=a65ec879502b58fc input=972aac88a1ec2f00]*/
{
+#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
BOOL result;
Py_BEGIN_ALLOW_THREADS
@@ -2890,6 +2912,9 @@ _winapi_NeedCurrentDirectoryForExePath_impl(PyObject *module,
Py_END_ALLOW_THREADS
return result;
+#else
+ return TRUE;
+#endif
}
@@ -2995,6 +3020,7 @@ static PyMethodDef winapi_functions[] = {
_WINAPI_WAITFORSINGLEOBJECT_METHODDEF
_WINAPI_WRITEFILE_METHODDEF
_WINAPI_GETACP_METHODDEF
+ _WINAPI_GETOEMCP_METHODDEF
_WINAPI_GETFILETYPE_METHODDEF
_WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF
_WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF
diff --git a/Modules/_zstd/_zstdmodule.c b/Modules/_zstd/_zstdmodule.c
index 4004bbb3461..986b3579479 100644
--- a/Modules/_zstd/_zstdmodule.c
+++ b/Modules/_zstd/_zstdmodule.c
@@ -1,13 +1,16 @@
-/*
-Low level interface to Meta's zstd library for use in the compression.zstd
-Python module.
-*/
+/* Low level interface to the Zstandard algorthm & the zstd library. */
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
+#include "Python.h"
+
#include "_zstdmodule.h"
+#include "zstddict.h"
+
+#include <zstd.h> // ZSTD_*()
+#include <zdict.h> // ZDICT_*()
/*[clinic input]
module _zstd
@@ -25,41 +28,42 @@ set_zstd_error(const _zstd_state* const state,
char *msg;
assert(ZSTD_isError(zstd_ret));
- switch (type)
- {
- case ERR_DECOMPRESS:
- msg = "Unable to decompress zstd data: %s";
- break;
- case ERR_COMPRESS:
- msg = "Unable to compress zstd data: %s";
- break;
-
- case ERR_LOAD_D_DICT:
- msg = "Unable to load zstd dictionary or prefix for decompression: %s";
- break;
- case ERR_LOAD_C_DICT:
- msg = "Unable to load zstd dictionary or prefix for compression: %s";
- break;
-
- case ERR_GET_C_BOUNDS:
- msg = "Unable to get zstd compression parameter bounds: %s";
- break;
- case ERR_GET_D_BOUNDS:
- msg = "Unable to get zstd decompression parameter bounds: %s";
- break;
- case ERR_SET_C_LEVEL:
- msg = "Unable to set zstd compression level: %s";
- break;
-
- case ERR_TRAIN_DICT:
- msg = "Unable to train zstd dictionary: %s";
- break;
- case ERR_FINALIZE_DICT:
- msg = "Unable to finalize zstd dictionary: %s";
- break;
-
- default:
- Py_UNREACHABLE();
+ switch (type) {
+ case ERR_DECOMPRESS:
+ msg = "Unable to decompress Zstandard data: %s";
+ break;
+ case ERR_COMPRESS:
+ msg = "Unable to compress Zstandard data: %s";
+ break;
+
+ case ERR_LOAD_D_DICT:
+ msg = "Unable to load Zstandard dictionary or prefix for "
+ "decompression: %s";
+ break;
+ case ERR_LOAD_C_DICT:
+ msg = "Unable to load Zstandard dictionary or prefix for "
+ "compression: %s";
+ break;
+
+ case ERR_GET_C_BOUNDS:
+ msg = "Unable to get zstd compression parameter bounds: %s";
+ break;
+ case ERR_GET_D_BOUNDS:
+ msg = "Unable to get zstd decompression parameter bounds: %s";
+ break;
+ case ERR_SET_C_LEVEL:
+ msg = "Unable to set zstd compression level: %s";
+ break;
+
+ case ERR_TRAIN_DICT:
+ msg = "Unable to train the Zstandard dictionary: %s";
+ break;
+ case ERR_FINALIZE_DICT:
+ msg = "Unable to finalize the Zstandard dictionary: %s";
+ break;
+
+ default:
+ Py_UNREACHABLE();
}
PyErr_Format(state->ZstdError, msg, ZSTD_getErrorName(zstd_ret));
}
@@ -69,8 +73,7 @@ typedef struct {
char parameter_name[32];
} ParameterInfo;
-static const ParameterInfo cp_list[] =
-{
+static const ParameterInfo cp_list[] = {
{ZSTD_c_compressionLevel, "compression_level"},
{ZSTD_c_windowLog, "window_log"},
{ZSTD_c_hashLog, "hash_log"},
@@ -95,22 +98,18 @@ static const ParameterInfo cp_list[] =
{ZSTD_c_overlapLog, "overlap_log"}
};
-static const ParameterInfo dp_list[] =
-{
+static const ParameterInfo dp_list[] = {
{ZSTD_d_windowLogMax, "window_log_max"}
};
void
-set_parameter_error(const _zstd_state* const state, int is_compress,
- int key_v, int value_v)
+set_parameter_error(int is_compress, int key_v, int value_v)
{
ParameterInfo const *list;
int list_size;
- char const *name;
char *type;
ZSTD_bounds bounds;
- int i;
- char pos_msg[128];
+ char pos_msg[64];
if (is_compress) {
list = cp_list;
@@ -124,8 +123,8 @@ set_parameter_error(const _zstd_state* const state, int is_compress,
}
/* Find parameter's name */
- name = NULL;
- for (i = 0; i < list_size; i++) {
+ char const *name = NULL;
+ for (int i = 0; i < list_size; i++) {
if (key_v == (list+i)->parameter) {
name = (list+i)->parameter_name;
break;
@@ -147,20 +146,16 @@ set_parameter_error(const _zstd_state* const state, int is_compress,
bounds = ZSTD_dParam_getBounds(key_v);
}
if (ZSTD_isError(bounds.error)) {
- PyErr_Format(state->ZstdError,
- "Zstd %s parameter \"%s\" is invalid.",
+ PyErr_Format(PyExc_ValueError, "invalid %s parameter '%s'",
type, name);
return;
}
/* Error message */
- PyErr_Format(state->ZstdError,
- "Error when setting zstd %s parameter \"%s\", it "
- "should %d <= value <= %d, provided value is %d. "
- "(%d-bit build)",
- type, name,
- bounds.lowerBound, bounds.upperBound, value_v,
- 8*(int)sizeof(Py_ssize_t));
+ PyErr_Format(PyExc_ValueError,
+ "%s parameter '%s' received an illegal value %d; "
+ "the valid range is [%d, %d]",
+ type, name, value_v, bounds.lowerBound, bounds.upperBound);
}
static inline _zstd_state*
@@ -171,71 +166,86 @@ get_zstd_state(PyObject *module)
return (_zstd_state *)state;
}
-
-/*[clinic input]
-_zstd._train_dict
-
- samples_bytes: PyBytesObject
- Concatenation of samples.
- samples_sizes: object(subclass_of='&PyTuple_Type')
- Tuple of samples' sizes.
- dict_size: Py_ssize_t
- The size of the dictionary.
- /
-
-Internal function, train a zstd dictionary on sample data.
-[clinic start generated code]*/
-
-static PyObject *
-_zstd__train_dict_impl(PyObject *module, PyBytesObject *samples_bytes,
- PyObject *samples_sizes, Py_ssize_t dict_size)
-/*[clinic end generated code: output=b5b4f36347c0addd input=2dce5b57d63923e2]*/
+static Py_ssize_t
+calculate_samples_stats(PyBytesObject *samples_bytes, PyObject *samples_sizes,
+ size_t **chunk_sizes)
{
- // TODO(emmatyping): The preamble and suffix to this function and _finalize_dict
- // are pretty similar. We should see if we can refactor them to share that code.
Py_ssize_t chunks_number;
- size_t *chunk_sizes = NULL;
- PyObject *dst_dict_bytes = NULL;
- size_t zstd_ret;
Py_ssize_t sizes_sum;
Py_ssize_t i;
- /* Check arguments */
- if (dict_size <= 0) {
- PyErr_SetString(PyExc_ValueError, "dict_size argument should be positive number.");
- return NULL;
- }
-
chunks_number = Py_SIZE(samples_sizes);
if ((size_t) chunks_number > UINT32_MAX) {
PyErr_Format(PyExc_ValueError,
- "The number of samples should be <= %u.", UINT32_MAX);
- return NULL;
+ "The number of samples should be <= %u.", UINT32_MAX);
+ return -1;
}
/* Prepare chunk_sizes */
- chunk_sizes = PyMem_New(size_t, chunks_number);
- if (chunk_sizes == NULL) {
+ *chunk_sizes = PyMem_New(size_t, chunks_number);
+ if (*chunk_sizes == NULL) {
PyErr_NoMemory();
- goto error;
+ return -1;
}
sizes_sum = 0;
for (i = 0; i < chunks_number; i++) {
PyObject *size = PyTuple_GetItem(samples_sizes, i);
- chunk_sizes[i] = PyLong_AsSize_t(size);
- if (chunk_sizes[i] == (size_t)-1 && PyErr_Occurred()) {
+ (*chunk_sizes)[i] = PyLong_AsSize_t(size);
+ if ((*chunk_sizes)[i] == (size_t)-1 && PyErr_Occurred()) {
PyErr_Format(PyExc_ValueError,
- "Items in samples_sizes should be an int "
- "object, with a value between 0 and %u.", SIZE_MAX);
- goto error;
+ "Items in samples_sizes should be an int "
+ "object, with a value between 0 and %u.", SIZE_MAX);
+ return -1;
}
- sizes_sum += chunk_sizes[i];
+ sizes_sum += (*chunk_sizes)[i];
}
if (sizes_sum != Py_SIZE(samples_bytes)) {
PyErr_SetString(PyExc_ValueError,
- "The samples size tuple doesn't match the concatenation's size.");
+ "The samples size tuple doesn't match the "
+ "concatenation's size.");
+ return -1;
+ }
+ return chunks_number;
+}
+
+
+/*[clinic input]
+_zstd.train_dict
+
+ samples_bytes: PyBytesObject
+ Concatenation of samples.
+ samples_sizes: object(subclass_of='&PyTuple_Type')
+ Tuple of samples' sizes.
+ dict_size: Py_ssize_t
+ The size of the dictionary.
+ /
+
+Train a Zstandard dictionary on sample data.
+[clinic start generated code]*/
+
+static PyObject *
+_zstd_train_dict_impl(PyObject *module, PyBytesObject *samples_bytes,
+ PyObject *samples_sizes, Py_ssize_t dict_size)
+/*[clinic end generated code: output=8e87fe43935e8f77 input=d20dedb21c72cb62]*/
+{
+ PyObject *dst_dict_bytes = NULL;
+ size_t *chunk_sizes = NULL;
+ Py_ssize_t chunks_number;
+ size_t zstd_ret;
+
+ /* Check arguments */
+ if (dict_size <= 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "dict_size argument should be positive number.");
+ return NULL;
+ }
+
+ /* Check that the samples are valid and get their sizes */
+ chunks_number = calculate_samples_stats(samples_bytes, samples_sizes,
+ &chunk_sizes);
+ if (chunks_number < 0) {
goto error;
}
@@ -254,9 +264,9 @@ _zstd__train_dict_impl(PyObject *module, PyBytesObject *samples_bytes,
chunk_sizes, (uint32_t)chunks_number);
Py_END_ALLOW_THREADS
- /* Check zstd dict error */
+ /* Check Zstandard dict error */
if (ZDICT_isError(zstd_ret)) {
- _zstd_state* const mod_state = get_zstd_state(module);
+ _zstd_state* mod_state = get_zstd_state(module);
set_zstd_error(mod_state, ERR_TRAIN_DICT, zstd_ret);
goto error;
}
@@ -277,7 +287,7 @@ success:
}
/*[clinic input]
-_zstd._finalize_dict
+_zstd.finalize_dict
custom_dict_bytes: PyBytesObject
Custom dictionary content.
@@ -288,63 +298,36 @@ _zstd._finalize_dict
dict_size: Py_ssize_t
The size of the dictionary.
compression_level: int
- Optimize for a specific zstd compression level, 0 means default.
+ Optimize for a specific Zstandard compression level, 0 means default.
/
-Internal function, finalize a zstd dictionary.
+Finalize a Zstandard dictionary.
[clinic start generated code]*/
static PyObject *
-_zstd__finalize_dict_impl(PyObject *module, PyBytesObject *custom_dict_bytes,
- PyBytesObject *samples_bytes,
- PyObject *samples_sizes, Py_ssize_t dict_size,
- int compression_level)
-/*[clinic end generated code: output=5dc5b520fddba37f input=8afd42a249078460]*/
+_zstd_finalize_dict_impl(PyObject *module, PyBytesObject *custom_dict_bytes,
+ PyBytesObject *samples_bytes,
+ PyObject *samples_sizes, Py_ssize_t dict_size,
+ int compression_level)
+/*[clinic end generated code: output=f91821ba5ae85bda input=3c7e2480aa08fb56]*/
{
Py_ssize_t chunks_number;
size_t *chunk_sizes = NULL;
PyObject *dst_dict_bytes = NULL;
size_t zstd_ret;
ZDICT_params_t params;
- Py_ssize_t sizes_sum;
- Py_ssize_t i;
/* Check arguments */
if (dict_size <= 0) {
- PyErr_SetString(PyExc_ValueError, "dict_size argument should be positive number.");
- return NULL;
- }
-
- chunks_number = Py_SIZE(samples_sizes);
- if ((size_t) chunks_number > UINT32_MAX) {
- PyErr_Format(PyExc_ValueError,
- "The number of samples should be <= %u.", UINT32_MAX);
+ PyErr_SetString(PyExc_ValueError,
+ "dict_size argument should be positive number.");
return NULL;
}
- /* Prepare chunk_sizes */
- chunk_sizes = PyMem_New(size_t, chunks_number);
- if (chunk_sizes == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- sizes_sum = 0;
- for (i = 0; i < chunks_number; i++) {
- PyObject *size = PyTuple_GetItem(samples_sizes, i);
- chunk_sizes[i] = PyLong_AsSize_t(size);
- if (chunk_sizes[i] == (size_t)-1 && PyErr_Occurred()) {
- PyErr_Format(PyExc_ValueError,
- "Items in samples_sizes should be an int "
- "object, with a value between 0 and %u.", SIZE_MAX);
- goto error;
- }
- sizes_sum += chunk_sizes[i];
- }
-
- if (sizes_sum != Py_SIZE(samples_bytes)) {
- PyErr_SetString(PyExc_ValueError,
- "The samples size tuple doesn't match the concatenation's size.");
+ /* Check that the samples are valid and get their sizes */
+ chunks_number = calculate_samples_stats(samples_bytes, samples_sizes,
+ &chunk_sizes);
+ if (chunks_number < 0) {
goto error;
}
@@ -356,7 +339,7 @@ _zstd__finalize_dict_impl(PyObject *module, PyBytesObject *custom_dict_bytes,
/* Parameters */
- /* Optimize for a specific zstd compression level, 0 means default. */
+ /* Optimize for a specific Zstandard compression level, 0 means default. */
params.compressionLevel = compression_level;
/* Write log to stderr, 0 = none. */
params.notificationLevel = 0;
@@ -367,14 +350,15 @@ _zstd__finalize_dict_impl(PyObject *module, PyBytesObject *custom_dict_bytes,
Py_BEGIN_ALLOW_THREADS
zstd_ret = ZDICT_finalizeDictionary(
PyBytes_AS_STRING(dst_dict_bytes), dict_size,
- PyBytes_AS_STRING(custom_dict_bytes), Py_SIZE(custom_dict_bytes),
+ PyBytes_AS_STRING(custom_dict_bytes),
+ Py_SIZE(custom_dict_bytes),
PyBytes_AS_STRING(samples_bytes), chunk_sizes,
(uint32_t)chunks_number, params);
Py_END_ALLOW_THREADS
- /* Check zstd dict error */
+ /* Check Zstandard dict error */
if (ZDICT_isError(zstd_ret)) {
- _zstd_state* const mod_state = get_zstd_state(module);
+ _zstd_state* mod_state = get_zstd_state(module);
set_zstd_error(mod_state, ERR_FINALIZE_DICT, zstd_ret);
goto error;
}
@@ -396,26 +380,25 @@ success:
/*[clinic input]
-_zstd._get_param_bounds
+_zstd.get_param_bounds
parameter: int
The parameter to get bounds.
is_compress: bool
True for CompressionParameter, False for DecompressionParameter.
-Internal function, get CompressionParameter/DecompressionParameter bounds.
+Get CompressionParameter/DecompressionParameter bounds.
[clinic start generated code]*/
static PyObject *
-_zstd__get_param_bounds_impl(PyObject *module, int parameter,
- int is_compress)
-/*[clinic end generated code: output=9892cd822f937e79 input=884cd1a01125267d]*/
+_zstd_get_param_bounds_impl(PyObject *module, int parameter, int is_compress)
+/*[clinic end generated code: output=4acf5a876f0620ca input=45742ef0a3531b65]*/
{
ZSTD_bounds bound;
if (is_compress) {
bound = ZSTD_cParam_getBounds(parameter);
if (ZSTD_isError(bound.error)) {
- _zstd_state* const mod_state = get_zstd_state(module);
+ _zstd_state* mod_state = get_zstd_state(module);
set_zstd_error(mod_state, ERR_GET_C_BOUNDS, bound.error);
return NULL;
}
@@ -423,7 +406,7 @@ _zstd__get_param_bounds_impl(PyObject *module, int parameter,
else {
bound = ZSTD_dParam_getBounds(parameter);
if (ZSTD_isError(bound.error)) {
- _zstd_state* const mod_state = get_zstd_state(module);
+ _zstd_state* mod_state = get_zstd_state(module);
set_zstd_error(mod_state, ERR_GET_D_BOUNDS, bound.error);
return NULL;
}
@@ -439,24 +422,23 @@ _zstd.get_frame_size
A bytes-like object, it should start from the beginning of a frame,
and contains at least one complete frame.
-Get the size of a zstd frame, including frame header and 4-byte checksum if it has one.
-
-It will iterate all blocks' headers within a frame, to accumulate the frame size.
+Get the size of a Zstandard frame, including the header and optional checksum.
[clinic start generated code]*/
static PyObject *
_zstd_get_frame_size_impl(PyObject *module, Py_buffer *frame_buffer)
-/*[clinic end generated code: output=a7384c2f8780f442 input=7d3ad24311893bf3]*/
+/*[clinic end generated code: output=a7384c2f8780f442 input=3b9f73f8c8129d38]*/
{
size_t frame_size;
- frame_size = ZSTD_findFrameCompressedSize(frame_buffer->buf, frame_buffer->len);
+ frame_size = ZSTD_findFrameCompressedSize(frame_buffer->buf,
+ frame_buffer->len);
if (ZSTD_isError(frame_size)) {
- _zstd_state* const mod_state = get_zstd_state(module);
+ _zstd_state* mod_state = get_zstd_state(module);
PyErr_Format(mod_state->ZstdError,
- "Error when finding the compressed size of a zstd frame. "
- "Make sure the frame_buffer argument starts from the "
- "beginning of a frame, and its length not less than this "
+ "Error when finding the compressed size of a Zstandard frame. "
+ "Ensure the frame_buffer argument starts from the "
+ "beginning of a frame, and its length is not less than this "
"complete frame. Zstd error message: %s.",
ZSTD_getErrorName(frame_size));
return NULL;
@@ -466,17 +448,17 @@ _zstd_get_frame_size_impl(PyObject *module, Py_buffer *frame_buffer)
}
/*[clinic input]
-_zstd._get_frame_info
+_zstd.get_frame_info
frame_buffer: Py_buffer
- A bytes-like object, containing the header of a zstd frame.
+ A bytes-like object, containing the header of a Zstandard frame.
-Internal function, get zstd frame infomation from a frame header.
+Get Zstandard frame infomation from a frame header.
[clinic start generated code]*/
static PyObject *
-_zstd__get_frame_info_impl(PyObject *module, Py_buffer *frame_buffer)
-/*[clinic end generated code: output=5462855464ecdf81 input=67f1f8e4b7b89c4d]*/
+_zstd_get_frame_info_impl(PyObject *module, Py_buffer *frame_buffer)
+/*[clinic end generated code: output=56e033cf48001929 input=94b240583ae22ca5]*/
{
uint64_t decompressed_size;
uint32_t dict_id;
@@ -488,12 +470,12 @@ _zstd__get_frame_info_impl(PyObject *module, Py_buffer *frame_buffer)
/* #define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)
#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2) */
if (decompressed_size == ZSTD_CONTENTSIZE_ERROR) {
- _zstd_state* const mod_state = get_zstd_state(module);
+ _zstd_state* mod_state = get_zstd_state(module);
PyErr_SetString(mod_state->ZstdError,
"Error when getting information from the header of "
- "a zstd frame. Make sure the frame_buffer argument "
+ "a Zstandard frame. Ensure the frame_buffer argument "
"starts from the beginning of a frame, and its length "
- "not less than the frame header (6~18 bytes).");
+ "is not less than the frame header (6~18 bytes).");
return NULL;
}
@@ -508,22 +490,22 @@ _zstd__get_frame_info_impl(PyObject *module, Py_buffer *frame_buffer)
}
/*[clinic input]
-_zstd._set_parameter_types
+_zstd.set_parameter_types
c_parameter_type: object(subclass_of='&PyType_Type')
CompressionParameter IntEnum type object
d_parameter_type: object(subclass_of='&PyType_Type')
DecompressionParameter IntEnum type object
-Internal function, set CompressionParameter/DecompressionParameter types for validity check.
+Set CompressionParameter and DecompressionParameter types for validity check.
[clinic start generated code]*/
static PyObject *
-_zstd__set_parameter_types_impl(PyObject *module, PyObject *c_parameter_type,
- PyObject *d_parameter_type)
-/*[clinic end generated code: output=a13d4890ccbd2873 input=4535545d903853d3]*/
+_zstd_set_parameter_types_impl(PyObject *module, PyObject *c_parameter_type,
+ PyObject *d_parameter_type)
+/*[clinic end generated code: output=f3313b1294f19502 input=75d7a953580fae5f]*/
{
- _zstd_state* const mod_state = get_zstd_state(module);
+ _zstd_state* mod_state = get_zstd_state(module);
if (!PyType_Check(c_parameter_type) || !PyType_Check(d_parameter_type)) {
PyErr_SetString(PyExc_ValueError,
@@ -532,26 +514,22 @@ _zstd__set_parameter_types_impl(PyObject *module, PyObject *c_parameter_type,
return NULL;
}
- Py_XDECREF(mod_state->CParameter_type);
- Py_INCREF(c_parameter_type);
- mod_state->CParameter_type = (PyTypeObject*)c_parameter_type;
-
- Py_XDECREF(mod_state->DParameter_type);
- Py_INCREF(d_parameter_type);
- mod_state->DParameter_type = (PyTypeObject*)d_parameter_type;
+ Py_XSETREF(
+ mod_state->CParameter_type, (PyTypeObject*)Py_NewRef(c_parameter_type));
+ Py_XSETREF(
+ mod_state->DParameter_type, (PyTypeObject*)Py_NewRef(d_parameter_type));
Py_RETURN_NONE;
}
static PyMethodDef _zstd_methods[] = {
- _ZSTD__TRAIN_DICT_METHODDEF
- _ZSTD__FINALIZE_DICT_METHODDEF
- _ZSTD__GET_PARAM_BOUNDS_METHODDEF
+ _ZSTD_TRAIN_DICT_METHODDEF
+ _ZSTD_FINALIZE_DICT_METHODDEF
+ _ZSTD_GET_PARAM_BOUNDS_METHODDEF
_ZSTD_GET_FRAME_SIZE_METHODDEF
- _ZSTD__GET_FRAME_INFO_METHODDEF
- _ZSTD__SET_PARAMETER_TYPES_METHODDEF
-
- {0}
+ _ZSTD_GET_FRAME_INFO_METHODDEF
+ _ZSTD_SET_PARAMETER_TYPES_METHODDEF
+ {NULL, NULL}
};
static int
@@ -584,14 +562,9 @@ do { \
Py_DECREF(v); \
} while (0)
- _zstd_state* const mod_state = get_zstd_state(m);
+ _zstd_state* mod_state = get_zstd_state(m);
/* Reusable objects & variables */
- mod_state->empty_bytes = PyBytes_FromStringAndSize(NULL, 0);
- if (mod_state->empty_bytes == NULL) {
- return -1;
- }
-
mod_state->CParameter_type = NULL;
mod_state->DParameter_type = NULL;
@@ -600,7 +573,7 @@ do { \
ADD_TYPE(mod_state->ZstdCompressor_type, zstd_compressor_type_spec);
ADD_TYPE(mod_state->ZstdDecompressor_type, zstd_decompressor_type_spec);
mod_state->ZstdError = PyErr_NewExceptionWithDoc(
- "_zstd.ZstdError",
+ "compression.zstd.ZstdError",
"An error occurred in the zstd library.",
NULL, NULL);
if (mod_state->ZstdError == NULL) {
@@ -682,6 +655,9 @@ do { \
ADD_INT_CONST_TO_TYPE(mod_state->ZstdCompressor_type,
"FLUSH_FRAME", ZSTD_e_end);
+ /* Make ZstdCompressor immutable (set Py_TPFLAGS_IMMUTABLETYPE) */
+ PyType_Freeze(mod_state->ZstdCompressor_type);
+
#undef ADD_TYPE
#undef ADD_INT_MACRO
#undef ADD_ZSTD_COMPRESSOR_INT_CONST
@@ -692,9 +668,7 @@ do { \
static int
_zstd_traverse(PyObject *module, visitproc visit, void *arg)
{
- _zstd_state* const mod_state = get_zstd_state(module);
-
- Py_VISIT(mod_state->empty_bytes);
+ _zstd_state* mod_state = get_zstd_state(module);
Py_VISIT(mod_state->ZstdDict_type);
Py_VISIT(mod_state->ZstdCompressor_type);
@@ -711,9 +685,7 @@ _zstd_traverse(PyObject *module, visitproc visit, void *arg)
static int
_zstd_clear(PyObject *module)
{
- _zstd_state* const mod_state = get_zstd_state(module);
-
- Py_CLEAR(mod_state->empty_bytes);
+ _zstd_state* mod_state = get_zstd_state(module);
Py_CLEAR(mod_state->ZstdDict_type);
Py_CLEAR(mod_state->ZstdCompressor_type);
@@ -740,15 +712,16 @@ static struct PyModuleDef_Slot _zstd_slots[] = {
{0, NULL},
};
-struct PyModuleDef _zstdmodule = {
- PyModuleDef_HEAD_INIT,
+static struct PyModuleDef _zstdmodule = {
+ .m_base = PyModuleDef_HEAD_INIT,
.m_name = "_zstd",
+ .m_doc = "Implementation module for Zstandard compression.",
.m_size = sizeof(_zstd_state),
.m_slots = _zstd_slots,
.m_methods = _zstd_methods,
.m_traverse = _zstd_traverse,
.m_clear = _zstd_clear,
- .m_free = _zstd_free
+ .m_free = _zstd_free,
};
PyMODINIT_FUNC
diff --git a/Modules/_zstd/_zstdmodule.h b/Modules/_zstd/_zstdmodule.h
index 58622a5cb48..1f4160f474f 100644
--- a/Modules/_zstd/_zstdmodule.h
+++ b/Modules/_zstd/_zstdmodule.h
@@ -1,133 +1,26 @@
-#pragma once
-/*
-Low level interface to Meta's zstd library for use in the compression.zstd
-Python module.
-*/
+/* Low level interface to the Zstandard algorthm & the zstd library. */
/* Declarations shared between different parts of the _zstd module*/
-#include "Python.h"
-
-#include "zstd.h"
-#include "zdict.h"
-
-
-/* Forward declaration of module state */
-typedef struct _zstd_state _zstd_state;
-
-/* Forward reference of module def */
-extern PyModuleDef _zstdmodule;
-
-/* For clinic type calculations */
-static inline _zstd_state *
-get_zstd_state_from_type(PyTypeObject *type) {
- PyObject *module = PyType_GetModuleByDef(type, &_zstdmodule);
- if (module == NULL) {
- return NULL;
- }
- void *state = PyModule_GetState(module);
- assert(state != NULL);
- return (_zstd_state *)state;
-}
+#ifndef ZSTD_MODULE_H
+#define ZSTD_MODULE_H
+/* Type specs */
extern PyType_Spec zstd_dict_type_spec;
extern PyType_Spec zstd_compressor_type_spec;
extern PyType_Spec zstd_decompressor_type_spec;
-struct _zstd_state {
- PyObject *empty_bytes;
-
+typedef struct {
+ /* Module heap types. */
PyTypeObject *ZstdDict_type;
PyTypeObject *ZstdCompressor_type;
PyTypeObject *ZstdDecompressor_type;
PyObject *ZstdError;
+ /* enum types set by set_parameter_types. */
PyTypeObject *CParameter_type;
PyTypeObject *DParameter_type;
-};
-
-typedef struct {
- PyObject_HEAD
-
- /* Reusable compress/decompress dictionary, they are created once and
- can be shared by multiple threads concurrently, since its usage is
- read-only.
- c_dicts is a dict, int(compressionLevel):PyCapsule(ZSTD_CDict*) */
- ZSTD_DDict *d_dict;
- PyObject *c_dicts;
-
- /* Content of the dictionary, bytes object. */
- PyObject *dict_content;
- /* Dictionary id */
- uint32_t dict_id;
-
- /* __init__ has been called, 0 or 1. */
- int inited;
-} ZstdDict;
-
-typedef struct {
- PyObject_HEAD
-
- /* Compression context */
- ZSTD_CCtx *cctx;
-
- /* ZstdDict object in use */
- PyObject *dict;
-
- /* Last mode, initialized to ZSTD_e_end */
- int last_mode;
-
- /* (nbWorker >= 1) ? 1 : 0 */
- int use_multithread;
-
- /* Compression level */
- int compression_level;
-
- /* __init__ has been called, 0 or 1. */
- int inited;
-} ZstdCompressor;
-
-typedef struct {
- PyObject_HEAD
-
- /* Decompression context */
- ZSTD_DCtx *dctx;
-
- /* ZstdDict object in use */
- PyObject *dict;
-
- /* Unconsumed input data */
- char *input_buffer;
- size_t input_buffer_size;
- size_t in_begin, in_end;
-
- /* Unused data */
- PyObject *unused_data;
-
- /* 0 if decompressor has (or may has) unconsumed input data, 0 or 1. */
- char needs_input;
-
- /* For decompress(), 0 or 1.
- 1 when both input and output streams are at a frame edge, means a
- frame is completely decoded and fully flushed, or the decompressor
- just be initialized. */
- char at_frame_edge;
-
- /* For ZstdDecompressor, 0 or 1.
- 1 means the end of the first frame has been reached. */
- char eof;
-
- /* Used for fast reset above three variables */
- char _unused_char_for_align;
-
- /* __init__ has been called, 0 or 1. */
- int inited;
-} ZstdDecompressor;
-
-typedef enum {
- TYPE_DECOMPRESSOR, // <D>, ZstdDecompressor class
- TYPE_ENDLESS_DECOMPRESSOR, // <E>, decompress() function
-} decompress_type;
+} _zstd_state;
typedef enum {
ERR_DECOMPRESS,
@@ -150,28 +43,12 @@ typedef enum {
DICT_TYPE_PREFIX = 2
} dictionary_type;
-static inline int
-mt_continue_should_break(ZSTD_inBuffer *in, ZSTD_outBuffer *out) {
- return in->size == in->pos && out->size != out->pos;
-}
-
/* Format error message and set ZstdError. */
extern void
set_zstd_error(const _zstd_state* const state,
const error_type type, size_t zstd_ret);
extern void
-set_parameter_error(const _zstd_state* const state, int is_compress,
- int key_v, int value_v);
-
-static const char init_twice_msg[] = "__init__ method is called twice.";
-
-extern PyObject *
-decompress_impl(ZstdDecompressor *self, ZSTD_inBuffer *in,
- Py_ssize_t max_length,
- Py_ssize_t initial_size,
- decompress_type type);
+set_parameter_error(int is_compress, int key_v, int value_v);
-extern PyObject *
-compress_impl(ZstdCompressor *self, Py_buffer *data,
- ZSTD_EndDirective end_directive);
+#endif // !ZSTD_MODULE_H
diff --git a/Modules/_zstd/buffer.h b/Modules/_zstd/buffer.h
index 319b1214833..4c885fa0d72 100644
--- a/Modules/_zstd/buffer.h
+++ b/Modules/_zstd/buffer.h
@@ -1,11 +1,12 @@
-/*
-Low level interface to Meta's zstd library for use in the compression.zstd
-Python module.
-*/
+/* Low level interface to the Zstandard algorthm & the zstd library. */
+
+#ifndef ZSTD_BUFFER_H
+#define ZSTD_BUFFER_H
-#include "_zstdmodule.h"
#include "pycore_blocks_output_buffer.h"
+#include <zstd.h> // ZSTD_outBuffer
+
/* Blocks output buffer wrapper code */
/* Initialize the buffer, and grow the buffer.
@@ -18,7 +19,8 @@ _OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, ZSTD_outBuffer *ob,
/* Ensure .list was set to NULL */
assert(buffer->list == NULL);
- Py_ssize_t res = _BlocksOutputBuffer_InitAndGrow(buffer, max_length, &ob->dst);
+ Py_ssize_t res = _BlocksOutputBuffer_InitAndGrow(buffer, max_length,
+ &ob->dst);
if (res < 0) {
return -1;
}
@@ -33,8 +35,7 @@ _OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, ZSTD_outBuffer *ob,
Return -1 on failure */
static inline int
_OutputBuffer_InitWithSize(_BlocksOutputBuffer *buffer, ZSTD_outBuffer *ob,
- Py_ssize_t max_length,
- Py_ssize_t init_size)
+ Py_ssize_t max_length, Py_ssize_t init_size)
{
Py_ssize_t block_size;
@@ -49,7 +50,8 @@ _OutputBuffer_InitWithSize(_BlocksOutputBuffer *buffer, ZSTD_outBuffer *ob,
block_size = init_size;
}
- Py_ssize_t res = _BlocksOutputBuffer_InitWithSize(buffer, block_size, &ob->dst);
+ Py_ssize_t res = _BlocksOutputBuffer_InitWithSize(buffer, block_size,
+ &ob->dst);
if (res < 0) {
return -1;
}
@@ -102,3 +104,5 @@ _OutputBuffer_ReachedMaxLength(_BlocksOutputBuffer *buffer, ZSTD_outBuffer *ob)
return buffer->allocated == buffer->max_length;
}
+
+#endif // !ZSTD_BUFFER_H
diff --git a/Modules/_zstd/clinic/_zstdmodule.c.h b/Modules/_zstd/clinic/_zstdmodule.c.h
index 2f8225389b7..766e1cfa776 100644
--- a/Modules/_zstd/clinic/_zstdmodule.c.h
+++ b/Modules/_zstd/clinic/_zstdmodule.c.h
@@ -9,11 +9,11 @@ preserve
#include "pycore_abstract.h" // _PyNumber_Index()
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
-PyDoc_STRVAR(_zstd__train_dict__doc__,
-"_train_dict($module, samples_bytes, samples_sizes, dict_size, /)\n"
+PyDoc_STRVAR(_zstd_train_dict__doc__,
+"train_dict($module, samples_bytes, samples_sizes, dict_size, /)\n"
"--\n"
"\n"
-"Internal function, train a zstd dictionary on sample data.\n"
+"Train a Zstandard dictionary on sample data.\n"
"\n"
" samples_bytes\n"
" Concatenation of samples.\n"
@@ -22,31 +22,31 @@ PyDoc_STRVAR(_zstd__train_dict__doc__,
" dict_size\n"
" The size of the dictionary.");
-#define _ZSTD__TRAIN_DICT_METHODDEF \
- {"_train_dict", _PyCFunction_CAST(_zstd__train_dict), METH_FASTCALL, _zstd__train_dict__doc__},
+#define _ZSTD_TRAIN_DICT_METHODDEF \
+ {"train_dict", _PyCFunction_CAST(_zstd_train_dict), METH_FASTCALL, _zstd_train_dict__doc__},
static PyObject *
-_zstd__train_dict_impl(PyObject *module, PyBytesObject *samples_bytes,
- PyObject *samples_sizes, Py_ssize_t dict_size);
+_zstd_train_dict_impl(PyObject *module, PyBytesObject *samples_bytes,
+ PyObject *samples_sizes, Py_ssize_t dict_size);
static PyObject *
-_zstd__train_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+_zstd_train_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyBytesObject *samples_bytes;
PyObject *samples_sizes;
Py_ssize_t dict_size;
- if (!_PyArg_CheckPositional("_train_dict", nargs, 3, 3)) {
+ if (!_PyArg_CheckPositional("train_dict", nargs, 3, 3)) {
goto exit;
}
if (!PyBytes_Check(args[0])) {
- _PyArg_BadArgument("_train_dict", "argument 1", "bytes", args[0]);
+ _PyArg_BadArgument("train_dict", "argument 1", "bytes", args[0]);
goto exit;
}
samples_bytes = (PyBytesObject *)args[0];
if (!PyTuple_Check(args[1])) {
- _PyArg_BadArgument("_train_dict", "argument 2", "tuple", args[1]);
+ _PyArg_BadArgument("train_dict", "argument 2", "tuple", args[1]);
goto exit;
}
samples_sizes = args[1];
@@ -62,18 +62,18 @@ _zstd__train_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
}
dict_size = ival;
}
- return_value = _zstd__train_dict_impl(module, samples_bytes, samples_sizes, dict_size);
+ return_value = _zstd_train_dict_impl(module, samples_bytes, samples_sizes, dict_size);
exit:
return return_value;
}
-PyDoc_STRVAR(_zstd__finalize_dict__doc__,
-"_finalize_dict($module, custom_dict_bytes, samples_bytes,\n"
-" samples_sizes, dict_size, compression_level, /)\n"
+PyDoc_STRVAR(_zstd_finalize_dict__doc__,
+"finalize_dict($module, custom_dict_bytes, samples_bytes, samples_sizes,\n"
+" dict_size, compression_level, /)\n"
"--\n"
"\n"
-"Internal function, finalize a zstd dictionary.\n"
+"Finalize a Zstandard dictionary.\n"
"\n"
" custom_dict_bytes\n"
" Custom dictionary content.\n"
@@ -84,19 +84,19 @@ PyDoc_STRVAR(_zstd__finalize_dict__doc__,
" dict_size\n"
" The size of the dictionary.\n"
" compression_level\n"
-" Optimize for a specific zstd compression level, 0 means default.");
+" Optimize for a specific Zstandard compression level, 0 means default.");
-#define _ZSTD__FINALIZE_DICT_METHODDEF \
- {"_finalize_dict", _PyCFunction_CAST(_zstd__finalize_dict), METH_FASTCALL, _zstd__finalize_dict__doc__},
+#define _ZSTD_FINALIZE_DICT_METHODDEF \
+ {"finalize_dict", _PyCFunction_CAST(_zstd_finalize_dict), METH_FASTCALL, _zstd_finalize_dict__doc__},
static PyObject *
-_zstd__finalize_dict_impl(PyObject *module, PyBytesObject *custom_dict_bytes,
- PyBytesObject *samples_bytes,
- PyObject *samples_sizes, Py_ssize_t dict_size,
- int compression_level);
+_zstd_finalize_dict_impl(PyObject *module, PyBytesObject *custom_dict_bytes,
+ PyBytesObject *samples_bytes,
+ PyObject *samples_sizes, Py_ssize_t dict_size,
+ int compression_level);
static PyObject *
-_zstd__finalize_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+_zstd_finalize_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyBytesObject *custom_dict_bytes;
@@ -105,21 +105,21 @@ _zstd__finalize_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
Py_ssize_t dict_size;
int compression_level;
- if (!_PyArg_CheckPositional("_finalize_dict", nargs, 5, 5)) {
+ if (!_PyArg_CheckPositional("finalize_dict", nargs, 5, 5)) {
goto exit;
}
if (!PyBytes_Check(args[0])) {
- _PyArg_BadArgument("_finalize_dict", "argument 1", "bytes", args[0]);
+ _PyArg_BadArgument("finalize_dict", "argument 1", "bytes", args[0]);
goto exit;
}
custom_dict_bytes = (PyBytesObject *)args[0];
if (!PyBytes_Check(args[1])) {
- _PyArg_BadArgument("_finalize_dict", "argument 2", "bytes", args[1]);
+ _PyArg_BadArgument("finalize_dict", "argument 2", "bytes", args[1]);
goto exit;
}
samples_bytes = (PyBytesObject *)args[1];
if (!PyTuple_Check(args[2])) {
- _PyArg_BadArgument("_finalize_dict", "argument 3", "tuple", args[2]);
+ _PyArg_BadArgument("finalize_dict", "argument 3", "tuple", args[2]);
goto exit;
}
samples_sizes = args[2];
@@ -139,32 +139,31 @@ _zstd__finalize_dict(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (compression_level == -1 && PyErr_Occurred()) {
goto exit;
}
- return_value = _zstd__finalize_dict_impl(module, custom_dict_bytes, samples_bytes, samples_sizes, dict_size, compression_level);
+ return_value = _zstd_finalize_dict_impl(module, custom_dict_bytes, samples_bytes, samples_sizes, dict_size, compression_level);
exit:
return return_value;
}
-PyDoc_STRVAR(_zstd__get_param_bounds__doc__,
-"_get_param_bounds($module, /, parameter, is_compress)\n"
+PyDoc_STRVAR(_zstd_get_param_bounds__doc__,
+"get_param_bounds($module, /, parameter, is_compress)\n"
"--\n"
"\n"
-"Internal function, get CompressionParameter/DecompressionParameter bounds.\n"
+"Get CompressionParameter/DecompressionParameter bounds.\n"
"\n"
" parameter\n"
" The parameter to get bounds.\n"
" is_compress\n"
" True for CompressionParameter, False for DecompressionParameter.");
-#define _ZSTD__GET_PARAM_BOUNDS_METHODDEF \
- {"_get_param_bounds", _PyCFunction_CAST(_zstd__get_param_bounds), METH_FASTCALL|METH_KEYWORDS, _zstd__get_param_bounds__doc__},
+#define _ZSTD_GET_PARAM_BOUNDS_METHODDEF \
+ {"get_param_bounds", _PyCFunction_CAST(_zstd_get_param_bounds), METH_FASTCALL|METH_KEYWORDS, _zstd_get_param_bounds__doc__},
static PyObject *
-_zstd__get_param_bounds_impl(PyObject *module, int parameter,
- int is_compress);
+_zstd_get_param_bounds_impl(PyObject *module, int parameter, int is_compress);
static PyObject *
-_zstd__get_param_bounds(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_zstd_get_param_bounds(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
@@ -190,7 +189,7 @@ _zstd__get_param_bounds(PyObject *module, PyObject *const *args, Py_ssize_t narg
static const char * const _keywords[] = {"parameter", "is_compress", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
- .fname = "_get_param_bounds",
+ .fname = "get_param_bounds",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
@@ -211,7 +210,7 @@ _zstd__get_param_bounds(PyObject *module, PyObject *const *args, Py_ssize_t narg
if (is_compress < 0) {
goto exit;
}
- return_value = _zstd__get_param_bounds_impl(module, parameter, is_compress);
+ return_value = _zstd_get_param_bounds_impl(module, parameter, is_compress);
exit:
return return_value;
@@ -221,13 +220,11 @@ PyDoc_STRVAR(_zstd_get_frame_size__doc__,
"get_frame_size($module, /, frame_buffer)\n"
"--\n"
"\n"
-"Get the size of a zstd frame, including frame header and 4-byte checksum if it has one.\n"
+"Get the size of a Zstandard frame, including the header and optional checksum.\n"
"\n"
" frame_buffer\n"
" A bytes-like object, it should start from the beginning of a frame,\n"
-" and contains at least one complete frame.\n"
-"\n"
-"It will iterate all blocks\' headers within a frame, to accumulate the frame size.");
+" and contains at least one complete frame.");
#define _ZSTD_GET_FRAME_SIZE_METHODDEF \
{"get_frame_size", _PyCFunction_CAST(_zstd_get_frame_size), METH_FASTCALL|METH_KEYWORDS, _zstd_get_frame_size__doc__},
@@ -288,23 +285,23 @@ exit:
return return_value;
}
-PyDoc_STRVAR(_zstd__get_frame_info__doc__,
-"_get_frame_info($module, /, frame_buffer)\n"
+PyDoc_STRVAR(_zstd_get_frame_info__doc__,
+"get_frame_info($module, /, frame_buffer)\n"
"--\n"
"\n"
-"Internal function, get zstd frame infomation from a frame header.\n"
+"Get Zstandard frame infomation from a frame header.\n"
"\n"
" frame_buffer\n"
-" A bytes-like object, containing the header of a zstd frame.");
+" A bytes-like object, containing the header of a Zstandard frame.");
-#define _ZSTD__GET_FRAME_INFO_METHODDEF \
- {"_get_frame_info", _PyCFunction_CAST(_zstd__get_frame_info), METH_FASTCALL|METH_KEYWORDS, _zstd__get_frame_info__doc__},
+#define _ZSTD_GET_FRAME_INFO_METHODDEF \
+ {"get_frame_info", _PyCFunction_CAST(_zstd_get_frame_info), METH_FASTCALL|METH_KEYWORDS, _zstd_get_frame_info__doc__},
static PyObject *
-_zstd__get_frame_info_impl(PyObject *module, Py_buffer *frame_buffer);
+_zstd_get_frame_info_impl(PyObject *module, Py_buffer *frame_buffer);
static PyObject *
-_zstd__get_frame_info(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_zstd_get_frame_info(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
@@ -330,7 +327,7 @@ _zstd__get_frame_info(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
static const char * const _keywords[] = {"frame_buffer", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
- .fname = "_get_frame_info",
+ .fname = "get_frame_info",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
@@ -345,7 +342,7 @@ _zstd__get_frame_info(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
if (PyObject_GetBuffer(args[0], &frame_buffer, PyBUF_SIMPLE) != 0) {
goto exit;
}
- return_value = _zstd__get_frame_info_impl(module, &frame_buffer);
+ return_value = _zstd_get_frame_info_impl(module, &frame_buffer);
exit:
/* Cleanup for frame_buffer */
@@ -356,26 +353,26 @@ exit:
return return_value;
}
-PyDoc_STRVAR(_zstd__set_parameter_types__doc__,
-"_set_parameter_types($module, /, c_parameter_type, d_parameter_type)\n"
+PyDoc_STRVAR(_zstd_set_parameter_types__doc__,
+"set_parameter_types($module, /, c_parameter_type, d_parameter_type)\n"
"--\n"
"\n"
-"Internal function, set CompressionParameter/DecompressionParameter types for validity check.\n"
+"Set CompressionParameter and DecompressionParameter types for validity check.\n"
"\n"
" c_parameter_type\n"
" CompressionParameter IntEnum type object\n"
" d_parameter_type\n"
" DecompressionParameter IntEnum type object");
-#define _ZSTD__SET_PARAMETER_TYPES_METHODDEF \
- {"_set_parameter_types", _PyCFunction_CAST(_zstd__set_parameter_types), METH_FASTCALL|METH_KEYWORDS, _zstd__set_parameter_types__doc__},
+#define _ZSTD_SET_PARAMETER_TYPES_METHODDEF \
+ {"set_parameter_types", _PyCFunction_CAST(_zstd_set_parameter_types), METH_FASTCALL|METH_KEYWORDS, _zstd_set_parameter_types__doc__},
static PyObject *
-_zstd__set_parameter_types_impl(PyObject *module, PyObject *c_parameter_type,
- PyObject *d_parameter_type);
+_zstd_set_parameter_types_impl(PyObject *module, PyObject *c_parameter_type,
+ PyObject *d_parameter_type);
static PyObject *
-_zstd__set_parameter_types(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_zstd_set_parameter_types(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
@@ -401,7 +398,7 @@ _zstd__set_parameter_types(PyObject *module, PyObject *const *args, Py_ssize_t n
static const char * const _keywords[] = {"c_parameter_type", "d_parameter_type", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
- .fname = "_set_parameter_types",
+ .fname = "set_parameter_types",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
@@ -415,18 +412,18 @@ _zstd__set_parameter_types(PyObject *module, PyObject *const *args, Py_ssize_t n
goto exit;
}
if (!PyObject_TypeCheck(args[0], &PyType_Type)) {
- _PyArg_BadArgument("_set_parameter_types", "argument 'c_parameter_type'", (&PyType_Type)->tp_name, args[0]);
+ _PyArg_BadArgument("set_parameter_types", "argument 'c_parameter_type'", (&PyType_Type)->tp_name, args[0]);
goto exit;
}
c_parameter_type = args[0];
if (!PyObject_TypeCheck(args[1], &PyType_Type)) {
- _PyArg_BadArgument("_set_parameter_types", "argument 'd_parameter_type'", (&PyType_Type)->tp_name, args[1]);
+ _PyArg_BadArgument("set_parameter_types", "argument 'd_parameter_type'", (&PyType_Type)->tp_name, args[1]);
goto exit;
}
d_parameter_type = args[1];
- return_value = _zstd__set_parameter_types_impl(module, c_parameter_type, d_parameter_type);
+ return_value = _zstd_set_parameter_types_impl(module, c_parameter_type, d_parameter_type);
exit:
return return_value;
}
-/*[clinic end generated code: output=189c462236a7096c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=437b084f149e68e5 input=a9049054013a1b77]*/
diff --git a/Modules/_zstd/clinic/compressor.c.h b/Modules/_zstd/clinic/compressor.c.h
index d7909cdf89f..f69161b590e 100644
--- a/Modules/_zstd/clinic/compressor.c.h
+++ b/Modules/_zstd/clinic/compressor.c.h
@@ -8,30 +8,30 @@ preserve
#endif
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
-PyDoc_STRVAR(_zstd_ZstdCompressor___init____doc__,
+PyDoc_STRVAR(_zstd_ZstdCompressor_new__doc__,
"ZstdCompressor(level=None, options=None, zstd_dict=None)\n"
"--\n"
"\n"
"Create a compressor object for compressing data incrementally.\n"
"\n"
" level\n"
-" The compression level to use, defaults to ZSTD_CLEVEL_DEFAULT.\n"
+" The compression level to use. Defaults to COMPRESSION_LEVEL_DEFAULT.\n"
" options\n"
" A dict object that contains advanced compression parameters.\n"
" zstd_dict\n"
-" A ZstdDict object, a pre-trained zstd dictionary.\n"
+" A ZstdDict object, a pre-trained Zstandard dictionary.\n"
"\n"
"Thread-safe at method level. For one-shot compression, use the compress()\n"
"function instead.");
-static int
-_zstd_ZstdCompressor___init___impl(ZstdCompressor *self, PyObject *level,
- PyObject *options, PyObject *zstd_dict);
+static PyObject *
+_zstd_ZstdCompressor_new_impl(PyTypeObject *type, PyObject *level,
+ PyObject *options, PyObject *zstd_dict);
-static int
-_zstd_ZstdCompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+static PyObject *
+_zstd_ZstdCompressor_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
- int return_value = -1;
+ PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 3
@@ -89,7 +89,7 @@ _zstd_ZstdCompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
}
zstd_dict = fastargs[2];
skip_optional_pos:
- return_value = _zstd_ZstdCompressor___init___impl((ZstdCompressor *)self, level, options, zstd_dict);
+ return_value = _zstd_ZstdCompressor_new_impl(type, level, options, zstd_dict);
exit:
return return_value;
@@ -189,9 +189,9 @@ PyDoc_STRVAR(_zstd_ZstdCompressor_flush__doc__,
" Can be these 2 values ZstdCompressor.FLUSH_FRAME,\n"
" ZstdCompressor.FLUSH_BLOCK\n"
"\n"
-"Flush any remaining data left in internal buffers. Since zstd data consists\n"
-"of one or more independent frames, the compressor object can still be used\n"
-"after this method is called.");
+"Flush any remaining data left in internal buffers. Since Zstandard data\n"
+"consists of one or more independent frames, the compressor object can still\n"
+"be used after this method is called.");
#define _ZSTD_ZSTDCOMPRESSOR_FLUSH_METHODDEF \
{"flush", _PyCFunction_CAST(_zstd_ZstdCompressor_flush), METH_FASTCALL|METH_KEYWORDS, _zstd_ZstdCompressor_flush__doc__},
@@ -252,4 +252,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=ef69eab155be39f6 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=ee2d1dc298de790c input=a9049054013a1b77]*/
diff --git a/Modules/_zstd/clinic/decompressor.c.h b/Modules/_zstd/clinic/decompressor.c.h
index 9359c637203..c6fdae74ab0 100644
--- a/Modules/_zstd/clinic/decompressor.c.h
+++ b/Modules/_zstd/clinic/decompressor.c.h
@@ -7,31 +7,30 @@ preserve
# include "pycore_runtime.h" // _Py_ID()
#endif
#include "pycore_abstract.h" // _PyNumber_Index()
-#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
-PyDoc_STRVAR(_zstd_ZstdDecompressor___init____doc__,
+PyDoc_STRVAR(_zstd_ZstdDecompressor_new__doc__,
"ZstdDecompressor(zstd_dict=None, options=None)\n"
"--\n"
"\n"
"Create a decompressor object for decompressing data incrementally.\n"
"\n"
" zstd_dict\n"
-" A ZstdDict object, a pre-trained zstd dictionary.\n"
+" A ZstdDict object, a pre-trained Zstandard dictionary.\n"
" options\n"
" A dict object that contains advanced decompression parameters.\n"
"\n"
"Thread-safe at method level. For one-shot decompression, use the decompress()\n"
"function instead.");
-static int
-_zstd_ZstdDecompressor___init___impl(ZstdDecompressor *self,
- PyObject *zstd_dict, PyObject *options);
+static PyObject *
+_zstd_ZstdDecompressor_new_impl(PyTypeObject *type, PyObject *zstd_dict,
+ PyObject *options);
-static int
-_zstd_ZstdDecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+static PyObject *
+_zstd_ZstdDecompressor_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
- int return_value = -1;
+ PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 2
@@ -82,7 +81,7 @@ _zstd_ZstdDecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs
}
options = fastargs[1];
skip_optional_pos:
- return_value = _zstd_ZstdDecompressor___init___impl((ZstdDecompressor *)self, zstd_dict, options);
+ return_value = _zstd_ZstdDecompressor_new_impl(type, zstd_dict, options);
exit:
return return_value;
@@ -114,13 +113,7 @@ _zstd_ZstdDecompressor_unused_data_get_impl(ZstdDecompressor *self);
static PyObject *
_zstd_ZstdDecompressor_unused_data_get(PyObject *self, void *Py_UNUSED(context))
{
- PyObject *return_value = NULL;
-
- Py_BEGIN_CRITICAL_SECTION(self);
- return_value = _zstd_ZstdDecompressor_unused_data_get_impl((ZstdDecompressor *)self);
- Py_END_CRITICAL_SECTION();
-
- return return_value;
+ return _zstd_ZstdDecompressor_unused_data_get_impl((ZstdDecompressor *)self);
}
PyDoc_STRVAR(_zstd_ZstdDecompressor_decompress__doc__,
@@ -130,7 +123,7 @@ PyDoc_STRVAR(_zstd_ZstdDecompressor_decompress__doc__,
"Decompress *data*, returning uncompressed bytes if possible, or b\'\' otherwise.\n"
"\n"
" data\n"
-" A bytes-like object, zstd data to be decompressed.\n"
+" A bytes-like object, Zstandard data to be decompressed.\n"
" max_length\n"
" Maximum size of returned data. When it is negative, the size of\n"
" output buffer is unlimited. When it is nonnegative, returns at\n"
@@ -227,4 +220,4 @@ exit:
return return_value;
}
-/*[clinic end generated code: output=ae703f0465a2906d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=30c12ef047027ede input=a9049054013a1b77]*/
diff --git a/Modules/_zstd/clinic/zstddict.c.h b/Modules/_zstd/clinic/zstddict.c.h
index 4e0f7b64172..79db85405d6 100644
--- a/Modules/_zstd/clinic/zstddict.c.h
+++ b/Modules/_zstd/clinic/zstddict.c.h
@@ -6,38 +6,35 @@ preserve
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
-#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
-PyDoc_STRVAR(_zstd_ZstdDict___init____doc__,
-"ZstdDict(dict_content, is_raw=False)\n"
+PyDoc_STRVAR(_zstd_ZstdDict_new__doc__,
+"ZstdDict(dict_content, /, *, is_raw=False)\n"
"--\n"
"\n"
-"Represents a zstd dictionary, which can be used for compression/decompression.\n"
+"Represents a Zstandard dictionary.\n"
"\n"
" dict_content\n"
-" A bytes-like object, dictionary\'s content.\n"
+" The content of a Zstandard dictionary as a bytes-like object.\n"
" is_raw\n"
-" This parameter is for advanced user. True means dict_content\n"
-" argument is a \"raw content\" dictionary, free of any format\n"
-" restriction. False means dict_content argument is an ordinary\n"
-" zstd dictionary, was created by zstd functions, follow a\n"
-" specified format.\n"
+" If true, perform no checks on *dict_content*, useful for some\n"
+" advanced cases. Otherwise, check that the content represents\n"
+" a Zstandard dictionary created by the zstd library or CLI.\n"
"\n"
-"It\'s thread-safe, and can be shared by multiple ZstdCompressor /\n"
-"ZstdDecompressor objects.");
+"The dictionary can be used for compression or decompression, and can be shared\n"
+"by multiple ZstdCompressor or ZstdDecompressor objects.");
-static int
-_zstd_ZstdDict___init___impl(ZstdDict *self, PyObject *dict_content,
- int is_raw);
+static PyObject *
+_zstd_ZstdDict_new_impl(PyTypeObject *type, Py_buffer *dict_content,
+ int is_raw);
-static int
-_zstd_ZstdDict___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+static PyObject *
+_zstd_ZstdDict_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
- int return_value = -1;
+ PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 1
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -46,7 +43,7 @@ _zstd_ZstdDict___init__(PyObject *self, PyObject *args, PyObject *kwargs)
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(dict_content), &_Py_ID(is_raw), },
+ .ob_item = { &_Py_ID(is_raw), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -55,7 +52,7 @@ _zstd_ZstdDict___init__(PyObject *self, PyObject *args, PyObject *kwargs)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"dict_content", "is_raw", NULL};
+ static const char * const _keywords[] = {"", "is_raw", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "ZstdDict",
@@ -66,33 +63,68 @@ _zstd_ZstdDict___init__(PyObject *self, PyObject *args, PyObject *kwargs)
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
- PyObject *dict_content;
+ Py_buffer dict_content = {NULL, NULL};
int is_raw = 0;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser,
- /*minpos*/ 1, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+ /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
if (!fastargs) {
goto exit;
}
- dict_content = fastargs[0];
+ if (PyObject_GetBuffer(fastargs[0], &dict_content, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
if (!noptargs) {
- goto skip_optional_pos;
+ goto skip_optional_kwonly;
}
is_raw = PyObject_IsTrue(fastargs[1]);
if (is_raw < 0) {
goto exit;
}
-skip_optional_pos:
- return_value = _zstd_ZstdDict___init___impl((ZstdDict *)self, dict_content, is_raw);
+skip_optional_kwonly:
+ return_value = _zstd_ZstdDict_new_impl(type, &dict_content, is_raw);
exit:
+ /* Cleanup for dict_content */
+ if (dict_content.obj) {
+ PyBuffer_Release(&dict_content);
+ }
+
return return_value;
}
+PyDoc_STRVAR(_zstd_ZstdDict_dict_content__doc__,
+"The content of a Zstandard dictionary, as a bytes object.");
+#if defined(_zstd_ZstdDict_dict_content_DOCSTR)
+# undef _zstd_ZstdDict_dict_content_DOCSTR
+#endif
+#define _zstd_ZstdDict_dict_content_DOCSTR _zstd_ZstdDict_dict_content__doc__
+
+#if !defined(_zstd_ZstdDict_dict_content_DOCSTR)
+# define _zstd_ZstdDict_dict_content_DOCSTR NULL
+#endif
+#if defined(_ZSTD_ZSTDDICT_DICT_CONTENT_GETSETDEF)
+# undef _ZSTD_ZSTDDICT_DICT_CONTENT_GETSETDEF
+# define _ZSTD_ZSTDDICT_DICT_CONTENT_GETSETDEF {"dict_content", (getter)_zstd_ZstdDict_dict_content_get, (setter)_zstd_ZstdDict_dict_content_set, _zstd_ZstdDict_dict_content_DOCSTR},
+#else
+# define _ZSTD_ZSTDDICT_DICT_CONTENT_GETSETDEF {"dict_content", (getter)_zstd_ZstdDict_dict_content_get, NULL, _zstd_ZstdDict_dict_content_DOCSTR},
+#endif
+
+static PyObject *
+_zstd_ZstdDict_dict_content_get_impl(ZstdDict *self);
+
+static PyObject *
+_zstd_ZstdDict_dict_content_get(PyObject *self, void *Py_UNUSED(context))
+{
+ return _zstd_ZstdDict_dict_content_get_impl((ZstdDict *)self);
+}
+
PyDoc_STRVAR(_zstd_ZstdDict_as_digested_dict__doc__,
"Load as a digested dictionary to compressor.\n"
"\n"
-"Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_digested_dict)\n"
+"Pass this attribute as zstd_dict argument:\n"
+"compress(dat, zstd_dict=zd.as_digested_dict)\n"
+"\n"
"1. Some advanced compression parameters of compressor may be overridden\n"
" by parameters of digested dictionary.\n"
"2. ZstdDict has a digested dictionaries cache for each compression level.\n"
@@ -120,19 +152,15 @@ _zstd_ZstdDict_as_digested_dict_get_impl(ZstdDict *self);
static PyObject *
_zstd_ZstdDict_as_digested_dict_get(PyObject *self, void *Py_UNUSED(context))
{
- PyObject *return_value = NULL;
-
- Py_BEGIN_CRITICAL_SECTION(self);
- return_value = _zstd_ZstdDict_as_digested_dict_get_impl((ZstdDict *)self);
- Py_END_CRITICAL_SECTION();
-
- return return_value;
+ return _zstd_ZstdDict_as_digested_dict_get_impl((ZstdDict *)self);
}
PyDoc_STRVAR(_zstd_ZstdDict_as_undigested_dict__doc__,
"Load as an undigested dictionary to compressor.\n"
"\n"
-"Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_undigested_dict)\n"
+"Pass this attribute as zstd_dict argument:\n"
+"compress(dat, zstd_dict=zd.as_undigested_dict)\n"
+"\n"
"1. The advanced compression parameters of compressor will not be overridden.\n"
"2. Loading an undigested dictionary is costly. If load an undigested dictionary\n"
" multiple times, consider reusing a compressor object.\n"
@@ -158,19 +186,15 @@ _zstd_ZstdDict_as_undigested_dict_get_impl(ZstdDict *self);
static PyObject *
_zstd_ZstdDict_as_undigested_dict_get(PyObject *self, void *Py_UNUSED(context))
{
- PyObject *return_value = NULL;
-
- Py_BEGIN_CRITICAL_SECTION(self);
- return_value = _zstd_ZstdDict_as_undigested_dict_get_impl((ZstdDict *)self);
- Py_END_CRITICAL_SECTION();
-
- return return_value;
+ return _zstd_ZstdDict_as_undigested_dict_get_impl((ZstdDict *)self);
}
PyDoc_STRVAR(_zstd_ZstdDict_as_prefix__doc__,
"Load as a prefix to compressor/decompressor.\n"
"\n"
-"Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_prefix)\n"
+"Pass this attribute as zstd_dict argument:\n"
+"compress(dat, zstd_dict=zd.as_prefix)\n"
+"\n"
"1. Prefix is compatible with long distance matching, while dictionary is not.\n"
"2. It only works for the first frame, then the compressor/decompressor will\n"
" return to no prefix state.\n"
@@ -196,12 +220,6 @@ _zstd_ZstdDict_as_prefix_get_impl(ZstdDict *self);
static PyObject *
_zstd_ZstdDict_as_prefix_get(PyObject *self, void *Py_UNUSED(context))
{
- PyObject *return_value = NULL;
-
- Py_BEGIN_CRITICAL_SECTION(self);
- return_value = _zstd_ZstdDict_as_prefix_get_impl((ZstdDict *)self);
- Py_END_CRITICAL_SECTION();
-
- return return_value;
+ return _zstd_ZstdDict_as_prefix_get_impl((ZstdDict *)self);
}
-/*[clinic end generated code: output=59257c053f74eda7 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4696cbc722e5fdfc input=a9049054013a1b77]*/
diff --git a/Modules/_zstd/compressor.c b/Modules/_zstd/compressor.c
index 48ecf4b0da9..8ff2a3aadc1 100644
--- a/Modules/_zstd/compressor.c
+++ b/Modules/_zstd/compressor.c
@@ -1,123 +1,154 @@
-/*
-Low level interface to Meta's zstd library for use in the compression.zstd
-Python module.
-*/
+/* Low level interface to the Zstandard algorthm & the zstd library. */
/* ZstdCompressor class definitions */
/*[clinic input]
module _zstd
-class _zstd.ZstdCompressor "ZstdCompressor *" "clinic_state()->ZstdCompressor_type"
+class _zstd.ZstdCompressor "ZstdCompressor *" "&zstd_compressor_type_spec"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=875bf614798f80cb]*/
-
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7166021db1ef7df8]*/
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
-#include "_zstdmodule.h"
+#include "Python.h"
+#include "_zstdmodule.h"
#include "buffer.h"
+#include "zstddict.h"
+#include "internal/pycore_lock.h" // PyMutex_IsLocked
#include <stddef.h> // offsetof()
+#include <zstd.h> // ZSTD_*()
+
+typedef struct {
+ PyObject_HEAD
+
+ /* Compression context */
+ ZSTD_CCtx *cctx;
+
+ /* ZstdDict object in use */
+ PyObject *dict;
+ /* Last mode, initialized to ZSTD_e_end */
+ int last_mode;
+
+ /* (nbWorker >= 1) ? 1 : 0 */
+ int use_multithread;
+
+ /* Compression level */
+ int compression_level;
+
+ /* Lock to protect the compression context */
+ PyMutex lock;
+} ZstdCompressor;
#define ZstdCompressor_CAST(op) ((ZstdCompressor *)op)
+#include "clinic/compressor.c.h"
+
static int
-_zstd_set_c_parameters(ZstdCompressor *self, PyObject *level_or_options,
- const char *arg_name, const char* arg_type)
+_zstd_set_c_level(ZstdCompressor *self, int level)
{
- size_t zstd_ret;
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
- if (mod_state == NULL) {
+ /* Set integer compression level */
+ int min_level = ZSTD_minCLevel();
+ int max_level = ZSTD_maxCLevel();
+ if (level < min_level || level > max_level) {
+ PyErr_Format(PyExc_ValueError,
+ "illegal compression level %d; the valid range is [%d, %d]",
+ level, min_level, max_level);
return -1;
}
- /* Integer compression level */
- if (PyLong_Check(level_or_options)) {
- int level = PyLong_AsInt(level_or_options);
- if (level == -1 && PyErr_Occurred()) {
- PyErr_Format(PyExc_ValueError,
- "Compression level should be an int value between %d and %d.",
- ZSTD_minCLevel(), ZSTD_maxCLevel());
+ /* Save for generating ZSTD_CDICT */
+ self->compression_level = level;
+
+ /* Set compressionLevel to compression context */
+ size_t zstd_ret = ZSTD_CCtx_setParameter(
+ self->cctx, ZSTD_c_compressionLevel, level);
+
+ /* Check error */
+ if (ZSTD_isError(zstd_ret)) {
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
+ if (mod_state == NULL) {
return -1;
}
+ set_zstd_error(mod_state, ERR_SET_C_LEVEL, zstd_ret);
+ return -1;
+ }
+ return 0;
+}
- /* Save for generating ZSTD_CDICT */
- self->compression_level = level;
+static int
+_zstd_set_c_parameters(ZstdCompressor *self, PyObject *options)
+{
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
+ if (mod_state == NULL) {
+ return -1;
+ }
- /* Set compressionLevel to compression context */
- zstd_ret = ZSTD_CCtx_setParameter(self->cctx,
- ZSTD_c_compressionLevel,
- level);
+ if (!PyDict_Check(options)) {
+ PyErr_Format(PyExc_TypeError,
+ "ZstdCompressor() argument 'options' must be dict, not %T",
+ options);
+ return -1;
+ }
- /* Check error */
- if (ZSTD_isError(zstd_ret)) {
- set_zstd_error(mod_state, ERR_SET_C_LEVEL, zstd_ret);
+ Py_ssize_t pos = 0;
+ PyObject *key, *value;
+ while (PyDict_Next(options, &pos, &key, &value)) {
+ /* Check key type */
+ if (Py_TYPE(key) == mod_state->DParameter_type) {
+ PyErr_SetString(PyExc_TypeError,
+ "compression options dictionary key must not be a "
+ "DecompressionParameter attribute");
return -1;
}
- return 0;
- }
- /* Options dict */
- if (PyDict_Check(level_or_options)) {
- PyObject *key, *value;
- Py_ssize_t pos = 0;
+ Py_INCREF(key);
+ Py_INCREF(value);
+ int key_v = PyLong_AsInt(key);
+ Py_DECREF(key);
+ if (key_v == -1 && PyErr_Occurred()) {
+ Py_DECREF(value);
+ return -1;
+ }
- while (PyDict_Next(level_or_options, &pos, &key, &value)) {
- /* Check key type */
- if (Py_TYPE(key) == mod_state->DParameter_type) {
- PyErr_SetString(PyExc_TypeError,
- "Key of compression option dict should "
- "NOT be DecompressionParameter.");
- return -1;
- }
+ int value_v = PyLong_AsInt(value);
+ Py_DECREF(value);
+ if (value_v == -1 && PyErr_Occurred()) {
+ return -1;
+ }
- int key_v = PyLong_AsInt(key);
- if (key_v == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "Key of options dict should be a CompressionParameter attribute.");
+ if (key_v == ZSTD_c_compressionLevel) {
+ if (_zstd_set_c_level(self, value_v) < 0) {
return -1;
}
-
- // TODO(emmatyping): check bounds when there is a value error here for better
- // error message?
- int value_v = PyLong_AsInt(value);
- if (value_v == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "Value of option dict should be an int.");
- return -1;
+ continue;
+ }
+ if (key_v == ZSTD_c_nbWorkers) {
+ /* From the zstd library docs:
+ 1. When nbWorkers >= 1, triggers asynchronous mode when
+ used with ZSTD_compressStream2().
+ 2, Default value is `0`, aka "single-threaded mode" : no
+ worker is spawned, compression is performed inside
+ caller's thread, all invocations are blocking. */
+ if (value_v != 0) {
+ self->use_multithread = 1;
}
+ }
- if (key_v == ZSTD_c_compressionLevel) {
- /* Save for generating ZSTD_CDICT */
- self->compression_level = value_v;
- }
- else if (key_v == ZSTD_c_nbWorkers) {
- /* From zstd library doc:
- 1. When nbWorkers >= 1, triggers asynchronous mode when
- used with ZSTD_compressStream2().
- 2, Default value is `0`, aka "single-threaded mode" : no
- worker is spawned, compression is performed inside
- caller's thread, all invocations are blocking. */
- if (value_v != 0) {
- self->use_multithread = 1;
- }
- }
+ /* Set parameter to compression context */
+ size_t zstd_ret = ZSTD_CCtx_setParameter(self->cctx, key_v, value_v);
- /* Set parameter to compression context */
- zstd_ret = ZSTD_CCtx_setParameter(self->cctx, key_v, value_v);
- if (ZSTD_isError(zstd_ret)) {
- set_parameter_error(mod_state, 1, key_v, value_v);
- return -1;
- }
+ /* Check error */
+ if (ZSTD_isError(zstd_ret)) {
+ set_parameter_error(1, key_v, value_v);
+ return -1;
}
- return 0;
}
- PyErr_Format(PyExc_TypeError, "Invalid type for %s. Expected %s", arg_name, arg_type);
- return -1;
+ return 0;
}
static void
@@ -130,12 +161,12 @@ capsule_free_cdict(PyObject *capsule)
ZSTD_CDict *
_get_CDict(ZstdDict *self, int compressionLevel)
{
+ assert(PyMutex_IsLocked(&self->lock));
PyObject *level = NULL;
- PyObject *capsule;
+ PyObject *capsule = NULL;
ZSTD_CDict *cdict;
+ int ret;
- // TODO(emmatyping): refactor critical section code into a lock_held function
- Py_BEGIN_CRITICAL_SECTION(self);
/* int level object */
level = PyLong_FromLong(compressionLevel);
@@ -144,27 +175,23 @@ _get_CDict(ZstdDict *self, int compressionLevel)
}
/* Get PyCapsule object from self->c_dicts */
- capsule = PyDict_GetItemWithError(self->c_dicts, level);
+ ret = PyDict_GetItemRef(self->c_dicts, level, &capsule);
+ if (ret < 0) {
+ goto error;
+ }
if (capsule == NULL) {
- if (PyErr_Occurred()) {
- goto error;
- }
-
/* Create ZSTD_CDict instance */
- char *dict_buffer = PyBytes_AS_STRING(self->dict_content);
- Py_ssize_t dict_len = Py_SIZE(self->dict_content);
Py_BEGIN_ALLOW_THREADS
- cdict = ZSTD_createCDict(dict_buffer,
- dict_len,
+ cdict = ZSTD_createCDict(self->dict_buffer, self->dict_len,
compressionLevel);
Py_END_ALLOW_THREADS
if (cdict == NULL) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state != NULL) {
PyErr_SetString(mod_state->ZstdError,
- "Failed to create ZSTD_CDict instance from zstd "
- "dictionary content. Maybe the content is corrupted.");
+ "Failed to create a ZSTD_CDict instance from "
+ "Zstandard dictionary content.");
}
goto error;
}
@@ -177,11 +204,10 @@ _get_CDict(ZstdDict *self, int compressionLevel)
}
/* Add PyCapsule object to self->c_dicts */
- if (PyDict_SetItem(self->c_dicts, level, capsule) < 0) {
- Py_DECREF(capsule);
+ ret = PyDict_SetItem(self->c_dicts, level, capsule);
+ if (ret < 0) {
goto error;
}
- Py_DECREF(capsule);
}
else {
/* ZSTD_CDict instance already exists */
@@ -193,15 +219,52 @@ error:
cdict = NULL;
success:
Py_XDECREF(level);
- Py_END_CRITICAL_SECTION();
+ Py_XDECREF(capsule);
return cdict;
}
static int
-_zstd_load_c_dict(ZstdCompressor *self, PyObject *dict) {
-
+_zstd_load_impl(ZstdCompressor *self, ZstdDict *zd,
+ _zstd_state *mod_state, int type)
+{
size_t zstd_ret;
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ if (type == DICT_TYPE_DIGESTED) {
+ /* Get ZSTD_CDict */
+ ZSTD_CDict *c_dict = _get_CDict(zd, self->compression_level);
+ if (c_dict == NULL) {
+ return -1;
+ }
+ /* Reference a prepared dictionary.
+ It overrides some compression context's parameters. */
+ zstd_ret = ZSTD_CCtx_refCDict(self->cctx, c_dict);
+ }
+ else if (type == DICT_TYPE_UNDIGESTED) {
+ /* Load a dictionary.
+ It doesn't override compression context's parameters. */
+ zstd_ret = ZSTD_CCtx_loadDictionary(self->cctx, zd->dict_buffer,
+ zd->dict_len);
+ }
+ else if (type == DICT_TYPE_PREFIX) {
+ /* Load a prefix */
+ zstd_ret = ZSTD_CCtx_refPrefix(self->cctx, zd->dict_buffer,
+ zd->dict_len);
+ }
+ else {
+ Py_UNREACHABLE();
+ }
+
+ /* Check error */
+ if (ZSTD_isError(zstd_ret)) {
+ set_zstd_error(mod_state, ERR_LOAD_C_DICT, zstd_ret);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+_zstd_load_c_dict(ZstdCompressor *self, PyObject *dict)
+{
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state == NULL) {
return -1;
}
@@ -217,7 +280,10 @@ _zstd_load_c_dict(ZstdCompressor *self, PyObject *dict) {
/* When compressing, use undigested dictionary by default. */
zd = (ZstdDict*)dict;
type = DICT_TYPE_UNDIGESTED;
- goto load;
+ PyMutex_Lock(&zd->lock);
+ ret = _zstd_load_impl(self, zd, mod_state, type);
+ PyMutex_Unlock(&zd->lock);
+ return ret;
}
/* Check (ZstdDict, type) */
@@ -231,13 +297,16 @@ _zstd_load_c_dict(ZstdCompressor *self, PyObject *dict) {
else if (ret > 0) {
/* type == -1 may indicate an error. */
type = PyLong_AsInt(PyTuple_GET_ITEM(dict, 1));
- if (type == DICT_TYPE_DIGESTED ||
- type == DICT_TYPE_UNDIGESTED ||
- type == DICT_TYPE_PREFIX)
+ if (type == DICT_TYPE_DIGESTED
+ || type == DICT_TYPE_UNDIGESTED
+ || type == DICT_TYPE_PREFIX)
{
assert(type >= 0);
zd = (ZstdDict*)PyTuple_GET_ITEM(dict, 0);
- goto load;
+ PyMutex_Lock(&zd->lock);
+ ret = _zstd_load_impl(self, zd, mod_state, type);
+ PyMutex_Unlock(&zd->lock);
+ return ret;
}
}
}
@@ -246,73 +315,42 @@ _zstd_load_c_dict(ZstdCompressor *self, PyObject *dict) {
PyErr_SetString(PyExc_TypeError,
"zstd_dict argument should be ZstdDict object.");
return -1;
+}
-load:
- if (type == DICT_TYPE_DIGESTED) {
- /* Get ZSTD_CDict */
- ZSTD_CDict *c_dict = _get_CDict(zd, self->compression_level);
- if (c_dict == NULL) {
- return -1;
- }
- /* Reference a prepared dictionary.
- It overrides some compression context's parameters. */
- Py_BEGIN_CRITICAL_SECTION(self);
- zstd_ret = ZSTD_CCtx_refCDict(self->cctx, c_dict);
- Py_END_CRITICAL_SECTION();
- }
- else if (type == DICT_TYPE_UNDIGESTED) {
- /* Load a dictionary.
- It doesn't override compression context's parameters. */
- Py_BEGIN_CRITICAL_SECTION2(self, zd);
- zstd_ret = ZSTD_CCtx_loadDictionary(
- self->cctx,
- PyBytes_AS_STRING(zd->dict_content),
- Py_SIZE(zd->dict_content));
- Py_END_CRITICAL_SECTION2();
- }
- else if (type == DICT_TYPE_PREFIX) {
- /* Load a prefix */
- Py_BEGIN_CRITICAL_SECTION2(self, zd);
- zstd_ret = ZSTD_CCtx_refPrefix(
- self->cctx,
- PyBytes_AS_STRING(zd->dict_content),
- Py_SIZE(zd->dict_content));
- Py_END_CRITICAL_SECTION2();
- }
- else {
- Py_UNREACHABLE();
- }
+/*[clinic input]
+@classmethod
+_zstd.ZstdCompressor.__new__ as _zstd_ZstdCompressor_new
+ level: object = None
+ The compression level to use. Defaults to COMPRESSION_LEVEL_DEFAULT.
+ options: object = None
+ A dict object that contains advanced compression parameters.
+ zstd_dict: object = None
+ A ZstdDict object, a pre-trained Zstandard dictionary.
- /* Check error */
- if (ZSTD_isError(zstd_ret)) {
- set_zstd_error(mod_state, ERR_LOAD_C_DICT, zstd_ret);
- return -1;
- }
- return 0;
-}
+Create a compressor object for compressing data incrementally.
-#define clinic_state() (get_zstd_state_from_type(type))
-#include "clinic/compressor.c.h"
-#undef clinic_state
+Thread-safe at method level. For one-shot compression, use the compress()
+function instead.
+[clinic start generated code]*/
static PyObject *
-_zstd_ZstdCompressor_new(PyTypeObject *type, PyObject *Py_UNUSED(args), PyObject *Py_UNUSED(kwargs))
+_zstd_ZstdCompressor_new_impl(PyTypeObject *type, PyObject *level,
+ PyObject *options, PyObject *zstd_dict)
+/*[clinic end generated code: output=cdef61eafecac3d7 input=92de0211ae20ffdc]*/
{
- ZstdCompressor *self;
- self = PyObject_GC_New(ZstdCompressor, type);
+ ZstdCompressor* self = PyObject_GC_New(ZstdCompressor, type);
if (self == NULL) {
goto error;
}
- self->inited = 0;
- self->dict = NULL;
self->use_multithread = 0;
-
+ self->dict = NULL;
+ self->lock = (PyMutex){0};
/* Compression context */
self->cctx = ZSTD_createCCtx();
if (self->cctx == NULL) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state != NULL) {
PyErr_SetString(mod_state->ZstdError,
"Unable to create ZSTD_CCtx instance.");
@@ -323,12 +361,56 @@ _zstd_ZstdCompressor_new(PyTypeObject *type, PyObject *Py_UNUSED(args), PyObject
/* Last mode */
self->last_mode = ZSTD_e_end;
+ if (level != Py_None && options != Py_None) {
+ PyErr_SetString(PyExc_TypeError,
+ "Only one of level or options should be used.");
+ goto error;
+ }
+
+ /* Set compression level */
+ if (level != Py_None) {
+ if (!PyLong_Check(level)) {
+ PyErr_SetString(PyExc_TypeError,
+ "invalid type for level, expected int");
+ goto error;
+ }
+ int level_v = PyLong_AsInt(level);
+ if (level_v == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
+ PyErr_Format(PyExc_ValueError,
+ "illegal compression level; the valid range is [%d, %d]",
+ ZSTD_minCLevel(), ZSTD_maxCLevel());
+ }
+ goto error;
+ }
+ if (_zstd_set_c_level(self, level_v) < 0) {
+ goto error;
+ }
+ }
+
+ /* Set options dictionary */
+ if (options != Py_None) {
+ if (_zstd_set_c_parameters(self, options) < 0) {
+ goto error;
+ }
+ }
+
+ /* Load Zstandard dictionary to compression context */
+ if (zstd_dict != Py_None) {
+ if (_zstd_load_c_dict(self, zstd_dict) < 0) {
+ goto error;
+ }
+ Py_INCREF(zstd_dict);
+ self->dict = zstd_dict;
+ }
+
+ // We can only start GC tracking once self->dict is set.
+ PyObject_GC_Track(self);
+
return (PyObject*)self;
error:
- if (self != NULL) {
- PyObject_GC_Del(self);
- }
+ Py_XDECREF(self);
return NULL;
}
@@ -340,7 +422,11 @@ ZstdCompressor_dealloc(PyObject *ob)
PyObject_GC_UnTrack(self);
/* Free compression context */
- ZSTD_freeCCtx(self->cctx);
+ if (self->cctx) {
+ ZSTD_freeCCtx(self->cctx);
+ }
+
+ assert(!PyMutex_IsLocked(&self->lock));
/* Py_XDECREF the dict after free the compression context */
Py_CLEAR(self->dict);
@@ -350,72 +436,11 @@ ZstdCompressor_dealloc(PyObject *ob)
Py_DECREF(tp);
}
-/*[clinic input]
-_zstd.ZstdCompressor.__init__
-
- level: object = None
- The compression level to use, defaults to ZSTD_CLEVEL_DEFAULT.
- options: object = None
- A dict object that contains advanced compression parameters.
- zstd_dict: object = None
- A ZstdDict object, a pre-trained zstd dictionary.
-
-Create a compressor object for compressing data incrementally.
-
-Thread-safe at method level. For one-shot compression, use the compress()
-function instead.
-[clinic start generated code]*/
-
-static int
-_zstd_ZstdCompressor___init___impl(ZstdCompressor *self, PyObject *level,
- PyObject *options, PyObject *zstd_dict)
-/*[clinic end generated code: output=215e6c4342732f96 input=9f79b0d8d34c8ef0]*/
-{
- /* Only called once */
- if (self->inited) {
- PyErr_SetString(PyExc_RuntimeError, init_twice_msg);
- return -1;
- }
- self->inited = 1;
-
- if (level != Py_None && options != Py_None) {
- PyErr_SetString(PyExc_RuntimeError, "Only one of level or options should be used.");
- return -1;
- }
-
- /* Set compressLevel/options to compression context */
- if (level != Py_None) {
- if (_zstd_set_c_parameters(self, level, "level", "int") < 0) {
- return -1;
- }
- }
-
- if (options != Py_None) {
- if (_zstd_set_c_parameters(self, options, "options", "dict") < 0) {
- return -1;
- }
- }
-
- /* Load dictionary to compression context */
- if (zstd_dict != Py_None) {
- if (_zstd_load_c_dict(self, zstd_dict) < 0) {
- return -1;
- }
-
- /* Py_INCREF the dict */
- Py_INCREF(zstd_dict);
- self->dict = zstd_dict;
- }
-
- // We can only start tracking self with the GC once self->dict is set.
- PyObject_GC_Track(self);
- return 0;
-}
-
-PyObject *
-compress_impl(ZstdCompressor *self, Py_buffer *data,
- ZSTD_EndDirective end_directive)
+static PyObject *
+compress_lock_held(ZstdCompressor *self, Py_buffer *data,
+ ZSTD_EndDirective end_directive)
{
+ assert(PyMutex_IsLocked(&self->lock));
ZSTD_inBuffer in;
ZSTD_outBuffer out;
_BlocksOutputBuffer buffer = {.list = NULL};
@@ -442,12 +467,12 @@ compress_impl(ZstdCompressor *self, Py_buffer *data,
}
if (_OutputBuffer_InitWithSize(&buffer, &out, -1,
- (Py_ssize_t) output_buffer_size) < 0) {
+ (Py_ssize_t) output_buffer_size) < 0) {
goto error;
}
- /* zstd stream compress */
+ /* Zstandard stream compress */
while (1) {
Py_BEGIN_ALLOW_THREADS
zstd_ret = ZSTD_compressStream2(self->cctx, &out, &in, end_directive);
@@ -455,7 +480,7 @@ compress_impl(ZstdCompressor *self, Py_buffer *data,
/* Check error */
if (ZSTD_isError(zstd_ret)) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state != NULL) {
set_zstd_error(mod_state, ERR_COMPRESS, zstd_ret);
}
@@ -487,9 +512,18 @@ error:
return NULL;
}
+#ifndef NDEBUG
+static inline int
+mt_continue_should_break(ZSTD_inBuffer *in, ZSTD_outBuffer *out)
+{
+ return in->size == in->pos && out->size != out->pos;
+}
+#endif
+
static PyObject *
-compress_mt_continue_impl(ZstdCompressor *self, Py_buffer *data)
+compress_mt_continue_lock_held(ZstdCompressor *self, Py_buffer *data)
{
+ assert(PyMutex_IsLocked(&self->lock));
ZSTD_inBuffer in;
ZSTD_outBuffer out;
_BlocksOutputBuffer buffer = {.list = NULL};
@@ -505,24 +539,27 @@ compress_mt_continue_impl(ZstdCompressor *self, Py_buffer *data)
goto error;
}
- /* zstd stream compress */
+ /* Zstandard stream compress */
while (1) {
Py_BEGIN_ALLOW_THREADS
do {
- zstd_ret = ZSTD_compressStream2(self->cctx, &out, &in, ZSTD_e_continue);
- } while (out.pos != out.size && in.pos != in.size && !ZSTD_isError(zstd_ret));
+ zstd_ret = ZSTD_compressStream2(self->cctx, &out, &in,
+ ZSTD_e_continue);
+ } while (out.pos != out.size
+ && in.pos != in.size
+ && !ZSTD_isError(zstd_ret));
Py_END_ALLOW_THREADS
/* Check error */
if (ZSTD_isError(zstd_ret)) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state != NULL) {
set_zstd_error(mod_state, ERR_COMPRESS, zstd_ret);
}
goto error;
}
- /* Like compress_impl(), output as much as possible. */
+ /* Like compress_lock_held(), output as much as possible. */
if (out.pos == out.size) {
if (_OutputBuffer_Grow(&buffer, &out) < 0) {
goto error;
@@ -581,14 +618,14 @@ _zstd_ZstdCompressor_compress_impl(ZstdCompressor *self, Py_buffer *data,
}
/* Thread-safe code */
- Py_BEGIN_CRITICAL_SECTION(self);
+ PyMutex_Lock(&self->lock);
/* Compress */
if (self->use_multithread && mode == ZSTD_e_continue) {
- ret = compress_mt_continue_impl(self, data);
+ ret = compress_mt_continue_lock_held(self, data);
}
else {
- ret = compress_impl(self, data, mode);
+ ret = compress_lock_held(self, data, mode);
}
if (ret) {
@@ -600,7 +637,7 @@ _zstd_ZstdCompressor_compress_impl(ZstdCompressor *self, Py_buffer *data,
/* Resetting cctx's session never fail */
ZSTD_CCtx_reset(self->cctx, ZSTD_reset_session_only);
}
- Py_END_CRITICAL_SECTION();
+ PyMutex_Unlock(&self->lock);
return ret;
}
@@ -614,14 +651,14 @@ _zstd.ZstdCompressor.flush
Finish the compression process.
-Flush any remaining data left in internal buffers. Since zstd data consists
-of one or more independent frames, the compressor object can still be used
-after this method is called.
+Flush any remaining data left in internal buffers. Since Zstandard data
+consists of one or more independent frames, the compressor object can still
+be used after this method is called.
[clinic start generated code]*/
static PyObject *
_zstd_ZstdCompressor_flush_impl(ZstdCompressor *self, int mode)
-/*[clinic end generated code: output=b7cf2c8d64dcf2e3 input=a766870301932b85]*/
+/*[clinic end generated code: output=b7cf2c8d64dcf2e3 input=0ab19627f323cdbc]*/
{
PyObject *ret;
@@ -635,8 +672,9 @@ _zstd_ZstdCompressor_flush_impl(ZstdCompressor *self, int mode)
}
/* Thread-safe code */
- Py_BEGIN_CRITICAL_SECTION(self);
- ret = compress_impl(self, NULL, mode);
+ PyMutex_Lock(&self->lock);
+
+ ret = compress_lock_held(self, NULL, mode);
if (ret) {
self->last_mode = mode;
@@ -647,7 +685,7 @@ _zstd_ZstdCompressor_flush_impl(ZstdCompressor *self, int mode)
/* Resetting cctx's session never fail */
ZSTD_CCtx_reset(self->cctx, ZSTD_reset_session_only);
}
- Py_END_CRITICAL_SECTION();
+ PyMutex_Unlock(&self->lock);
return ret;
}
@@ -655,20 +693,19 @@ _zstd_ZstdCompressor_flush_impl(ZstdCompressor *self, int mode)
static PyMethodDef ZstdCompressor_methods[] = {
_ZSTD_ZSTDCOMPRESSOR_COMPRESS_METHODDEF
_ZSTD_ZSTDCOMPRESSOR_FLUSH_METHODDEF
-
- {0}
+ {NULL, NULL}
};
PyDoc_STRVAR(ZstdCompressor_last_mode_doc,
"The last mode used to this compressor object, its value can be .CONTINUE,\n"
".FLUSH_BLOCK, .FLUSH_FRAME. Initialized to .FLUSH_FRAME.\n\n"
-"It can be used to get the current state of a compressor, such as, data flushed,\n"
-"a frame ended.");
+"It can be used to get the current state of a compressor, such as, data\n"
+"flushed, or a frame ended.");
static PyMemberDef ZstdCompressor_members[] = {
{"last_mode", Py_T_INT, offsetof(ZstdCompressor, last_mode),
- Py_READONLY, ZstdCompressor_last_mode_doc},
- {0}
+ Py_READONLY, ZstdCompressor_last_mode_doc},
+ {NULL}
};
static int
@@ -690,18 +727,20 @@ ZstdCompressor_clear(PyObject *ob)
static PyType_Slot zstdcompressor_slots[] = {
{Py_tp_new, _zstd_ZstdCompressor_new},
{Py_tp_dealloc, ZstdCompressor_dealloc},
- {Py_tp_init, _zstd_ZstdCompressor___init__},
{Py_tp_methods, ZstdCompressor_methods},
{Py_tp_members, ZstdCompressor_members},
- {Py_tp_doc, (char*)_zstd_ZstdCompressor___init____doc__},
+ {Py_tp_doc, (void *)_zstd_ZstdCompressor_new__doc__},
{Py_tp_traverse, ZstdCompressor_traverse},
{Py_tp_clear, ZstdCompressor_clear},
- {0}
+ {0, 0}
};
PyType_Spec zstd_compressor_type_spec = {
- .name = "_zstd.ZstdCompressor",
+ .name = "compression.zstd.ZstdCompressor",
.basicsize = sizeof(ZstdCompressor),
+ // Py_TPFLAGS_IMMUTABLETYPE is not used here as several
+ // associated constants need to be added to the type.
+ // PyType_Freeze is called later to set the flag.
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.slots = zstdcompressor_slots,
};
diff --git a/Modules/_zstd/decompressor.c b/Modules/_zstd/decompressor.c
index d141e68efde..26e568cf433 100644
--- a/Modules/_zstd/decompressor.c
+++ b/Modules/_zstd/decompressor.c
@@ -1,31 +1,64 @@
-/*
-Low level interface to Meta's zstd library for use in the compression.zstd
-Python module.
-*/
+/* Low level interface to the Zstandard algorthm & the zstd library. */
/* ZstdDecompressor class definition */
/*[clinic input]
module _zstd
-class _zstd.ZstdDecompressor "ZstdDecompressor *" "clinic_state()->ZstdDecompressor_type"
+class _zstd.ZstdDecompressor "ZstdDecompressor *" "&zstd_decompressor_type_spec"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4e6eae327c0c0c76]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e2969ddf48a203e0]*/
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
-#include "_zstdmodule.h"
+#include "Python.h"
+#include "_zstdmodule.h"
#include "buffer.h"
+#include "zstddict.h"
+#include "internal/pycore_lock.h" // PyMutex_IsLocked
+#include <stdbool.h> // bool
#include <stddef.h> // offsetof()
+#include <zstd.h> // ZSTD_*()
+
+typedef struct {
+ PyObject_HEAD
+
+ /* Decompression context */
+ ZSTD_DCtx *dctx;
+
+ /* ZstdDict object in use */
+ PyObject *dict;
+
+ /* Unconsumed input data */
+ char *input_buffer;
+ size_t input_buffer_size;
+ size_t in_begin, in_end;
+
+ /* Unused data */
+ PyObject *unused_data;
+
+ /* 0 if decompressor has (or may has) unconsumed input data, 0 or 1. */
+ bool needs_input;
+
+ /* For ZstdDecompressor, 0 or 1.
+ 1 means the end of the first frame has been reached. */
+ bool eof;
+
+ /* Lock to protect the decompression context */
+ PyMutex lock;
+} ZstdDecompressor;
#define ZstdDecompressor_CAST(op) ((ZstdDecompressor *)op)
+#include "clinic/decompressor.c.h"
+
static inline ZSTD_DDict *
_get_DDict(ZstdDict *self)
{
+ assert(PyMutex_IsLocked(&self->lock));
ZSTD_DDict *ret;
/* Already created */
@@ -33,98 +66,122 @@ _get_DDict(ZstdDict *self)
return self->d_dict;
}
- Py_BEGIN_CRITICAL_SECTION(self);
if (self->d_dict == NULL) {
/* Create ZSTD_DDict instance from dictionary content */
- char *dict_buffer = PyBytes_AS_STRING(self->dict_content);
- Py_ssize_t dict_len = Py_SIZE(self->dict_content);
Py_BEGIN_ALLOW_THREADS
- self->d_dict = ZSTD_createDDict(dict_buffer,
- dict_len);
+ ret = ZSTD_createDDict(self->dict_buffer, self->dict_len);
Py_END_ALLOW_THREADS
+ self->d_dict = ret;
if (self->d_dict == NULL) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state != NULL) {
PyErr_SetString(mod_state->ZstdError,
- "Failed to create ZSTD_DDict instance from zstd "
- "dictionary content. Maybe the content is corrupted.");
+ "Failed to create a ZSTD_DDict instance from "
+ "Zstandard dictionary content.");
}
}
}
- /* Don't lose any exception */
- ret = self->d_dict;
- Py_END_CRITICAL_SECTION();
-
- return ret;
+ return self->d_dict;
}
-/* Set decompression parameters to decompression context */
static int
_zstd_set_d_parameters(ZstdDecompressor *self, PyObject *options)
{
- size_t zstd_ret;
- PyObject *key, *value;
- Py_ssize_t pos;
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state == NULL) {
return -1;
}
if (!PyDict_Check(options)) {
- PyErr_SetString(PyExc_TypeError,
- "options argument should be dict object.");
+ PyErr_Format(PyExc_TypeError,
+ "ZstdDecompressor() argument 'options' must be dict, not %T",
+ options);
return -1;
}
- pos = 0;
+ Py_ssize_t pos = 0;
+ PyObject *key, *value;
while (PyDict_Next(options, &pos, &key, &value)) {
/* Check key type */
if (Py_TYPE(key) == mod_state->CParameter_type) {
PyErr_SetString(PyExc_TypeError,
- "Key of decompression options dict should "
- "NOT be CompressionParameter.");
+ "compression options dictionary key must not be a "
+ "CompressionParameter attribute");
return -1;
}
- /* Both key & value should be 32-bit signed int */
+ Py_INCREF(key);
+ Py_INCREF(value);
int key_v = PyLong_AsInt(key);
+ Py_DECREF(key);
if (key_v == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "Key of options dict should be a DecompressionParameter attribute.");
return -1;
}
- // TODO(emmatyping): check bounds when there is a value error here for better
- // error message?
int value_v = PyLong_AsInt(value);
+ Py_DECREF(value);
if (value_v == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_ValueError,
- "Value of options dict should be an int.");
return -1;
}
/* Set parameter to compression context */
- Py_BEGIN_CRITICAL_SECTION(self);
- zstd_ret = ZSTD_DCtx_setParameter(self->dctx, key_v, value_v);
- Py_END_CRITICAL_SECTION();
+ size_t zstd_ret = ZSTD_DCtx_setParameter(self->dctx, key_v, value_v);
/* Check error */
if (ZSTD_isError(zstd_ret)) {
- set_parameter_error(mod_state, 0, key_v, value_v);
+ set_parameter_error(0, key_v, value_v);
return -1;
}
}
return 0;
}
+static int
+_zstd_load_impl(ZstdDecompressor *self, ZstdDict *zd,
+ _zstd_state *mod_state, int type)
+{
+ size_t zstd_ret;
+ if (type == DICT_TYPE_DIGESTED) {
+ /* Get ZSTD_DDict */
+ ZSTD_DDict *d_dict = _get_DDict(zd);
+ if (d_dict == NULL) {
+ return -1;
+ }
+ /* Reference a prepared dictionary */
+ zstd_ret = ZSTD_DCtx_refDDict(self->dctx, d_dict);
+ }
+ else if (type == DICT_TYPE_UNDIGESTED) {
+ /* Load a dictionary */
+ zstd_ret = ZSTD_DCtx_loadDictionary(self->dctx, zd->dict_buffer,
+ zd->dict_len);
+ }
+ else if (type == DICT_TYPE_PREFIX) {
+ /* Load a prefix */
+ zstd_ret = ZSTD_DCtx_refPrefix(self->dctx, zd->dict_buffer,
+ zd->dict_len);
+ }
+ else {
+ /* Impossible code path */
+ PyErr_SetString(PyExc_SystemError,
+ "load_d_dict() impossible code path");
+ return -1;
+ }
+
+ /* Check error */
+ if (ZSTD_isError(zstd_ret)) {
+ set_zstd_error(mod_state, ERR_LOAD_D_DICT, zstd_ret);
+ return -1;
+ }
+ return 0;
+}
+
/* Load dictionary or prefix to decompression context */
static int
_zstd_load_d_dict(ZstdDecompressor *self, PyObject *dict)
{
- size_t zstd_ret;
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state == NULL) {
return -1;
}
@@ -140,7 +197,10 @@ _zstd_load_d_dict(ZstdDecompressor *self, PyObject *dict)
/* When decompressing, use digested dictionary by default. */
zd = (ZstdDict*)dict;
type = DICT_TYPE_DIGESTED;
- goto load;
+ PyMutex_Lock(&zd->lock);
+ ret = _zstd_load_impl(self, zd, mod_state, type);
+ PyMutex_Unlock(&zd->lock);
+ return ret;
}
/* Check (ZstdDict, type) */
@@ -154,13 +214,16 @@ _zstd_load_d_dict(ZstdDecompressor *self, PyObject *dict)
else if (ret > 0) {
/* type == -1 may indicate an error. */
type = PyLong_AsInt(PyTuple_GET_ITEM(dict, 1));
- if (type == DICT_TYPE_DIGESTED ||
- type == DICT_TYPE_UNDIGESTED ||
- type == DICT_TYPE_PREFIX)
+ if (type == DICT_TYPE_DIGESTED
+ || type == DICT_TYPE_UNDIGESTED
+ || type == DICT_TYPE_PREFIX)
{
assert(type >= 0);
zd = (ZstdDict*)PyTuple_GET_ITEM(dict, 0);
- goto load;
+ PyMutex_Lock(&zd->lock);
+ ret = _zstd_load_impl(self, zd, mod_state, type);
+ PyMutex_Unlock(&zd->lock);
+ return ret;
}
}
}
@@ -169,68 +232,15 @@ _zstd_load_d_dict(ZstdDecompressor *self, PyObject *dict)
PyErr_SetString(PyExc_TypeError,
"zstd_dict argument should be ZstdDict object.");
return -1;
-
-load:
- if (type == DICT_TYPE_DIGESTED) {
- /* Get ZSTD_DDict */
- ZSTD_DDict *d_dict = _get_DDict(zd);
- if (d_dict == NULL) {
- return -1;
- }
- /* Reference a prepared dictionary */
- Py_BEGIN_CRITICAL_SECTION(self);
- zstd_ret = ZSTD_DCtx_refDDict(self->dctx, d_dict);
- Py_END_CRITICAL_SECTION();
- }
- else if (type == DICT_TYPE_UNDIGESTED) {
- /* Load a dictionary */
- Py_BEGIN_CRITICAL_SECTION2(self, zd);
- zstd_ret = ZSTD_DCtx_loadDictionary(
- self->dctx,
- PyBytes_AS_STRING(zd->dict_content),
- Py_SIZE(zd->dict_content));
- Py_END_CRITICAL_SECTION2();
- }
- else if (type == DICT_TYPE_PREFIX) {
- /* Load a prefix */
- Py_BEGIN_CRITICAL_SECTION2(self, zd);
- zstd_ret = ZSTD_DCtx_refPrefix(
- self->dctx,
- PyBytes_AS_STRING(zd->dict_content),
- Py_SIZE(zd->dict_content));
- Py_END_CRITICAL_SECTION2();
- }
- else {
- /* Impossible code path */
- PyErr_SetString(PyExc_SystemError,
- "load_d_dict() impossible code path");
- return -1;
- }
-
- /* Check error */
- if (ZSTD_isError(zstd_ret)) {
- set_zstd_error(mod_state, ERR_LOAD_D_DICT, zstd_ret);
- return -1;
- }
- return 0;
}
-
-
/*
- Given the two types of decompressors (defined in _zstdmodule.h):
-
- typedef enum {
- TYPE_DECOMPRESSOR, // <D>, ZstdDecompressor class
- TYPE_ENDLESS_DECOMPRESSOR, // <E>, decompress() function
- } decompress_type;
-
- Decompress implementation for <D>, <E>, pseudo code:
+ Decompress implementation in pseudo code:
initialize_output_buffer
while True:
decompress_data
- set_object_flag # .eof for <D>, .at_frame_edge for <E>.
+ set_object_flag # .eof
if output_buffer_exhausted:
if output_buffer_reached_max_length:
@@ -240,76 +250,26 @@ load:
finish
ZSTD_decompressStream()'s size_t return value:
- - 0 when a frame is completely decoded and fully flushed, zstd's internal
- buffer has no data.
+ - 0 when a frame is completely decoded and fully flushed,
+ zstd's internal buffer has no data.
- An error code, which can be tested using ZSTD_isError().
- Or any other value > 0, which means there is still some decoding or
flushing to do to complete current frame.
Note, decompressing "an empty input" in any case will make it > 0.
-
- <E> supports multiple frames, has an .at_frame_edge flag, it means both the
- input and output streams are at a frame edge. The flag can be set by this
- statement:
-
- .at_frame_edge = (zstd_ret == 0) ? 1 : 0
-
- But if decompressing "an empty input" at "a frame edge", zstd_ret will be
- non-zero, then .at_frame_edge will be wrongly set to false. To solve this
- problem, two AFE checks are needed to ensure that: when at "a frame edge",
- empty input will not be decompressed.
-
- // AFE check
- if (self->at_frame_edge && in->pos == in->size) {
- finish
- }
-
- In <E>, if .at_frame_edge is eventually set to true, but input stream has
- unconsumed data (in->pos < in->size), then the outer function
- stream_decompress() will set .at_frame_edge to false. In this case,
- although the output stream is at a frame edge, for the caller, the input
- stream is not at a frame edge, see below diagram. This behavior does not
- affect the next AFE check, since (in->pos < in->size).
-
- input stream: --------------|---
- ^
- output stream: ====================|
- ^
*/
-PyObject *
-decompress_impl(ZstdDecompressor *self, ZSTD_inBuffer *in,
- Py_ssize_t max_length,
- Py_ssize_t initial_size,
- decompress_type type)
+static PyObject *
+decompress_lock_held(ZstdDecompressor *self, ZSTD_inBuffer *in,
+ Py_ssize_t max_length)
{
size_t zstd_ret;
ZSTD_outBuffer out;
_BlocksOutputBuffer buffer = {.list = NULL};
PyObject *ret;
- /* The first AFE check for setting .at_frame_edge flag */
- if (type == TYPE_ENDLESS_DECOMPRESSOR) {
- if (self->at_frame_edge && in->pos == in->size) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
- if (mod_state == NULL) {
- return NULL;
- }
- ret = mod_state->empty_bytes;
- Py_INCREF(ret);
- return ret;
- }
- }
-
/* Initialize the output buffer */
- if (initial_size >= 0) {
- if (_OutputBuffer_InitWithSize(&buffer, &out, max_length, initial_size) < 0) {
- goto error;
- }
- }
- else {
- if (_OutputBuffer_InitAndGrow(&buffer, &out, max_length) < 0) {
- goto error;
- }
+ if (_OutputBuffer_InitAndGrow(&buffer, &out, max_length) < 0) {
+ goto error;
}
assert(out.pos == 0);
@@ -321,33 +281,22 @@ decompress_impl(ZstdDecompressor *self, ZSTD_inBuffer *in,
/* Check error */
if (ZSTD_isError(zstd_ret)) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state != NULL) {
set_zstd_error(mod_state, ERR_DECOMPRESS, zstd_ret);
}
goto error;
}
- /* Set .eof/.af_frame_edge flag */
- if (type == TYPE_DECOMPRESSOR) {
- /* ZstdDecompressor class stops when a frame is decompressed */
- if (zstd_ret == 0) {
- self->eof = 1;
- break;
- }
- }
- else if (type == TYPE_ENDLESS_DECOMPRESSOR) {
- /* decompress() function supports multiple frames */
- self->at_frame_edge = (zstd_ret == 0) ? 1 : 0;
-
- /* The second AFE check for setting .at_frame_edge flag */
- if (self->at_frame_edge && in->pos == in->size) {
- break;
- }
+ /* Set .eof flag */
+ if (zstd_ret == 0) {
+ /* Stop when a frame is decompressed */
+ self->eof = 1;
+ break;
}
/* Need to check out before in. Maybe zstd's internal buffer still has
- a few bytes can be output, grow the buffer and continue. */
+ a few bytes that can be output, grow the buffer and continue. */
if (out.pos == out.size) {
/* Output buffer exhausted */
@@ -380,67 +329,40 @@ error:
return NULL;
}
-void
-decompressor_reset_session(ZstdDecompressor *self,
- decompress_type type)
+static void
+decompressor_reset_session_lock_held(ZstdDecompressor *self)
{
- // TODO(emmatyping): use _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED here
- // and ensure lock is always held
+ assert(PyMutex_IsLocked(&self->lock));
/* Reset variables */
self->in_begin = 0;
self->in_end = 0;
- if (type == TYPE_DECOMPRESSOR) {
- Py_CLEAR(self->unused_data);
- }
+ Py_CLEAR(self->unused_data);
/* Reset variables in one operation */
self->needs_input = 1;
- self->at_frame_edge = 1;
self->eof = 0;
- self->_unused_char_for_align = 0;
- /* Resetting session never fail */
+ /* Resetting session is guaranteed to never fail */
ZSTD_DCtx_reset(self->dctx, ZSTD_reset_session_only);
}
-PyObject *
-stream_decompress(ZstdDecompressor *self, Py_buffer *data, Py_ssize_t max_length,
- decompress_type type)
+static PyObject *
+stream_decompress_lock_held(ZstdDecompressor *self, Py_buffer *data,
+ Py_ssize_t max_length)
{
- Py_ssize_t initial_buffer_size = -1;
+ assert(PyMutex_IsLocked(&self->lock));
ZSTD_inBuffer in;
PyObject *ret = NULL;
int use_input_buffer;
- if (type == TYPE_DECOMPRESSOR) {
- /* Check .eof flag */
- if (self->eof) {
- PyErr_SetString(PyExc_EOFError, "Already at the end of a zstd frame.");
- assert(ret == NULL);
- goto success;
- }
- }
- else if (type == TYPE_ENDLESS_DECOMPRESSOR) {
- /* Fast path for the first frame */
- if (self->at_frame_edge && self->in_begin == self->in_end) {
- /* Read decompressed size */
- uint64_t decompressed_size = ZSTD_getFrameContentSize(data->buf, data->len);
-
- /* These two zstd constants always > PY_SSIZE_T_MAX:
- ZSTD_CONTENTSIZE_UNKNOWN is (0ULL - 1)
- ZSTD_CONTENTSIZE_ERROR is (0ULL - 2)
-
- Use ZSTD_findFrameCompressedSize() to check complete frame,
- prevent allocating too much memory for small input chunk. */
-
- if (decompressed_size <= (uint64_t) PY_SSIZE_T_MAX &&
- !ZSTD_isError(ZSTD_findFrameCompressedSize(data->buf, data->len)) )
- {
- initial_buffer_size = (Py_ssize_t) decompressed_size;
- }
- }
+ /* Check .eof flag */
+ if (self->eof) {
+ PyErr_SetString(PyExc_EOFError,
+ "Already at the end of a Zstandard frame.");
+ assert(ret == NULL);
+ return NULL;
}
/* Prepare input buffer w/wo unconsumed data */
@@ -527,30 +449,18 @@ stream_decompress(ZstdDecompressor *self, Py_buffer *data, Py_ssize_t max_length
assert(in.pos == 0);
/* Decompress */
- ret = decompress_impl(self, &in,
- max_length, initial_buffer_size,
- type);
+ ret = decompress_lock_held(self, &in, max_length);
if (ret == NULL) {
goto error;
}
/* Unconsumed input data */
if (in.pos == in.size) {
- if (type == TYPE_DECOMPRESSOR) {
- if (Py_SIZE(ret) == max_length || self->eof) {
- self->needs_input = 0;
- }
- else {
- self->needs_input = 1;
- }
+ if (Py_SIZE(ret) == max_length || self->eof) {
+ self->needs_input = 0;
}
- else if (type == TYPE_ENDLESS_DECOMPRESSOR) {
- if (Py_SIZE(ret) == max_length && !self->at_frame_edge) {
- self->needs_input = 0;
- }
- else {
- self->needs_input = 1;
- }
+ else {
+ self->needs_input = 1;
}
if (use_input_buffer) {
@@ -564,15 +474,11 @@ stream_decompress(ZstdDecompressor *self, Py_buffer *data, Py_ssize_t max_length
self->needs_input = 0;
- if (type == TYPE_ENDLESS_DECOMPRESSOR) {
- self->at_frame_edge = 0;
- }
-
if (!use_input_buffer) {
/* Discard buffer if it's too small
(resizing it may needlessly copy the current contents) */
- if (self->input_buffer != NULL &&
- self->input_buffer_size < data_size)
+ if (self->input_buffer != NULL
+ && self->input_buffer_size < data_size)
{
PyMem_Free(self->input_buffer);
self->input_buffer = NULL;
@@ -600,47 +506,57 @@ stream_decompress(ZstdDecompressor *self, Py_buffer *data, Py_ssize_t max_length
}
}
- goto success;
+ return ret;
error:
/* Reset decompressor's states/session */
- decompressor_reset_session(self, type);
+ decompressor_reset_session_lock_held(self);
Py_CLEAR(ret);
-success:
-
- return ret;
+ return NULL;
}
+/*[clinic input]
+@classmethod
+_zstd.ZstdDecompressor.__new__ as _zstd_ZstdDecompressor_new
+ zstd_dict: object = None
+ A ZstdDict object, a pre-trained Zstandard dictionary.
+ options: object = None
+ A dict object that contains advanced decompression parameters.
+
+Create a decompressor object for decompressing data incrementally.
+
+Thread-safe at method level. For one-shot decompression, use the decompress()
+function instead.
+[clinic start generated code]*/
+
static PyObject *
-_zstd_ZstdDecompressor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+_zstd_ZstdDecompressor_new_impl(PyTypeObject *type, PyObject *zstd_dict,
+ PyObject *options)
+/*[clinic end generated code: output=590ca65c1102ff4a input=213daa57e3ea4062]*/
{
- ZstdDecompressor *self;
- self = PyObject_GC_New(ZstdDecompressor, type);
+ ZstdDecompressor* self = PyObject_GC_New(ZstdDecompressor, type);
if (self == NULL) {
goto error;
}
- self->inited = 0;
- self->dict = NULL;
self->input_buffer = NULL;
self->input_buffer_size = 0;
self->in_begin = -1;
self->in_end = -1;
self->unused_data = NULL;
self->eof = 0;
+ self->dict = NULL;
+ self->lock = (PyMutex){0};
/* needs_input flag */
self->needs_input = 1;
- /* at_frame_edge flag */
- self->at_frame_edge = 1;
-
/* Decompression context */
self->dctx = ZSTD_createDCtx();
if (self->dctx == NULL) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
+ _zstd_state* mod_state = PyType_GetModuleState(Py_TYPE(self));
if (mod_state != NULL) {
PyErr_SetString(mod_state->ZstdError,
"Unable to create ZSTD_DCtx instance.");
@@ -648,12 +564,29 @@ _zstd_ZstdDecompressor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
goto error;
}
+ /* Load Zstandard dictionary to decompression context */
+ if (zstd_dict != Py_None) {
+ if (_zstd_load_d_dict(self, zstd_dict) < 0) {
+ goto error;
+ }
+ Py_INCREF(zstd_dict);
+ self->dict = zstd_dict;
+ }
+
+ /* Set options dictionary */
+ if (options != Py_None) {
+ if (_zstd_set_d_parameters(self, options) < 0) {
+ goto error;
+ }
+ }
+
+ // We can only start GC tracking once self->dict is set.
+ PyObject_GC_Track(self);
+
return (PyObject*)self;
error:
- if (self != NULL) {
- PyObject_GC_Del(self);
- }
+ Py_XDECREF(self);
return NULL;
}
@@ -665,7 +598,11 @@ ZstdDecompressor_dealloc(PyObject *ob)
PyObject_GC_UnTrack(self);
/* Free decompression context */
- ZSTD_freeDCtx(self->dctx);
+ if (self->dctx) {
+ ZSTD_freeDCtx(self->dctx);
+ }
+
+ assert(!PyMutex_IsLocked(&self->lock));
/* Py_CLEAR the dict after free decompression context */
Py_CLEAR(self->dict);
@@ -682,56 +619,6 @@ ZstdDecompressor_dealloc(PyObject *ob)
}
/*[clinic input]
-_zstd.ZstdDecompressor.__init__
-
- zstd_dict: object = None
- A ZstdDict object, a pre-trained zstd dictionary.
- options: object = None
- A dict object that contains advanced decompression parameters.
-
-Create a decompressor object for decompressing data incrementally.
-
-Thread-safe at method level. For one-shot decompression, use the decompress()
-function instead.
-[clinic start generated code]*/
-
-static int
-_zstd_ZstdDecompressor___init___impl(ZstdDecompressor *self,
- PyObject *zstd_dict, PyObject *options)
-/*[clinic end generated code: output=703af2f1ec226642 input=8fd72999acc1a146]*/
-{
- /* Only called once */
- if (self->inited) {
- PyErr_SetString(PyExc_RuntimeError, init_twice_msg);
- return -1;
- }
- self->inited = 1;
-
- /* Load dictionary to decompression context */
- if (zstd_dict != Py_None) {
- if (_zstd_load_d_dict(self, zstd_dict) < 0) {
- return -1;
- }
-
- /* Py_INCREF the dict */
- Py_INCREF(zstd_dict);
- self->dict = zstd_dict;
- }
-
- /* Set option to decompression context */
- if (options != Py_None) {
- if (_zstd_set_d_parameters(self, options) < 0) {
- return -1;
- }
- }
-
- // We can only start tracking self with the GC once self->dict is set.
- PyObject_GC_Track(self);
- return 0;
-}
-
-/*[clinic input]
-@critical_section
@getter
_zstd.ZstdDecompressor.unused_data
@@ -743,20 +630,15 @@ decompressed, unused input data after the frame. Otherwise this will be b''.
static PyObject *
_zstd_ZstdDecompressor_unused_data_get_impl(ZstdDecompressor *self)
-/*[clinic end generated code: output=f3a20940f11b6b09 input=5233800bef00df04]*/
+/*[clinic end generated code: output=f3a20940f11b6b09 input=54d41ecd681a3444]*/
{
PyObject *ret;
- /* Thread-safe code */
- Py_BEGIN_CRITICAL_SECTION(self);
+ PyMutex_Lock(&self->lock);
if (!self->eof) {
- _zstd_state* const mod_state = PyType_GetModuleState(Py_TYPE(self));
- if (mod_state == NULL) {
- return NULL;
- }
- ret = mod_state->empty_bytes;
- Py_INCREF(ret);
+ PyMutex_Unlock(&self->lock);
+ return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES);
}
else {
if (self->unused_data == NULL) {
@@ -772,8 +654,7 @@ _zstd_ZstdDecompressor_unused_data_get_impl(ZstdDecompressor *self)
}
}
- Py_END_CRITICAL_SECTION();
-
+ PyMutex_Unlock(&self->lock);
return ret;
}
@@ -781,7 +662,7 @@ _zstd_ZstdDecompressor_unused_data_get_impl(ZstdDecompressor *self)
_zstd.ZstdDecompressor.decompress
data: Py_buffer
- A bytes-like object, zstd data to be decompressed.
+ A bytes-like object, Zstandard data to be decompressed.
max_length: Py_ssize_t = -1
Maximum size of returned data. When it is negative, the size of
output buffer is unlimited. When it is nonnegative, returns at
@@ -807,25 +688,19 @@ static PyObject *
_zstd_ZstdDecompressor_decompress_impl(ZstdDecompressor *self,
Py_buffer *data,
Py_ssize_t max_length)
-/*[clinic end generated code: output=a4302b3c940dbec6 input=830e455bc9a50b6e]*/
+/*[clinic end generated code: output=a4302b3c940dbec6 input=6463dfdf98091caa]*/
{
PyObject *ret;
/* Thread-safe code */
- Py_BEGIN_CRITICAL_SECTION(self);
-
- ret = stream_decompress(self, data, max_length, TYPE_DECOMPRESSOR);
- Py_END_CRITICAL_SECTION();
+ PyMutex_Lock(&self->lock);
+ ret = stream_decompress_lock_held(self, data, max_length);
+ PyMutex_Unlock(&self->lock);
return ret;
}
-#define clinic_state() (get_zstd_state_from_type(type))
-#include "clinic/decompressor.c.h"
-#undef clinic_state
-
static PyMethodDef ZstdDecompressor_methods[] = {
_ZSTD_ZSTDDECOMPRESSOR_DECOMPRESS_METHODDEF
-
- {0}
+ {NULL, NULL}
};
PyDoc_STRVAR(ZstdDecompressor_eof_doc,
@@ -833,24 +708,22 @@ PyDoc_STRVAR(ZstdDecompressor_eof_doc,
"after that, an EOFError exception will be raised.");
PyDoc_STRVAR(ZstdDecompressor_needs_input_doc,
-"If the max_length output limit in .decompress() method has been reached, and\n"
-"the decompressor has (or may has) unconsumed input data, it will be set to\n"
-"False. In this case, pass b'' to .decompress() method may output further data.");
+"If the max_length output limit in .decompress() method has been reached,\n"
+"and the decompressor has (or may has) unconsumed input data, it will be set\n"
+"to False. In this case, passing b'' to the .decompress() method may output\n"
+"further data.");
static PyMemberDef ZstdDecompressor_members[] = {
{"eof", Py_T_BOOL, offsetof(ZstdDecompressor, eof),
Py_READONLY, ZstdDecompressor_eof_doc},
-
{"needs_input", Py_T_BOOL, offsetof(ZstdDecompressor, needs_input),
Py_READONLY, ZstdDecompressor_needs_input_doc},
-
- {0}
+ {NULL}
};
static PyGetSetDef ZstdDecompressor_getset[] = {
_ZSTD_ZSTDDECOMPRESSOR_UNUSED_DATA_GETSETDEF
-
- {0}
+ {NULL}
};
static int
@@ -873,19 +746,19 @@ ZstdDecompressor_clear(PyObject *ob)
static PyType_Slot ZstdDecompressor_slots[] = {
{Py_tp_new, _zstd_ZstdDecompressor_new},
{Py_tp_dealloc, ZstdDecompressor_dealloc},
- {Py_tp_init, _zstd_ZstdDecompressor___init__},
{Py_tp_methods, ZstdDecompressor_methods},
{Py_tp_members, ZstdDecompressor_members},
{Py_tp_getset, ZstdDecompressor_getset},
- {Py_tp_doc, (char*)_zstd_ZstdDecompressor___init____doc__},
+ {Py_tp_doc, (void *)_zstd_ZstdDecompressor_new__doc__},
{Py_tp_traverse, ZstdDecompressor_traverse},
{Py_tp_clear, ZstdDecompressor_clear},
- {0}
+ {0, 0}
};
PyType_Spec zstd_decompressor_type_spec = {
- .name = "_zstd.ZstdDecompressor",
+ .name = "compression.zstd.ZstdDecompressor",
.basicsize = sizeof(ZstdDecompressor),
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE
+ | Py_TPFLAGS_HAVE_GC,
.slots = ZstdDecompressor_slots,
};
diff --git a/Modules/_zstd/zstddict.c b/Modules/_zstd/zstddict.c
index b411eadfc95..afc58b42e89 100644
--- a/Modules/_zstd/zstddict.c
+++ b/Modules/_zstd/zstddict.c
@@ -1,38 +1,68 @@
-/*
-Low level interface to Meta's zstd library for use in the compression.zstd
-Python module.
-*/
+/* Low level interface to the Zstandard algorthm & the zstd library. */
/* ZstdDict class definitions */
/*[clinic input]
module _zstd
-class _zstd.ZstdDict "ZstdDict *" "clinic_state()->ZstdDict_type"
+class _zstd.ZstdDict "ZstdDict *" "&zstd_dict_type_spec"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a5d1254c497e52ba]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3dcc175ec974f81c]*/
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
+#include "Python.h"
+
#include "_zstdmodule.h"
+#include "zstddict.h"
+#include "clinic/zstddict.c.h"
+#include "internal/pycore_lock.h" // PyMutex_IsLocked
-#include <stddef.h> // offsetof()
+#include <zstd.h> // ZSTD_freeDDict(), ZSTD_getDictID_fromDict()
#define ZstdDict_CAST(op) ((ZstdDict *)op)
+/*[clinic input]
+@classmethod
+_zstd.ZstdDict.__new__ as _zstd_ZstdDict_new
+ dict_content: Py_buffer
+ The content of a Zstandard dictionary as a bytes-like object.
+ /
+ *
+ is_raw: bool = False
+ If true, perform no checks on *dict_content*, useful for some
+ advanced cases. Otherwise, check that the content represents
+ a Zstandard dictionary created by the zstd library or CLI.
+
+Represents a Zstandard dictionary.
+
+The dictionary can be used for compression or decompression, and can be shared
+by multiple ZstdCompressor or ZstdDecompressor objects.
+[clinic start generated code]*/
+
static PyObject *
-_zstd_ZstdDict_new(PyTypeObject *type, PyObject *Py_UNUSED(args), PyObject *Py_UNUSED(kwargs))
+_zstd_ZstdDict_new_impl(PyTypeObject *type, Py_buffer *dict_content,
+ int is_raw)
+/*[clinic end generated code: output=685b7406a48b0949 input=9e8c493e31c98383]*/
{
- ZstdDict *self;
- self = PyObject_GC_New(ZstdDict, type);
+ /* All dictionaries must be at least 8 bytes */
+ if (dict_content->len < 8) {
+ PyErr_SetString(PyExc_ValueError,
+ "Zstandard dictionary content too short "
+ "(must have at least eight bytes)");
+ return NULL;
+ }
+
+ ZstdDict* self = PyObject_GC_New(ZstdDict, type);
if (self == NULL) {
- goto error;
+ return NULL;
}
- self->dict_content = NULL;
- self->inited = 0;
self->d_dict = NULL;
+ self->dict_buffer = NULL;
+ self->dict_id = 0;
+ self->lock = (PyMutex){0};
/* ZSTD_CDict dict */
self->c_dicts = PyDict_New();
@@ -40,12 +70,29 @@ _zstd_ZstdDict_new(PyTypeObject *type, PyObject *Py_UNUSED(args), PyObject *Py_U
goto error;
}
- return (PyObject*)self;
+ self->dict_buffer = PyMem_Malloc(dict_content->len);
+ if (!self->dict_buffer) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ memcpy(self->dict_buffer, dict_content->buf, dict_content->len);
+ self->dict_len = dict_content->len;
-error:
- if (self != NULL) {
- PyObject_GC_Del(self);
+ /* Get dict_id, 0 means "raw content" dictionary. */
+ self->dict_id = ZSTD_getDictID_fromDict(self->dict_buffer, self->dict_len);
+
+ /* Check validity for ordinary dictionary */
+ if (!is_raw && self->dict_id == 0) {
+ PyErr_SetString(PyExc_ValueError, "invalid Zstandard dictionary");
+ goto error;
}
+
+ PyObject_GC_Track(self);
+
+ return (PyObject *)self;
+
+error:
+ Py_XDECREF(self);
return NULL;
}
@@ -57,121 +104,64 @@ ZstdDict_dealloc(PyObject *ob)
PyObject_GC_UnTrack(self);
/* Free ZSTD_DDict instance */
- ZSTD_freeDDict(self->d_dict);
+ if (self->d_dict) {
+ ZSTD_freeDDict(self->d_dict);
+ }
+
+ assert(!PyMutex_IsLocked(&self->lock));
- /* Release dict_content after Free ZSTD_CDict/ZSTD_DDict instances */
- Py_CLEAR(self->dict_content);
+ /* Release dict_buffer after freeing ZSTD_CDict/ZSTD_DDict instances */
+ PyMem_Free(self->dict_buffer);
Py_CLEAR(self->c_dicts);
PyTypeObject *tp = Py_TYPE(self);
- PyObject_GC_Del(ob);
+ tp->tp_free(self);
Py_DECREF(tp);
}
-/*[clinic input]
-_zstd.ZstdDict.__init__
-
- dict_content: object
- A bytes-like object, dictionary's content.
- is_raw: bool = False
- This parameter is for advanced user. True means dict_content
- argument is a "raw content" dictionary, free of any format
- restriction. False means dict_content argument is an ordinary
- zstd dictionary, was created by zstd functions, follow a
- specified format.
-
-Represents a zstd dictionary, which can be used for compression/decompression.
-
-It's thread-safe, and can be shared by multiple ZstdCompressor /
-ZstdDecompressor objects.
-[clinic start generated code]*/
-
-static int
-_zstd_ZstdDict___init___impl(ZstdDict *self, PyObject *dict_content,
- int is_raw)
-/*[clinic end generated code: output=c5f5a0d8377d037c input=e6750f62a513b3ee]*/
-{
- /* Only called once */
- if (self->inited) {
- PyErr_SetString(PyExc_RuntimeError, init_twice_msg);
- return -1;
- }
- self->inited = 1;
-
- /* Check dict_content's type */
- self->dict_content = PyBytes_FromObject(dict_content);
- if (self->dict_content == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "dict_content argument should be bytes-like object.");
- return -1;
- }
-
- /* Both ordinary dictionary and "raw content" dictionary should
- at least 8 bytes */
- if (Py_SIZE(self->dict_content) < 8) {
- PyErr_SetString(PyExc_ValueError,
- "Zstd dictionary content should at least 8 bytes.");
- return -1;
- }
-
- /* Get dict_id, 0 means "raw content" dictionary. */
- self->dict_id = ZSTD_getDictID_fromDict(PyBytes_AS_STRING(self->dict_content),
- Py_SIZE(self->dict_content));
-
- /* Check validity for ordinary dictionary */
- if (!is_raw && self->dict_id == 0) {
- char *msg = "The dict_content argument is not a valid zstd "
- "dictionary. The first 4 bytes of a valid zstd dictionary "
- "should be a magic number: b'\\x37\\xA4\\x30\\xEC'.\n"
- "If you are an advanced user, and can be sure that "
- "dict_content argument is a \"raw content\" zstd "
- "dictionary, set is_raw parameter to True.";
- PyErr_SetString(PyExc_ValueError, msg);
- return -1;
- }
-
- // Can only track self once self->dict_content is included
- PyObject_GC_Track(self);
- return 0;
-}
-
-#define clinic_state() (get_zstd_state(type))
-#include "clinic/zstddict.c.h"
-#undef clinic_state
-
PyDoc_STRVAR(ZstdDict_dictid_doc,
-"ID of zstd dictionary, a 32-bit unsigned int value.\n\n"
-"Non-zero means ordinary dictionary, was created by zstd functions, follow\n"
-"a specified format.\n\n"
-"0 means a \"raw content\" dictionary, free of any format restriction, used\n"
-"for advanced user.");
-
-PyDoc_STRVAR(ZstdDict_dictcontent_doc,
-"The content of zstd dictionary, a bytes object, it's the same as dict_content\n"
-"argument in ZstdDict.__init__() method. It can be used with other programs.");
+"the Zstandard dictionary, an int between 0 and 2**32.\n\n"
+"A non-zero value represents an ordinary Zstandard dictionary, "
+"conforming to the standardised format.\n\n"
+"The special value '0' means a 'raw content' dictionary,"
+"without any restrictions on format or content.");
static PyObject *
-ZstdDict_str(PyObject *ob)
+ZstdDict_repr(PyObject *ob)
{
ZstdDict *dict = ZstdDict_CAST(ob);
return PyUnicode_FromFormat("<ZstdDict dict_id=%u dict_size=%zd>",
- dict->dict_id, Py_SIZE(dict->dict_content));
+ (unsigned int)dict->dict_id, dict->dict_len);
}
static PyMemberDef ZstdDict_members[] = {
{"dict_id", Py_T_UINT, offsetof(ZstdDict, dict_id), Py_READONLY, ZstdDict_dictid_doc},
- {"dict_content", Py_T_OBJECT_EX, offsetof(ZstdDict, dict_content), Py_READONLY, ZstdDict_dictcontent_doc},
- {0}
+ {NULL}
};
/*[clinic input]
-@critical_section
+@getter
+_zstd.ZstdDict.dict_content
+
+The content of a Zstandard dictionary, as a bytes object.
+[clinic start generated code]*/
+
+static PyObject *
+_zstd_ZstdDict_dict_content_get_impl(ZstdDict *self)
+/*[clinic end generated code: output=0d05caa5b550eabb input=4ed526d1c151c596]*/
+{
+ return PyBytes_FromStringAndSize(self->dict_buffer, self->dict_len);
+}
+
+/*[clinic input]
@getter
_zstd.ZstdDict.as_digested_dict
Load as a digested dictionary to compressor.
-Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_digested_dict)
+Pass this attribute as zstd_dict argument:
+compress(dat, zstd_dict=zd.as_digested_dict)
+
1. Some advanced compression parameters of compressor may be overridden
by parameters of digested dictionary.
2. ZstdDict has a digested dictionaries cache for each compression level.
@@ -182,19 +172,20 @@ Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_digeste
static PyObject *
_zstd_ZstdDict_as_digested_dict_get_impl(ZstdDict *self)
-/*[clinic end generated code: output=09b086e7a7320dbb input=585448c79f31f74a]*/
+/*[clinic end generated code: output=09b086e7a7320dbb input=ee45e1b4a48f6f2c]*/
{
return Py_BuildValue("Oi", self, DICT_TYPE_DIGESTED);
}
/*[clinic input]
-@critical_section
@getter
_zstd.ZstdDict.as_undigested_dict
Load as an undigested dictionary to compressor.
-Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_undigested_dict)
+Pass this attribute as zstd_dict argument:
+compress(dat, zstd_dict=zd.as_undigested_dict)
+
1. The advanced compression parameters of compressor will not be overridden.
2. Loading an undigested dictionary is costly. If load an undigested dictionary
multiple times, consider reusing a compressor object.
@@ -203,19 +194,20 @@ Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_undiges
static PyObject *
_zstd_ZstdDict_as_undigested_dict_get_impl(ZstdDict *self)
-/*[clinic end generated code: output=43c7a989e6d4253a input=022b0829ffb1c220]*/
+/*[clinic end generated code: output=43c7a989e6d4253a input=d39210eedec76fed]*/
{
return Py_BuildValue("Oi", self, DICT_TYPE_UNDIGESTED);
}
/*[clinic input]
-@critical_section
@getter
_zstd.ZstdDict.as_prefix
Load as a prefix to compressor/decompressor.
-Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_prefix)
+Pass this attribute as zstd_dict argument:
+compress(dat, zstd_dict=zd.as_prefix)
+
1. Prefix is compatible with long distance matching, while dictionary is not.
2. It only works for the first frame, then the compressor/decompressor will
return to no prefix state.
@@ -224,27 +216,24 @@ Pass this attribute as zstd_dict argument: compress(dat, zstd_dict=zd.as_prefix)
static PyObject *
_zstd_ZstdDict_as_prefix_get_impl(ZstdDict *self)
-/*[clinic end generated code: output=6f7130c356595a16 input=09fb82a6a5407e87]*/
+/*[clinic end generated code: output=6f7130c356595a16 input=d59757b0b5a9551a]*/
{
return Py_BuildValue("Oi", self, DICT_TYPE_PREFIX);
}
static PyGetSetDef ZstdDict_getset[] = {
+ _ZSTD_ZSTDDICT_DICT_CONTENT_GETSETDEF
_ZSTD_ZSTDDICT_AS_DIGESTED_DICT_GETSETDEF
-
_ZSTD_ZSTDDICT_AS_UNDIGESTED_DICT_GETSETDEF
-
_ZSTD_ZSTDDICT_AS_PREFIX_GETSETDEF
-
- {0}
+ {NULL}
};
static Py_ssize_t
ZstdDict_length(PyObject *ob)
{
ZstdDict *self = ZstdDict_CAST(ob);
- assert(PyBytes_Check(self->dict_content));
- return Py_SIZE(self->dict_content);
+ return self->dict_len;
}
static int
@@ -252,7 +241,6 @@ ZstdDict_traverse(PyObject *ob, visitproc visit, void *arg)
{
ZstdDict *self = ZstdDict_CAST(ob);
Py_VISIT(self->c_dicts);
- Py_VISIT(self->dict_content);
return 0;
}
@@ -260,7 +248,7 @@ static int
ZstdDict_clear(PyObject *ob)
{
ZstdDict *self = ZstdDict_CAST(ob);
- Py_CLEAR(self->dict_content);
+ Py_CLEAR(self->c_dicts);
return 0;
}
@@ -269,18 +257,18 @@ static PyType_Slot zstddict_slots[] = {
{Py_tp_getset, ZstdDict_getset},
{Py_tp_new, _zstd_ZstdDict_new},
{Py_tp_dealloc, ZstdDict_dealloc},
- {Py_tp_init, _zstd_ZstdDict___init__},
- {Py_tp_str, ZstdDict_str},
- {Py_tp_doc, (char*)_zstd_ZstdDict___init____doc__},
+ {Py_tp_repr, ZstdDict_repr},
+ {Py_tp_doc, (void *)_zstd_ZstdDict_new__doc__},
{Py_sq_length, ZstdDict_length},
{Py_tp_traverse, ZstdDict_traverse},
{Py_tp_clear, ZstdDict_clear},
- {0}
+ {0, 0}
};
PyType_Spec zstd_dict_type_spec = {
- .name = "_zstd.ZstdDict",
+ .name = "compression.zstd.ZstdDict",
.basicsize = sizeof(ZstdDict),
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE
+ | Py_TPFLAGS_HAVE_GC,
.slots = zstddict_slots,
};
diff --git a/Modules/_zstd/zstddict.h b/Modules/_zstd/zstddict.h
new file mode 100644
index 00000000000..4a403416dbd
--- /dev/null
+++ b/Modules/_zstd/zstddict.h
@@ -0,0 +1,29 @@
+/* Low level interface to the Zstandard algorthm & the zstd library. */
+
+#ifndef ZSTD_DICT_H
+#define ZSTD_DICT_H
+
+#include <zstd.h> // ZSTD_DDict
+
+typedef struct {
+ PyObject_HEAD
+
+ /* Reusable compress/decompress dictionary, they are created once and
+ can be shared by multiple threads concurrently, since its usage is
+ read-only.
+ c_dicts is a dict, int(compressionLevel):PyCapsule(ZSTD_CDict*) */
+ ZSTD_DDict *d_dict;
+ PyObject *c_dicts;
+
+ /* Dictionary content. */
+ char *dict_buffer;
+ Py_ssize_t dict_len;
+
+ /* Dictionary id */
+ uint32_t dict_id;
+
+ /* Lock to protect the digested dictionaries */
+ PyMutex lock;
+} ZstdDict;
+
+#endif // !ZSTD_DICT_H
diff --git a/Modules/blake2module.c b/Modules/blake2module.c
index f9acc57f1b2..07aa89f573f 100644
--- a/Modules/blake2module.c
+++ b/Modules/blake2module.c
@@ -655,8 +655,7 @@ error:
/*[clinic input]
@classmethod
_blake2.blake2b.__new__ as py_blake2b_new
- data: object(c_default="NULL") = b''
- /
+ data as data_obj: object(c_default="NULL") = b''
*
digest_size: int(c_default="HACL_HASH_BLAKE2B_OUT_BYTES") = _blake2.blake2b.MAX_DIGEST_SIZE
key: Py_buffer(c_default="NULL", py_default="b''") = None
@@ -670,26 +669,31 @@ _blake2.blake2b.__new__ as py_blake2b_new
inner_size: int = 0
last_node: bool = False
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Return a new BLAKE2b hash object.
[clinic start generated code]*/
static PyObject *
-py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
+py_blake2b_new_impl(PyTypeObject *type, PyObject *data_obj, int digest_size,
Py_buffer *key, Py_buffer *salt, Py_buffer *person,
int fanout, int depth, unsigned long leaf_size,
unsigned long long node_offset, int node_depth,
- int inner_size, int last_node, int usedforsecurity)
-/*[clinic end generated code: output=32bfd8f043c6896f input=8fee2b7b11428b2d]*/
+ int inner_size, int last_node, int usedforsecurity,
+ PyObject *string)
+/*[clinic end generated code: output=de64bd850606b6a0 input=78cf60a2922d2f90]*/
{
+ PyObject *data;
+ if (_Py_hashlib_data_argument(&data, data_obj, string) < 0) {
+ return NULL;
+ }
return py_blake2b_or_s_new(type, data, digest_size, key, salt, person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity);
}
/*[clinic input]
@classmethod
_blake2.blake2s.__new__ as py_blake2s_new
- data: object(c_default="NULL") = b''
- /
+ data as data_obj: object(c_default="NULL") = b''
*
digest_size: int(c_default="HACL_HASH_BLAKE2S_OUT_BYTES") = _blake2.blake2s.MAX_DIGEST_SIZE
key: Py_buffer(c_default="NULL", py_default="b''") = None
@@ -703,18 +707,24 @@ _blake2.blake2s.__new__ as py_blake2s_new
inner_size: int = 0
last_node: bool = False
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Return a new BLAKE2s hash object.
[clinic start generated code]*/
static PyObject *
-py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
+py_blake2s_new_impl(PyTypeObject *type, PyObject *data_obj, int digest_size,
Py_buffer *key, Py_buffer *salt, Py_buffer *person,
int fanout, int depth, unsigned long leaf_size,
unsigned long long node_offset, int node_depth,
- int inner_size, int last_node, int usedforsecurity)
-/*[clinic end generated code: output=556181f73905c686 input=8165a11980eac7f3]*/
+ int inner_size, int last_node, int usedforsecurity,
+ PyObject *string)
+/*[clinic end generated code: output=582a0c4295cc3a3c input=6843d6332eefd295]*/
{
+ PyObject *data;
+ if (_Py_hashlib_data_argument(&data, data_obj, string) < 0) {
+ return NULL;
+ }
return py_blake2b_or_s_new(type, data, digest_size, key, salt, person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity);
}
diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h
index 552360eb80a..49c864318c8 100644
--- a/Modules/clinic/_cursesmodule.c.h
+++ b/Modules/clinic/_cursesmodule.c.h
@@ -733,23 +733,13 @@ PyDoc_STRVAR(_curses_window_getbkgd__doc__,
#define _CURSES_WINDOW_GETBKGD_METHODDEF \
{"getbkgd", (PyCFunction)_curses_window_getbkgd, METH_NOARGS, _curses_window_getbkgd__doc__},
-static long
+static PyObject *
_curses_window_getbkgd_impl(PyCursesWindowObject *self);
static PyObject *
_curses_window_getbkgd(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- PyObject *return_value = NULL;
- long _return_value;
-
- _return_value = _curses_window_getbkgd_impl((PyCursesWindowObject *)self);
- if ((_return_value == -1) && PyErr_Occurred()) {
- goto exit;
- }
- return_value = PyLong_FromLong(_return_value);
-
-exit:
- return return_value;
+ return _curses_window_getbkgd_impl((PyCursesWindowObject *)self);
}
PyDoc_STRVAR(_curses_window_getch__doc__,
@@ -768,7 +758,7 @@ PyDoc_STRVAR(_curses_window_getch__doc__,
#define _CURSES_WINDOW_GETCH_METHODDEF \
{"getch", (PyCFunction)_curses_window_getch, METH_VARARGS, _curses_window_getch__doc__},
-static int
+static PyObject *
_curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1,
int y, int x);
@@ -779,7 +769,6 @@ _curses_window_getch(PyObject *self, PyObject *args)
int group_right_1 = 0;
int y = 0;
int x = 0;
- int _return_value;
switch (PyTuple_GET_SIZE(args)) {
case 0:
@@ -794,11 +783,7 @@ _curses_window_getch(PyObject *self, PyObject *args)
PyErr_SetString(PyExc_TypeError, "_curses.window.getch requires 0 to 2 arguments");
goto exit;
}
- _return_value = _curses_window_getch_impl((PyCursesWindowObject *)self, group_right_1, y, x);
- if ((_return_value == -1) && PyErr_Occurred()) {
- goto exit;
- }
- return_value = PyLong_FromLong((long)_return_value);
+ return_value = _curses_window_getch_impl((PyCursesWindowObject *)self, group_right_1, y, x);
exit:
return return_value;
@@ -1055,7 +1040,7 @@ PyDoc_STRVAR(_curses_window_inch__doc__,
#define _CURSES_WINDOW_INCH_METHODDEF \
{"inch", (PyCFunction)_curses_window_inch, METH_VARARGS, _curses_window_inch__doc__},
-static unsigned long
+static PyObject *
_curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1,
int y, int x);
@@ -1066,7 +1051,6 @@ _curses_window_inch(PyObject *self, PyObject *args)
int group_right_1 = 0;
int y = 0;
int x = 0;
- unsigned long _return_value;
switch (PyTuple_GET_SIZE(args)) {
case 0:
@@ -1081,11 +1065,7 @@ _curses_window_inch(PyObject *self, PyObject *args)
PyErr_SetString(PyExc_TypeError, "_curses.window.inch requires 0 to 2 arguments");
goto exit;
}
- _return_value = _curses_window_inch_impl((PyCursesWindowObject *)self, group_right_1, y, x);
- if ((_return_value == (unsigned long)-1) && PyErr_Occurred()) {
- goto exit;
- }
- return_value = PyLong_FromUnsignedLong(_return_value);
+ return_value = _curses_window_inch_impl((PyCursesWindowObject *)self, group_right_1, y, x);
exit:
return return_value;
@@ -4440,4 +4420,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored
#ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF
#endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */
-/*[clinic end generated code: output=42b2923d88c8d0f6 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=a083473003179b30 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h
index 5e503194408..091ce9edc43 100644
--- a/Modules/clinic/_dbmmodule.c.h
+++ b/Modules/clinic/_dbmmodule.c.h
@@ -5,6 +5,7 @@ preserve
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# include "pycore_runtime.h" // _Py_SINGLETON()
#endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
PyDoc_STRVAR(_dbm_dbm_close__doc__,
@@ -22,7 +23,13 @@ _dbm_dbm_close_impl(dbmobject *self);
static PyObject *
_dbm_dbm_close(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- return _dbm_dbm_close_impl((dbmobject *)self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _dbm_dbm_close_impl((dbmobject *)self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_dbm_dbm_keys__doc__,
@@ -40,11 +47,18 @@ _dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls);
static PyObject *
_dbm_dbm_keys(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "keys() takes no arguments");
- return NULL;
+ goto exit;
}
- return _dbm_dbm_keys_impl((dbmobject *)self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _dbm_dbm_keys_impl((dbmobject *)self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(_dbm_dbm_get__doc__,
@@ -85,7 +99,9 @@ _dbm_dbm_get(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_
&key, &key_length, &default_value)) {
goto exit;
}
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _dbm_dbm_get_impl((dbmobject *)self, cls, key, key_length, default_value);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -131,7 +147,9 @@ _dbm_dbm_setdefault(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py
&key, &key_length, &default_value)) {
goto exit;
}
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _dbm_dbm_setdefault_impl((dbmobject *)self, cls, key, key_length, default_value);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -152,11 +170,18 @@ _dbm_dbm_clear_impl(dbmobject *self, PyTypeObject *cls);
static PyObject *
_dbm_dbm_clear(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "clear() takes no arguments");
- return NULL;
+ goto exit;
}
- return _dbm_dbm_clear_impl((dbmobject *)self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _dbm_dbm_clear_impl((dbmobject *)self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(dbmopen__doc__,
@@ -221,4 +246,4 @@ skip_optional:
exit:
return return_value;
}
-/*[clinic end generated code: output=3b456118f231b160 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=279511ea7cda38dd input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h
index 00950f18e53..6fd6aa3da50 100644
--- a/Modules/clinic/_gdbmmodule.c.h
+++ b/Modules/clinic/_gdbmmodule.c.h
@@ -5,6 +5,7 @@ preserve
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
# include "pycore_runtime.h" // _Py_SINGLETON()
#endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
PyDoc_STRVAR(_gdbm_gdbm_get__doc__,
@@ -70,7 +71,9 @@ _gdbm_gdbm_setdefault(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
}
default_value = args[1];
skip_optional:
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _gdbm_gdbm_setdefault_impl((gdbmobject *)self, key, default_value);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -91,7 +94,13 @@ _gdbm_gdbm_close_impl(gdbmobject *self);
static PyObject *
_gdbm_gdbm_close(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- return _gdbm_gdbm_close_impl((gdbmobject *)self);
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _gdbm_gdbm_close_impl((gdbmobject *)self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
}
PyDoc_STRVAR(_gdbm_gdbm_keys__doc__,
@@ -109,11 +118,18 @@ _gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_keys(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "keys() takes no arguments");
- return NULL;
+ goto exit;
}
- return _gdbm_gdbm_keys_impl((gdbmobject *)self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _gdbm_gdbm_keys_impl((gdbmobject *)self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(_gdbm_gdbm_firstkey__doc__,
@@ -135,11 +151,18 @@ _gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_firstkey(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "firstkey() takes no arguments");
- return NULL;
+ goto exit;
}
- return _gdbm_gdbm_firstkey_impl((gdbmobject *)self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _gdbm_gdbm_firstkey_impl((gdbmobject *)self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__,
@@ -187,7 +210,9 @@ _gdbm_gdbm_nextkey(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_
&key, &key_length)) {
goto exit;
}
+ Py_BEGIN_CRITICAL_SECTION(self);
return_value = _gdbm_gdbm_nextkey_impl((gdbmobject *)self, cls, key, key_length);
+ Py_END_CRITICAL_SECTION();
exit:
return return_value;
@@ -214,11 +239,18 @@ _gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_reorganize(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "reorganize() takes no arguments");
- return NULL;
+ goto exit;
}
- return _gdbm_gdbm_reorganize_impl((gdbmobject *)self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _gdbm_gdbm_reorganize_impl((gdbmobject *)self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(_gdbm_gdbm_sync__doc__,
@@ -239,11 +271,18 @@ _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_sync(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "sync() takes no arguments");
- return NULL;
+ goto exit;
}
- return _gdbm_gdbm_sync_impl((gdbmobject *)self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _gdbm_gdbm_sync_impl((gdbmobject *)self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(_gdbm_gdbm_clear__doc__,
@@ -261,11 +300,18 @@ _gdbm_gdbm_clear_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_clear(PyObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
+ PyObject *return_value = NULL;
+
if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
PyErr_SetString(PyExc_TypeError, "clear() takes no arguments");
- return NULL;
+ goto exit;
}
- return _gdbm_gdbm_clear_impl((gdbmobject *)self, cls);
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _gdbm_gdbm_clear_impl((gdbmobject *)self, cls);
+ Py_END_CRITICAL_SECTION();
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(dbmopen__doc__,
@@ -343,4 +389,4 @@ skip_optional:
exit:
return return_value;
}
-/*[clinic end generated code: output=d974cb39e4ee5d67 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8bca34ce9d4493dd input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_hashopenssl.c.h b/Modules/clinic/_hashopenssl.c.h
index 59ab46ca3f0..61ea10e2a48 100644
--- a/Modules/clinic/_hashopenssl.c.h
+++ b/Modules/clinic/_hashopenssl.c.h
@@ -10,98 +10,98 @@ preserve
#include "pycore_long.h" // _PyLong_UnsignedLong_Converter()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
-PyDoc_STRVAR(EVP_copy__doc__,
+PyDoc_STRVAR(_hashlib_HASH_copy__doc__,
"copy($self, /)\n"
"--\n"
"\n"
"Return a copy of the hash object.");
-#define EVP_COPY_METHODDEF \
- {"copy", (PyCFunction)EVP_copy, METH_NOARGS, EVP_copy__doc__},
+#define _HASHLIB_HASH_COPY_METHODDEF \
+ {"copy", (PyCFunction)_hashlib_HASH_copy, METH_NOARGS, _hashlib_HASH_copy__doc__},
static PyObject *
-EVP_copy_impl(EVPobject *self);
+_hashlib_HASH_copy_impl(HASHobject *self);
static PyObject *
-EVP_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
+_hashlib_HASH_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- return EVP_copy_impl((EVPobject *)self);
+ return _hashlib_HASH_copy_impl((HASHobject *)self);
}
-PyDoc_STRVAR(EVP_digest__doc__,
+PyDoc_STRVAR(_hashlib_HASH_digest__doc__,
"digest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a bytes object.");
-#define EVP_DIGEST_METHODDEF \
- {"digest", (PyCFunction)EVP_digest, METH_NOARGS, EVP_digest__doc__},
+#define _HASHLIB_HASH_DIGEST_METHODDEF \
+ {"digest", (PyCFunction)_hashlib_HASH_digest, METH_NOARGS, _hashlib_HASH_digest__doc__},
static PyObject *
-EVP_digest_impl(EVPobject *self);
+_hashlib_HASH_digest_impl(HASHobject *self);
static PyObject *
-EVP_digest(PyObject *self, PyObject *Py_UNUSED(ignored))
+_hashlib_HASH_digest(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- return EVP_digest_impl((EVPobject *)self);
+ return _hashlib_HASH_digest_impl((HASHobject *)self);
}
-PyDoc_STRVAR(EVP_hexdigest__doc__,
+PyDoc_STRVAR(_hashlib_HASH_hexdigest__doc__,
"hexdigest($self, /)\n"
"--\n"
"\n"
"Return the digest value as a string of hexadecimal digits.");
-#define EVP_HEXDIGEST_METHODDEF \
- {"hexdigest", (PyCFunction)EVP_hexdigest, METH_NOARGS, EVP_hexdigest__doc__},
+#define _HASHLIB_HASH_HEXDIGEST_METHODDEF \
+ {"hexdigest", (PyCFunction)_hashlib_HASH_hexdigest, METH_NOARGS, _hashlib_HASH_hexdigest__doc__},
static PyObject *
-EVP_hexdigest_impl(EVPobject *self);
+_hashlib_HASH_hexdigest_impl(HASHobject *self);
static PyObject *
-EVP_hexdigest(PyObject *self, PyObject *Py_UNUSED(ignored))
+_hashlib_HASH_hexdigest(PyObject *self, PyObject *Py_UNUSED(ignored))
{
- return EVP_hexdigest_impl((EVPobject *)self);
+ return _hashlib_HASH_hexdigest_impl((HASHobject *)self);
}
-PyDoc_STRVAR(EVP_update__doc__,
+PyDoc_STRVAR(_hashlib_HASH_update__doc__,
"update($self, obj, /)\n"
"--\n"
"\n"
"Update this hash object\'s state with the provided string.");
-#define EVP_UPDATE_METHODDEF \
- {"update", (PyCFunction)EVP_update, METH_O, EVP_update__doc__},
+#define _HASHLIB_HASH_UPDATE_METHODDEF \
+ {"update", (PyCFunction)_hashlib_HASH_update, METH_O, _hashlib_HASH_update__doc__},
static PyObject *
-EVP_update_impl(EVPobject *self, PyObject *obj);
+_hashlib_HASH_update_impl(HASHobject *self, PyObject *obj);
static PyObject *
-EVP_update(PyObject *self, PyObject *obj)
+_hashlib_HASH_update(PyObject *self, PyObject *obj)
{
PyObject *return_value = NULL;
- return_value = EVP_update_impl((EVPobject *)self, obj);
+ return_value = _hashlib_HASH_update_impl((HASHobject *)self, obj);
return return_value;
}
#if defined(PY_OPENSSL_HAS_SHAKE)
-PyDoc_STRVAR(EVPXOF_digest__doc__,
+PyDoc_STRVAR(_hashlib_HASHXOF_digest__doc__,
"digest($self, /, length)\n"
"--\n"
"\n"
"Return the digest value as a bytes object.");
-#define EVPXOF_DIGEST_METHODDEF \
- {"digest", _PyCFunction_CAST(EVPXOF_digest), METH_FASTCALL|METH_KEYWORDS, EVPXOF_digest__doc__},
+#define _HASHLIB_HASHXOF_DIGEST_METHODDEF \
+ {"digest", _PyCFunction_CAST(_hashlib_HASHXOF_digest), METH_FASTCALL|METH_KEYWORDS, _hashlib_HASHXOF_digest__doc__},
static PyObject *
-EVPXOF_digest_impl(EVPobject *self, Py_ssize_t length);
+_hashlib_HASHXOF_digest_impl(HASHobject *self, Py_ssize_t length);
static PyObject *
-EVPXOF_digest(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_hashlib_HASHXOF_digest(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
@@ -151,7 +151,7 @@ EVPXOF_digest(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
}
length = ival;
}
- return_value = EVPXOF_digest_impl((EVPobject *)self, length);
+ return_value = _hashlib_HASHXOF_digest_impl((HASHobject *)self, length);
exit:
return return_value;
@@ -161,20 +161,20 @@ exit:
#if defined(PY_OPENSSL_HAS_SHAKE)
-PyDoc_STRVAR(EVPXOF_hexdigest__doc__,
+PyDoc_STRVAR(_hashlib_HASHXOF_hexdigest__doc__,
"hexdigest($self, /, length)\n"
"--\n"
"\n"
"Return the digest value as a string of hexadecimal digits.");
-#define EVPXOF_HEXDIGEST_METHODDEF \
- {"hexdigest", _PyCFunction_CAST(EVPXOF_hexdigest), METH_FASTCALL|METH_KEYWORDS, EVPXOF_hexdigest__doc__},
+#define _HASHLIB_HASHXOF_HEXDIGEST_METHODDEF \
+ {"hexdigest", _PyCFunction_CAST(_hashlib_HASHXOF_hexdigest), METH_FASTCALL|METH_KEYWORDS, _hashlib_HASHXOF_hexdigest__doc__},
static PyObject *
-EVPXOF_hexdigest_impl(EVPobject *self, Py_ssize_t length);
+_hashlib_HASHXOF_hexdigest_impl(HASHobject *self, Py_ssize_t length);
static PyObject *
-EVPXOF_hexdigest(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_hashlib_HASHXOF_hexdigest(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
@@ -224,7 +224,7 @@ EVPXOF_hexdigest(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje
}
length = ival;
}
- return_value = EVPXOF_hexdigest_impl((EVPobject *)self, length);
+ return_value = _hashlib_HASHXOF_hexdigest_impl((HASHobject *)self, length);
exit:
return return_value;
@@ -232,8 +232,8 @@ exit:
#endif /* defined(PY_OPENSSL_HAS_SHAKE) */
-PyDoc_STRVAR(EVP_new__doc__,
-"new($module, /, name, string=b\'\', *, usedforsecurity=True)\n"
+PyDoc_STRVAR(_hashlib_HASH_new__doc__,
+"new($module, /, name, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new hash object using the named algorithm.\n"
@@ -243,20 +243,20 @@ PyDoc_STRVAR(EVP_new__doc__,
"\n"
"The MD5 and SHA1 algorithms are always supported.");
-#define EVP_NEW_METHODDEF \
- {"new", _PyCFunction_CAST(EVP_new), METH_FASTCALL|METH_KEYWORDS, EVP_new__doc__},
+#define _HASHLIB_HASH_NEW_METHODDEF \
+ {"new", _PyCFunction_CAST(_hashlib_HASH_new), METH_FASTCALL|METH_KEYWORDS, _hashlib_HASH_new__doc__},
static PyObject *
-EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_HASH_new_impl(PyObject *module, const char *name, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
-EVP_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+_hashlib_HASH_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 3
+ #define NUM_KEYWORDS 4
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -265,7 +265,7 @@ EVP_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(name), &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(name), &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -274,30 +274,43 @@ EVP_new(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwn
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"name", "string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"name", "data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "new",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[4];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
- PyObject *name_obj;
- PyObject *data_obj = NULL;
+ const char *name;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 1, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
if (!args) {
goto exit;
}
- name_obj = args[0];
+ if (!PyUnicode_Check(args[0])) {
+ _PyArg_BadArgument("new", "argument 'name'", "str", args[0]);
+ goto exit;
+ }
+ Py_ssize_t name_length;
+ name = PyUnicode_AsUTF8AndSize(args[0], &name_length);
+ if (name == NULL) {
+ goto exit;
+ }
+ if (strlen(name) != (size_t)name_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
if (!noptargs) {
goto skip_optional_pos;
}
if (args[1]) {
- data_obj = args[1];
+ data = args[1];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -306,19 +319,25 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[2]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[2]) {
+ usedforsecurity = PyObject_IsTrue(args[2]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[3];
skip_optional_kwonly:
- return_value = EVP_new_impl(module, name_obj, data_obj, usedforsecurity);
+ return_value = _hashlib_HASH_new_impl(module, name, data, usedforsecurity, string);
exit:
return return_value;
}
PyDoc_STRVAR(_hashlib_openssl_md5__doc__,
-"openssl_md5($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_md5($module, /, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Returns a md5 hash object; optionally initialized with a string");
@@ -327,8 +346,8 @@ PyDoc_STRVAR(_hashlib_openssl_md5__doc__,
{"openssl_md5", _PyCFunction_CAST(_hashlib_openssl_md5), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_md5__doc__},
static PyObject *
-_hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_md5_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -336,7 +355,7 @@ _hashlib_openssl_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -345,7 +364,7 @@ _hashlib_openssl_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -354,17 +373,18 @@ _hashlib_openssl_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_md5",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -375,7 +395,7 @@ _hashlib_openssl_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -384,19 +404,25 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_md5_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_md5_impl(module, data, usedforsecurity, string);
exit:
return return_value;
}
PyDoc_STRVAR(_hashlib_openssl_sha1__doc__,
-"openssl_sha1($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha1($module, /, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Returns a sha1 hash object; optionally initialized with a string");
@@ -405,8 +431,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha1__doc__,
{"openssl_sha1", _PyCFunction_CAST(_hashlib_openssl_sha1), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha1__doc__},
static PyObject *
-_hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha1_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -414,7 +440,7 @@ _hashlib_openssl_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -423,7 +449,7 @@ _hashlib_openssl_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -432,17 +458,18 @@ _hashlib_openssl_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha1",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -453,7 +480,7 @@ _hashlib_openssl_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs,
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -462,19 +489,26 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha1_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha1_impl(module, data, usedforsecurity, string);
exit:
return return_value;
}
PyDoc_STRVAR(_hashlib_openssl_sha224__doc__,
-"openssl_sha224($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha224($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a sha224 hash object; optionally initialized with a string");
@@ -483,8 +517,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha224__doc__,
{"openssl_sha224", _PyCFunction_CAST(_hashlib_openssl_sha224), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha224__doc__},
static PyObject *
-_hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha224_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -492,7 +526,7 @@ _hashlib_openssl_sha224(PyObject *module, PyObject *const *args, Py_ssize_t narg
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -501,7 +535,7 @@ _hashlib_openssl_sha224(PyObject *module, PyObject *const *args, Py_ssize_t narg
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -510,17 +544,18 @@ _hashlib_openssl_sha224(PyObject *module, PyObject *const *args, Py_ssize_t narg
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha224",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -531,7 +566,7 @@ _hashlib_openssl_sha224(PyObject *module, PyObject *const *args, Py_ssize_t narg
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -540,19 +575,26 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha224_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha224_impl(module, data, usedforsecurity, string);
exit:
return return_value;
}
PyDoc_STRVAR(_hashlib_openssl_sha256__doc__,
-"openssl_sha256($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha256($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a sha256 hash object; optionally initialized with a string");
@@ -561,8 +603,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha256__doc__,
{"openssl_sha256", _PyCFunction_CAST(_hashlib_openssl_sha256), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha256__doc__},
static PyObject *
-_hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha256_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -570,7 +612,7 @@ _hashlib_openssl_sha256(PyObject *module, PyObject *const *args, Py_ssize_t narg
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -579,7 +621,7 @@ _hashlib_openssl_sha256(PyObject *module, PyObject *const *args, Py_ssize_t narg
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -588,17 +630,18 @@ _hashlib_openssl_sha256(PyObject *module, PyObject *const *args, Py_ssize_t narg
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha256",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -609,7 +652,7 @@ _hashlib_openssl_sha256(PyObject *module, PyObject *const *args, Py_ssize_t narg
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -618,19 +661,26 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha256_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha256_impl(module, data, usedforsecurity, string);
exit:
return return_value;
}
PyDoc_STRVAR(_hashlib_openssl_sha384__doc__,
-"openssl_sha384($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha384($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a sha384 hash object; optionally initialized with a string");
@@ -639,8 +689,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha384__doc__,
{"openssl_sha384", _PyCFunction_CAST(_hashlib_openssl_sha384), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha384__doc__},
static PyObject *
-_hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha384_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -648,7 +698,7 @@ _hashlib_openssl_sha384(PyObject *module, PyObject *const *args, Py_ssize_t narg
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -657,7 +707,7 @@ _hashlib_openssl_sha384(PyObject *module, PyObject *const *args, Py_ssize_t narg
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -666,17 +716,18 @@ _hashlib_openssl_sha384(PyObject *module, PyObject *const *args, Py_ssize_t narg
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha384",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -687,7 +738,7 @@ _hashlib_openssl_sha384(PyObject *module, PyObject *const *args, Py_ssize_t narg
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -696,19 +747,26 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha384_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha384_impl(module, data, usedforsecurity, string);
exit:
return return_value;
}
PyDoc_STRVAR(_hashlib_openssl_sha512__doc__,
-"openssl_sha512($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha512($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a sha512 hash object; optionally initialized with a string");
@@ -717,8 +775,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha512__doc__,
{"openssl_sha512", _PyCFunction_CAST(_hashlib_openssl_sha512), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha512__doc__},
static PyObject *
-_hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha512_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -726,7 +784,7 @@ _hashlib_openssl_sha512(PyObject *module, PyObject *const *args, Py_ssize_t narg
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -735,7 +793,7 @@ _hashlib_openssl_sha512(PyObject *module, PyObject *const *args, Py_ssize_t narg
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -744,17 +802,18 @@ _hashlib_openssl_sha512(PyObject *module, PyObject *const *args, Py_ssize_t narg
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha512",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -765,7 +824,7 @@ _hashlib_openssl_sha512(PyObject *module, PyObject *const *args, Py_ssize_t narg
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -774,12 +833,18 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha512_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha512_impl(module, data, usedforsecurity, string);
exit:
return return_value;
@@ -788,7 +853,8 @@ exit:
#if defined(PY_OPENSSL_HAS_SHA3)
PyDoc_STRVAR(_hashlib_openssl_sha3_224__doc__,
-"openssl_sha3_224($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha3_224($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a sha3-224 hash object; optionally initialized with a string");
@@ -797,8 +863,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha3_224__doc__,
{"openssl_sha3_224", _PyCFunction_CAST(_hashlib_openssl_sha3_224), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_224__doc__},
static PyObject *
-_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha3_224_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -806,7 +872,7 @@ _hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t na
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -815,7 +881,7 @@ _hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t na
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -824,17 +890,18 @@ _hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t na
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha3_224",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -845,7 +912,7 @@ _hashlib_openssl_sha3_224(PyObject *module, PyObject *const *args, Py_ssize_t na
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -854,12 +921,18 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha3_224_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha3_224_impl(module, data, usedforsecurity, string);
exit:
return return_value;
@@ -870,7 +943,8 @@ exit:
#if defined(PY_OPENSSL_HAS_SHA3)
PyDoc_STRVAR(_hashlib_openssl_sha3_256__doc__,
-"openssl_sha3_256($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha3_256($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a sha3-256 hash object; optionally initialized with a string");
@@ -879,8 +953,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha3_256__doc__,
{"openssl_sha3_256", _PyCFunction_CAST(_hashlib_openssl_sha3_256), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_256__doc__},
static PyObject *
-_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha3_256_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -888,7 +962,7 @@ _hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t na
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -897,7 +971,7 @@ _hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t na
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -906,17 +980,18 @@ _hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t na
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha3_256",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -927,7 +1002,7 @@ _hashlib_openssl_sha3_256(PyObject *module, PyObject *const *args, Py_ssize_t na
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -936,12 +1011,18 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha3_256_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha3_256_impl(module, data, usedforsecurity, string);
exit:
return return_value;
@@ -952,7 +1033,8 @@ exit:
#if defined(PY_OPENSSL_HAS_SHA3)
PyDoc_STRVAR(_hashlib_openssl_sha3_384__doc__,
-"openssl_sha3_384($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha3_384($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a sha3-384 hash object; optionally initialized with a string");
@@ -961,8 +1043,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha3_384__doc__,
{"openssl_sha3_384", _PyCFunction_CAST(_hashlib_openssl_sha3_384), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_384__doc__},
static PyObject *
-_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha3_384_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -970,7 +1052,7 @@ _hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t na
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -979,7 +1061,7 @@ _hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t na
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -988,17 +1070,18 @@ _hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t na
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha3_384",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -1009,7 +1092,7 @@ _hashlib_openssl_sha3_384(PyObject *module, PyObject *const *args, Py_ssize_t na
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -1018,12 +1101,18 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha3_384_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha3_384_impl(module, data, usedforsecurity, string);
exit:
return return_value;
@@ -1034,7 +1123,8 @@ exit:
#if defined(PY_OPENSSL_HAS_SHA3)
PyDoc_STRVAR(_hashlib_openssl_sha3_512__doc__,
-"openssl_sha3_512($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_sha3_512($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a sha3-512 hash object; optionally initialized with a string");
@@ -1043,8 +1133,8 @@ PyDoc_STRVAR(_hashlib_openssl_sha3_512__doc__,
{"openssl_sha3_512", _PyCFunction_CAST(_hashlib_openssl_sha3_512), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_sha3_512__doc__},
static PyObject *
-_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_sha3_512_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -1052,7 +1142,7 @@ _hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t na
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -1061,7 +1151,7 @@ _hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t na
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -1070,17 +1160,18 @@ _hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t na
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_sha3_512",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -1091,7 +1182,7 @@ _hashlib_openssl_sha3_512(PyObject *module, PyObject *const *args, Py_ssize_t na
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -1100,12 +1191,18 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_sha3_512_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_sha3_512_impl(module, data, usedforsecurity, string);
exit:
return return_value;
@@ -1116,7 +1213,8 @@ exit:
#if defined(PY_OPENSSL_HAS_SHAKE)
PyDoc_STRVAR(_hashlib_openssl_shake_128__doc__,
-"openssl_shake_128($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_shake_128($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a shake-128 variable hash object; optionally initialized with a string");
@@ -1125,8 +1223,8 @@ PyDoc_STRVAR(_hashlib_openssl_shake_128__doc__,
{"openssl_shake_128", _PyCFunction_CAST(_hashlib_openssl_shake_128), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_128__doc__},
static PyObject *
-_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_shake_128_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -1134,7 +1232,7 @@ _hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t n
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -1143,7 +1241,7 @@ _hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t n
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -1152,17 +1250,18 @@ _hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t n
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_shake_128",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -1173,7 +1272,7 @@ _hashlib_openssl_shake_128(PyObject *module, PyObject *const *args, Py_ssize_t n
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -1182,12 +1281,18 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_shake_128_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_shake_128_impl(module, data, usedforsecurity, string);
exit:
return return_value;
@@ -1198,7 +1303,8 @@ exit:
#if defined(PY_OPENSSL_HAS_SHAKE)
PyDoc_STRVAR(_hashlib_openssl_shake_256__doc__,
-"openssl_shake_256($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"openssl_shake_256($module, /, data=b\'\', *, usedforsecurity=True,\n"
+" string=None)\n"
"--\n"
"\n"
"Returns a shake-256 variable hash object; optionally initialized with a string");
@@ -1207,8 +1313,8 @@ PyDoc_STRVAR(_hashlib_openssl_shake_256__doc__,
{"openssl_shake_256", _PyCFunction_CAST(_hashlib_openssl_shake_256), METH_FASTCALL|METH_KEYWORDS, _hashlib_openssl_shake_256__doc__},
static PyObject *
-_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data_obj,
- int usedforsecurity);
+_hashlib_openssl_shake_256_impl(PyObject *module, PyObject *data,
+ int usedforsecurity, PyObject *string);
static PyObject *
_hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -1216,7 +1322,7 @@ _hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t n
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -1225,7 +1331,7 @@ _hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t n
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -1234,17 +1340,18 @@ _hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t n
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "openssl_shake_256",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *data_obj = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -1255,7 +1362,7 @@ _hashlib_openssl_shake_256(PyObject *module, PyObject *const *args, Py_ssize_t n
goto skip_optional_pos;
}
if (args[0]) {
- data_obj = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -1264,12 +1371,18 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = args[2];
skip_optional_kwonly:
- return_value = _hashlib_openssl_shake_256_impl(module, data_obj, usedforsecurity);
+ return_value = _hashlib_openssl_shake_256_impl(module, data, usedforsecurity, string);
exit:
return return_value;
@@ -1836,13 +1949,13 @@ exit:
return return_value;
}
-#ifndef EVPXOF_DIGEST_METHODDEF
- #define EVPXOF_DIGEST_METHODDEF
-#endif /* !defined(EVPXOF_DIGEST_METHODDEF) */
+#ifndef _HASHLIB_HASHXOF_DIGEST_METHODDEF
+ #define _HASHLIB_HASHXOF_DIGEST_METHODDEF
+#endif /* !defined(_HASHLIB_HASHXOF_DIGEST_METHODDEF) */
-#ifndef EVPXOF_HEXDIGEST_METHODDEF
- #define EVPXOF_HEXDIGEST_METHODDEF
-#endif /* !defined(EVPXOF_HEXDIGEST_METHODDEF) */
+#ifndef _HASHLIB_HASHXOF_HEXDIGEST_METHODDEF
+ #define _HASHLIB_HASHXOF_HEXDIGEST_METHODDEF
+#endif /* !defined(_HASHLIB_HASHXOF_HEXDIGEST_METHODDEF) */
#ifndef _HASHLIB_OPENSSL_SHA3_224_METHODDEF
#define _HASHLIB_OPENSSL_SHA3_224_METHODDEF
@@ -1871,4 +1984,4 @@ exit:
#ifndef _HASHLIB_SCRYPT_METHODDEF
#define _HASHLIB_SCRYPT_METHODDEF
#endif /* !defined(_HASHLIB_SCRYPT_METHODDEF) */
-/*[clinic end generated code: output=2c78822e38be64a8 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=29f4aaf01714778e input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_randommodule.c.h b/Modules/clinic/_randommodule.c.h
index 1e989e970c9..2563a16aea0 100644
--- a/Modules/clinic/_randommodule.c.h
+++ b/Modules/clinic/_randommodule.c.h
@@ -3,6 +3,7 @@ preserve
[clinic start generated code]*/
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
+#include "pycore_long.h" // _PyLong_UInt64_Converter()
#include "pycore_modsupport.h" // _PyArg_CheckPositional()
PyDoc_STRVAR(_random_Random_random__doc__,
@@ -124,16 +125,15 @@ PyDoc_STRVAR(_random_Random_getrandbits__doc__,
{"getrandbits", (PyCFunction)_random_Random_getrandbits, METH_O, _random_Random_getrandbits__doc__},
static PyObject *
-_random_Random_getrandbits_impl(RandomObject *self, int k);
+_random_Random_getrandbits_impl(RandomObject *self, uint64_t k);
static PyObject *
_random_Random_getrandbits(PyObject *self, PyObject *arg)
{
PyObject *return_value = NULL;
- int k;
+ uint64_t k;
- k = PyLong_AsInt(arg);
- if (k == -1 && PyErr_Occurred()) {
+ if (!_PyLong_UInt64_Converter(arg, &k)) {
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
@@ -143,4 +143,4 @@ _random_Random_getrandbits(PyObject *self, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=4458b5a69201ebea input=a9049054013a1b77]*/
+/*[clinic end generated code: output=7ce97b2194eecaf7 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_remote_debugging_module.c.h b/Modules/clinic/_remote_debugging_module.c.h
new file mode 100644
index 00000000000..5c313a2d664
--- /dev/null
+++ b/Modules/clinic/_remote_debugging_module.c.h
@@ -0,0 +1,256 @@
+/*[clinic input]
+preserve
+[clinic start generated code]*/
+
+#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+# include "pycore_gc.h" // PyGC_Head
+# include "pycore_runtime.h" // _Py_ID()
+#endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
+#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
+
+PyDoc_STRVAR(_remote_debugging_RemoteUnwinder___init____doc__,
+"RemoteUnwinder(pid, *, all_threads=False, debug=False)\n"
+"--\n"
+"\n"
+"Initialize a new RemoteUnwinder object for debugging a remote Python process.\n"
+"\n"
+"Args:\n"
+" pid: Process ID of the target Python process to debug\n"
+" all_threads: If True, initialize state for all threads in the process.\n"
+" If False, only initialize for the main thread.\n"
+" debug: If True, chain exceptions to explain the sequence of events that\n"
+" lead to the exception.\n"
+"\n"
+"The RemoteUnwinder provides functionality to inspect and debug a running Python\n"
+"process, including examining thread states, stack frames and other runtime data.\n"
+"\n"
+"Raises:\n"
+" PermissionError: If access to the target process is denied\n"
+" OSError: If unable to attach to the target process or access its memory\n"
+" RuntimeError: If unable to read debug information from the target process");
+
+static int
+_remote_debugging_RemoteUnwinder___init___impl(RemoteUnwinderObject *self,
+ int pid, int all_threads,
+ int debug);
+
+static int
+_remote_debugging_RemoteUnwinder___init__(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int return_value = -1;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 3
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
+ .ob_item = { &_Py_ID(pid), &_Py_ID(all_threads), &_Py_ID(debug), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"pid", "all_threads", "debug", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "RemoteUnwinder",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[3];
+ PyObject * const *fastargs;
+ Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+ Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 1;
+ int pid;
+ int all_threads = 0;
+ int debug = 0;
+
+ fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser,
+ /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+ if (!fastargs) {
+ goto exit;
+ }
+ pid = PyLong_AsInt(fastargs[0]);
+ if (pid == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ if (fastargs[1]) {
+ all_threads = PyObject_IsTrue(fastargs[1]);
+ if (all_threads < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
+ }
+ debug = PyObject_IsTrue(fastargs[2]);
+ if (debug < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = _remote_debugging_RemoteUnwinder___init___impl((RemoteUnwinderObject *)self, pid, all_threads, debug);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_stack_trace__doc__,
+"get_stack_trace($self, /)\n"
+"--\n"
+"\n"
+"Returns a list of stack traces for all threads in the target process.\n"
+"\n"
+"Each element in the returned list is a tuple of (thread_id, frame_list), where:\n"
+"- thread_id is the OS thread identifier\n"
+"- frame_list is a list of tuples (function_name, filename, line_number) representing\n"
+" the Python stack frames for that thread, ordered from most recent to oldest\n"
+"\n"
+"Example:\n"
+" [\n"
+" (1234, [\n"
+" (\'process_data\', \'worker.py\', 127),\n"
+" (\'run_worker\', \'worker.py\', 45),\n"
+" (\'main\', \'app.py\', 23)\n"
+" ]),\n"
+" (1235, [\n"
+" (\'handle_request\', \'server.py\', 89),\n"
+" (\'serve_forever\', \'server.py\', 52)\n"
+" ])\n"
+" ]\n"
+"\n"
+"Raises:\n"
+" RuntimeError: If there is an error copying memory from the target process\n"
+" OSError: If there is an error accessing the target process\n"
+" PermissionError: If access to the target process is denied\n"
+" UnicodeDecodeError: If there is an error decoding strings from the target process");
+
+#define _REMOTE_DEBUGGING_REMOTEUNWINDER_GET_STACK_TRACE_METHODDEF \
+ {"get_stack_trace", (PyCFunction)_remote_debugging_RemoteUnwinder_get_stack_trace, METH_NOARGS, _remote_debugging_RemoteUnwinder_get_stack_trace__doc__},
+
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_stack_trace_impl(RemoteUnwinderObject *self);
+
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_stack_trace(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _remote_debugging_RemoteUnwinder_get_stack_trace_impl((RemoteUnwinderObject *)self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_all_awaited_by__doc__,
+"get_all_awaited_by($self, /)\n"
+"--\n"
+"\n"
+"Get all tasks and their awaited_by relationships from the remote process.\n"
+"\n"
+"This provides a tree structure showing which tasks are waiting for other tasks.\n"
+"\n"
+"For each task, returns:\n"
+"1. The call stack frames leading to where the task is currently executing\n"
+"2. The name of the task\n"
+"3. A list of tasks that this task is waiting for, with their own frames/names/etc\n"
+"\n"
+"Returns a list of [frames, task_name, subtasks] where:\n"
+"- frames: List of (func_name, filename, lineno) showing the call stack\n"
+"- task_name: String identifier for the task\n"
+"- subtasks: List of tasks being awaited by this task, in same format\n"
+"\n"
+"Raises:\n"
+" RuntimeError: If AsyncioDebug section is not available in the remote process\n"
+" MemoryError: If memory allocation fails\n"
+" OSError: If reading from the remote process fails\n"
+"\n"
+"Example output:\n"
+"[\n"
+" [\n"
+" [(\"c5\", \"script.py\", 10), (\"c4\", \"script.py\", 14)],\n"
+" \"c2_root\",\n"
+" [\n"
+" [\n"
+" [(\"c1\", \"script.py\", 23)],\n"
+" \"sub_main_2\",\n"
+" [...]\n"
+" ],\n"
+" [...]\n"
+" ]\n"
+" ]\n"
+"]");
+
+#define _REMOTE_DEBUGGING_REMOTEUNWINDER_GET_ALL_AWAITED_BY_METHODDEF \
+ {"get_all_awaited_by", (PyCFunction)_remote_debugging_RemoteUnwinder_get_all_awaited_by, METH_NOARGS, _remote_debugging_RemoteUnwinder_get_all_awaited_by__doc__},
+
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_all_awaited_by_impl(RemoteUnwinderObject *self);
+
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_all_awaited_by(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _remote_debugging_RemoteUnwinder_get_all_awaited_by_impl((RemoteUnwinderObject *)self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+
+PyDoc_STRVAR(_remote_debugging_RemoteUnwinder_get_async_stack_trace__doc__,
+"get_async_stack_trace($self, /)\n"
+"--\n"
+"\n"
+"Returns information about the currently running async task and its stack trace.\n"
+"\n"
+"Returns a tuple of (task_info, stack_frames) where:\n"
+"- task_info is a tuple of (task_id, task_name) identifying the task\n"
+"- stack_frames is a list of tuples (function_name, filename, line_number) representing\n"
+" the Python stack frames for the task, ordered from most recent to oldest\n"
+"\n"
+"Example:\n"
+" ((4345585712, \'Task-1\'), [\n"
+" (\'run_echo_server\', \'server.py\', 127),\n"
+" (\'serve_forever\', \'server.py\', 45),\n"
+" (\'main\', \'app.py\', 23)\n"
+" ])\n"
+"\n"
+"Raises:\n"
+" RuntimeError: If AsyncioDebug section is not available in the target process\n"
+" RuntimeError: If there is an error copying memory from the target process\n"
+" OSError: If there is an error accessing the target process\n"
+" PermissionError: If access to the target process is denied\n"
+" UnicodeDecodeError: If there is an error decoding strings from the target process");
+
+#define _REMOTE_DEBUGGING_REMOTEUNWINDER_GET_ASYNC_STACK_TRACE_METHODDEF \
+ {"get_async_stack_trace", (PyCFunction)_remote_debugging_RemoteUnwinder_get_async_stack_trace, METH_NOARGS, _remote_debugging_RemoteUnwinder_get_async_stack_trace__doc__},
+
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_async_stack_trace_impl(RemoteUnwinderObject *self);
+
+static PyObject *
+_remote_debugging_RemoteUnwinder_get_async_stack_trace(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *return_value = NULL;
+
+ Py_BEGIN_CRITICAL_SECTION(self);
+ return_value = _remote_debugging_RemoteUnwinder_get_async_stack_trace_impl((RemoteUnwinderObject *)self);
+ Py_END_CRITICAL_SECTION();
+
+ return return_value;
+}
+/*[clinic end generated code: output=774ec34aa653402d input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_threadmodule.c.h b/Modules/clinic/_threadmodule.c.h
index 8930e54170c..fd8e32a2261 100644
--- a/Modules/clinic/_threadmodule.c.h
+++ b/Modules/clinic/_threadmodule.c.h
@@ -6,7 +6,53 @@ preserve
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
-#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
+#include "pycore_modsupport.h" // _PyArg_NoKeywords()
+
+static PyObject *
+lock_new_impl(PyTypeObject *type);
+
+static PyObject *
+lock_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = clinic_state()->lock_type;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoPositional("lock", args)) {
+ goto exit;
+ }
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("lock", kwargs)) {
+ goto exit;
+ }
+ return_value = lock_new_impl(type);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+rlock_new_impl(PyTypeObject *type);
+
+static PyObject *
+rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ PyTypeObject *base_tp = clinic_state()->rlock_type;
+
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoPositional("RLock", args)) {
+ goto exit;
+ }
+ if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
+ !_PyArg_NoKeywords("RLock", kwargs)) {
+ goto exit;
+ }
+ return_value = rlock_new_impl(type);
+
+exit:
+ return return_value;
+}
#if (defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP) || defined(MS_WINDOWS))
@@ -103,4 +149,4 @@ exit:
#ifndef _THREAD_SET_NAME_METHODDEF
#define _THREAD_SET_NAME_METHODDEF
#endif /* !defined(_THREAD_SET_NAME_METHODDEF) */
-/*[clinic end generated code: output=e978dc4615b9bc35 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b381ec5e313198e7 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_winapi.c.h b/Modules/clinic/_winapi.c.h
index f8b623fca08..bd685e75d93 100644
--- a/Modules/clinic/_winapi.c.h
+++ b/Modules/clinic/_winapi.c.h
@@ -857,6 +857,8 @@ exit:
return return_value;
}
+#if (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM))
+
PyDoc_STRVAR(_winapi_GetShortPathName__doc__,
"GetShortPathName($module, /, path)\n"
"--\n"
@@ -930,6 +932,8 @@ exit:
return return_value;
}
+#endif /* (defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)) */
+
PyDoc_STRVAR(_winapi_GetStdHandle__doc__,
"GetStdHandle($module, std_handle, /)\n"
"--\n"
@@ -1929,6 +1933,24 @@ _winapi_GetACP(PyObject *module, PyObject *Py_UNUSED(ignored))
return _winapi_GetACP_impl(module);
}
+PyDoc_STRVAR(_winapi_GetOEMCP__doc__,
+"GetOEMCP($module, /)\n"
+"--\n"
+"\n"
+"Get the current Windows ANSI code page identifier.");
+
+#define _WINAPI_GETOEMCP_METHODDEF \
+ {"GetOEMCP", (PyCFunction)_winapi_GetOEMCP, METH_NOARGS, _winapi_GetOEMCP__doc__},
+
+static PyObject *
+_winapi_GetOEMCP_impl(PyObject *module);
+
+static PyObject *
+_winapi_GetOEMCP(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _winapi_GetOEMCP_impl(module);
+}
+
PyDoc_STRVAR(_winapi_GetFileType__doc__,
"GetFileType($module, /, handle)\n"
"--\n"
@@ -2161,4 +2183,8 @@ exit:
return return_value;
}
-/*[clinic end generated code: output=6cd07628af447d0a input=a9049054013a1b77]*/
+
+#ifndef _WINAPI_GETSHORTPATHNAME_METHODDEF
+ #define _WINAPI_GETSHORTPATHNAME_METHODDEF
+#endif /* !defined(_WINAPI_GETSHORTPATHNAME_METHODDEF) */
+/*[clinic end generated code: output=4581fd481c3c6293 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/blake2module.c.h b/Modules/clinic/blake2module.c.h
index bb2e308574a..9e9cd56e569 100644
--- a/Modules/clinic/blake2module.c.h
+++ b/Modules/clinic/blake2module.c.h
@@ -10,20 +10,21 @@ preserve
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
PyDoc_STRVAR(py_blake2b_new__doc__,
-"blake2b(data=b\'\', /, *, digest_size=_blake2.blake2b.MAX_DIGEST_SIZE,\n"
+"blake2b(data=b\'\', *, digest_size=_blake2.blake2b.MAX_DIGEST_SIZE,\n"
" key=b\'\', salt=b\'\', person=b\'\', fanout=1, depth=1, leaf_size=0,\n"
" node_offset=0, node_depth=0, inner_size=0, last_node=False,\n"
-" usedforsecurity=True)\n"
+" usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new BLAKE2b hash object.");
static PyObject *
-py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
+py_blake2b_new_impl(PyTypeObject *type, PyObject *data_obj, int digest_size,
Py_buffer *key, Py_buffer *salt, Py_buffer *person,
int fanout, int depth, unsigned long leaf_size,
unsigned long long node_offset, int node_depth,
- int inner_size, int last_node, int usedforsecurity);
+ int inner_size, int last_node, int usedforsecurity,
+ PyObject *string);
static PyObject *
py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
@@ -31,7 +32,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 12
+ #define NUM_KEYWORDS 14
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -40,7 +41,7 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(digest_size), &_Py_ID(key), &_Py_ID(salt), &_Py_ID(person), &_Py_ID(fanout), &_Py_ID(depth), &_Py_ID(leaf_size), &_Py_ID(node_offset), &_Py_ID(node_depth), &_Py_ID(inner_size), &_Py_ID(last_node), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(digest_size), &_Py_ID(key), &_Py_ID(salt), &_Py_ID(person), &_Py_ID(fanout), &_Py_ID(depth), &_Py_ID(leaf_size), &_Py_ID(node_offset), &_Py_ID(node_depth), &_Py_ID(inner_size), &_Py_ID(last_node), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -49,18 +50,18 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "blake2b",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[13];
+ PyObject *argsbuf[14];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0;
- PyObject *data = NULL;
+ PyObject *data_obj = NULL;
int digest_size = HACL_HASH_BLAKE2B_OUT_BYTES;
Py_buffer key = {NULL, NULL};
Py_buffer salt = {NULL, NULL};
@@ -73,18 +74,23 @@ py_blake2b_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
int inner_size = 0;
int last_node = 0;
int usedforsecurity = 1;
+ PyObject *string = NULL;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
if (!fastargs) {
goto exit;
}
- if (nargs < 1) {
- goto skip_optional_posonly;
+ if (!noptargs) {
+ goto skip_optional_pos;
}
- noptargs--;
- data = fastargs[0];
-skip_optional_posonly:
+ if (fastargs[0]) {
+ data_obj = fastargs[0];
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
@@ -182,12 +188,18 @@ skip_optional_posonly:
goto skip_optional_kwonly;
}
}
- usedforsecurity = PyObject_IsTrue(fastargs[12]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (fastargs[12]) {
+ usedforsecurity = PyObject_IsTrue(fastargs[12]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = fastargs[13];
skip_optional_kwonly:
- return_value = py_blake2b_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity);
+ return_value = py_blake2b_new_impl(type, data_obj, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity, string);
exit:
/* Cleanup for key */
@@ -207,20 +219,21 @@ exit:
}
PyDoc_STRVAR(py_blake2s_new__doc__,
-"blake2s(data=b\'\', /, *, digest_size=_blake2.blake2s.MAX_DIGEST_SIZE,\n"
+"blake2s(data=b\'\', *, digest_size=_blake2.blake2s.MAX_DIGEST_SIZE,\n"
" key=b\'\', salt=b\'\', person=b\'\', fanout=1, depth=1, leaf_size=0,\n"
" node_offset=0, node_depth=0, inner_size=0, last_node=False,\n"
-" usedforsecurity=True)\n"
+" usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new BLAKE2s hash object.");
static PyObject *
-py_blake2s_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
+py_blake2s_new_impl(PyTypeObject *type, PyObject *data_obj, int digest_size,
Py_buffer *key, Py_buffer *salt, Py_buffer *person,
int fanout, int depth, unsigned long leaf_size,
unsigned long long node_offset, int node_depth,
- int inner_size, int last_node, int usedforsecurity);
+ int inner_size, int last_node, int usedforsecurity,
+ PyObject *string);
static PyObject *
py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
@@ -228,7 +241,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 12
+ #define NUM_KEYWORDS 14
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -237,7 +250,7 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(digest_size), &_Py_ID(key), &_Py_ID(salt), &_Py_ID(person), &_Py_ID(fanout), &_Py_ID(depth), &_Py_ID(leaf_size), &_Py_ID(node_offset), &_Py_ID(node_depth), &_Py_ID(inner_size), &_Py_ID(last_node), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(digest_size), &_Py_ID(key), &_Py_ID(salt), &_Py_ID(person), &_Py_ID(fanout), &_Py_ID(depth), &_Py_ID(leaf_size), &_Py_ID(node_offset), &_Py_ID(node_depth), &_Py_ID(inner_size), &_Py_ID(last_node), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -246,18 +259,18 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "digest_size", "key", "salt", "person", "fanout", "depth", "leaf_size", "node_offset", "node_depth", "inner_size", "last_node", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "blake2s",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[13];
+ PyObject *argsbuf[14];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0;
- PyObject *data = NULL;
+ PyObject *data_obj = NULL;
int digest_size = HACL_HASH_BLAKE2S_OUT_BYTES;
Py_buffer key = {NULL, NULL};
Py_buffer salt = {NULL, NULL};
@@ -270,18 +283,23 @@ py_blake2s_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
int inner_size = 0;
int last_node = 0;
int usedforsecurity = 1;
+ PyObject *string = NULL;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
if (!fastargs) {
goto exit;
}
- if (nargs < 1) {
- goto skip_optional_posonly;
+ if (!noptargs) {
+ goto skip_optional_pos;
}
- noptargs--;
- data = fastargs[0];
-skip_optional_posonly:
+ if (fastargs[0]) {
+ data_obj = fastargs[0];
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
@@ -379,12 +397,18 @@ skip_optional_posonly:
goto skip_optional_kwonly;
}
}
- usedforsecurity = PyObject_IsTrue(fastargs[12]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (fastargs[12]) {
+ usedforsecurity = PyObject_IsTrue(fastargs[12]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = fastargs[13];
skip_optional_kwonly:
- return_value = py_blake2s_new_impl(type, data, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity);
+ return_value = py_blake2s_new_impl(type, data_obj, digest_size, &key, &salt, &person, fanout, depth, leaf_size, node_offset, node_depth, inner_size, last_node, usedforsecurity, string);
exit:
/* Cleanup for key */
@@ -478,4 +502,4 @@ _blake2_blake2b_hexdigest(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return _blake2_blake2b_hexdigest_impl((Blake2Object *)self);
}
-/*[clinic end generated code: output=d30e8293bd8e2950 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=eed18dcfaf6f7731 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/mathmodule.c.h b/Modules/clinic/mathmodule.c.h
index 4c2c8acd8f6..9df73b187bb 100644
--- a/Modules/clinic/mathmodule.c.h
+++ b/Modules/clinic/mathmodule.c.h
@@ -108,9 +108,7 @@ PyDoc_STRVAR(math_factorial__doc__,
"factorial($module, n, /)\n"
"--\n"
"\n"
-"Find n!.\n"
-"\n"
-"Raise a ValueError if x is negative or non-integral.");
+"Find n!.");
#define MATH_FACTORIAL_METHODDEF \
{"factorial", (PyCFunction)math_factorial, METH_O, math_factorial__doc__},
@@ -1112,4 +1110,4 @@ math_ulp(PyObject *module, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=634773bd18cd3f93 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=77e7b8c161c39843 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/md5module.c.h b/Modules/clinic/md5module.c.h
index 9ca4f6528ce..f76902586dd 100644
--- a/Modules/clinic/md5module.c.h
+++ b/Modules/clinic/md5module.c.h
@@ -89,7 +89,7 @@ MD5Type_update(PyObject *self, PyObject *obj)
}
PyDoc_STRVAR(_md5_md5__doc__,
-"md5($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"md5($module, /, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new MD5 hash object; optionally initialized with a string.");
@@ -98,7 +98,8 @@ PyDoc_STRVAR(_md5_md5__doc__,
{"md5", _PyCFunction_CAST(_md5_md5), METH_FASTCALL|METH_KEYWORDS, _md5_md5__doc__},
static PyObject *
-_md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity);
+_md5_md5_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj);
static PyObject *
_md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -106,7 +107,7 @@ _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -115,7 +116,7 @@ _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -124,17 +125,18 @@ _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "md5",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *string = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string_obj = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -145,7 +147,7 @@ _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw
goto skip_optional_pos;
}
if (args[0]) {
- string = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -154,14 +156,20 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string_obj = args[2];
skip_optional_kwonly:
- return_value = _md5_md5_impl(module, string, usedforsecurity);
+ return_value = _md5_md5_impl(module, data, usedforsecurity, string_obj);
exit:
return return_value;
}
-/*[clinic end generated code: output=73f4d2034d9fcc63 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=920fe54b9ed06f92 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha1module.c.h b/Modules/clinic/sha1module.c.h
index 3e5fd1a41ce..4a58d0cd9b8 100644
--- a/Modules/clinic/sha1module.c.h
+++ b/Modules/clinic/sha1module.c.h
@@ -89,7 +89,7 @@ SHA1Type_update(PyObject *self, PyObject *obj)
}
PyDoc_STRVAR(_sha1_sha1__doc__,
-"sha1($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"sha1($module, /, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new SHA1 hash object; optionally initialized with a string.");
@@ -98,7 +98,8 @@ PyDoc_STRVAR(_sha1_sha1__doc__,
{"sha1", _PyCFunction_CAST(_sha1_sha1), METH_FASTCALL|METH_KEYWORDS, _sha1_sha1__doc__},
static PyObject *
-_sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity);
+_sha1_sha1_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj);
static PyObject *
_sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -106,7 +107,7 @@ _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -115,7 +116,7 @@ _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -124,17 +125,18 @@ _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "sha1",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *string = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string_obj = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -145,7 +147,7 @@ _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
goto skip_optional_pos;
}
if (args[0]) {
- string = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -154,14 +156,20 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string_obj = args[2];
skip_optional_kwonly:
- return_value = _sha1_sha1_impl(module, string, usedforsecurity);
+ return_value = _sha1_sha1_impl(module, data, usedforsecurity, string_obj);
exit:
return return_value;
}
-/*[clinic end generated code: output=06161e87e2d645d4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=fd5a917404b68c4f input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha2module.c.h b/Modules/clinic/sha2module.c.h
index 26612125e75..07be91e4f6c 100644
--- a/Modules/clinic/sha2module.c.h
+++ b/Modules/clinic/sha2module.c.h
@@ -169,7 +169,7 @@ SHA512Type_update(PyObject *self, PyObject *obj)
}
PyDoc_STRVAR(_sha2_sha256__doc__,
-"sha256($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"sha256($module, /, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new SHA-256 hash object; optionally initialized with a string.");
@@ -178,7 +178,8 @@ PyDoc_STRVAR(_sha2_sha256__doc__,
{"sha256", _PyCFunction_CAST(_sha2_sha256), METH_FASTCALL|METH_KEYWORDS, _sha2_sha256__doc__},
static PyObject *
-_sha2_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity);
+_sha2_sha256_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj);
static PyObject *
_sha2_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -186,7 +187,7 @@ _sha2_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -195,7 +196,7 @@ _sha2_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -204,17 +205,18 @@ _sha2_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "sha256",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *string = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string_obj = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -225,7 +227,7 @@ _sha2_sha256(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
goto skip_optional_pos;
}
if (args[0]) {
- string = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -234,19 +236,25 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string_obj = args[2];
skip_optional_kwonly:
- return_value = _sha2_sha256_impl(module, string, usedforsecurity);
+ return_value = _sha2_sha256_impl(module, data, usedforsecurity, string_obj);
exit:
return return_value;
}
PyDoc_STRVAR(_sha2_sha224__doc__,
-"sha224($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"sha224($module, /, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new SHA-224 hash object; optionally initialized with a string.");
@@ -255,7 +263,8 @@ PyDoc_STRVAR(_sha2_sha224__doc__,
{"sha224", _PyCFunction_CAST(_sha2_sha224), METH_FASTCALL|METH_KEYWORDS, _sha2_sha224__doc__},
static PyObject *
-_sha2_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity);
+_sha2_sha224_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj);
static PyObject *
_sha2_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -263,7 +272,7 @@ _sha2_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -272,7 +281,7 @@ _sha2_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -281,17 +290,18 @@ _sha2_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "sha224",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *string = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string_obj = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -302,7 +312,7 @@ _sha2_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
goto skip_optional_pos;
}
if (args[0]) {
- string = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -311,19 +321,25 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string_obj = args[2];
skip_optional_kwonly:
- return_value = _sha2_sha224_impl(module, string, usedforsecurity);
+ return_value = _sha2_sha224_impl(module, data, usedforsecurity, string_obj);
exit:
return return_value;
}
PyDoc_STRVAR(_sha2_sha512__doc__,
-"sha512($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"sha512($module, /, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new SHA-512 hash object; optionally initialized with a string.");
@@ -332,7 +348,8 @@ PyDoc_STRVAR(_sha2_sha512__doc__,
{"sha512", _PyCFunction_CAST(_sha2_sha512), METH_FASTCALL|METH_KEYWORDS, _sha2_sha512__doc__},
static PyObject *
-_sha2_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity);
+_sha2_sha512_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj);
static PyObject *
_sha2_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -340,7 +357,7 @@ _sha2_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -349,7 +366,7 @@ _sha2_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -358,17 +375,18 @@ _sha2_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "sha512",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *string = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string_obj = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -379,7 +397,7 @@ _sha2_sha512(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
goto skip_optional_pos;
}
if (args[0]) {
- string = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -388,19 +406,25 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string_obj = args[2];
skip_optional_kwonly:
- return_value = _sha2_sha512_impl(module, string, usedforsecurity);
+ return_value = _sha2_sha512_impl(module, data, usedforsecurity, string_obj);
exit:
return return_value;
}
PyDoc_STRVAR(_sha2_sha384__doc__,
-"sha384($module, /, string=b\'\', *, usedforsecurity=True)\n"
+"sha384($module, /, data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new SHA-384 hash object; optionally initialized with a string.");
@@ -409,7 +433,8 @@ PyDoc_STRVAR(_sha2_sha384__doc__,
{"sha384", _PyCFunction_CAST(_sha2_sha384), METH_FASTCALL|METH_KEYWORDS, _sha2_sha384__doc__},
static PyObject *
-_sha2_sha384_impl(PyObject *module, PyObject *string, int usedforsecurity);
+_sha2_sha384_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj);
static PyObject *
_sha2_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
@@ -417,7 +442,7 @@ _sha2_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -426,7 +451,7 @@ _sha2_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(string), &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -435,17 +460,18 @@ _sha2_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"string", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "sha384",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
- PyObject *string = NULL;
+ PyObject *data = NULL;
int usedforsecurity = 1;
+ PyObject *string_obj = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@@ -456,7 +482,7 @@ _sha2_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject
goto skip_optional_pos;
}
if (args[0]) {
- string = args[0];
+ data = args[0];
if (!--noptargs) {
goto skip_optional_pos;
}
@@ -465,14 +491,20 @@ skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(args[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (args[1]) {
+ usedforsecurity = PyObject_IsTrue(args[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string_obj = args[2];
skip_optional_kwonly:
- return_value = _sha2_sha384_impl(module, string, usedforsecurity);
+ return_value = _sha2_sha384_impl(module, data, usedforsecurity, string_obj);
exit:
return return_value;
}
-/*[clinic end generated code: output=af11090855b7c85a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=90625b237c774a9f input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha3module.c.h b/Modules/clinic/sha3module.c.h
index 25f72b74f80..121be2c0758 100644
--- a/Modules/clinic/sha3module.c.h
+++ b/Modules/clinic/sha3module.c.h
@@ -10,13 +10,14 @@ preserve
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
PyDoc_STRVAR(py_sha3_new__doc__,
-"sha3_224(data=b\'\', /, *, usedforsecurity=True)\n"
+"sha3_224(data=b\'\', *, usedforsecurity=True, string=None)\n"
"--\n"
"\n"
"Return a new SHA3 hash object.");
static PyObject *
-py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity);
+py_sha3_new_impl(PyTypeObject *type, PyObject *data_obj, int usedforsecurity,
+ PyObject *string);
static PyObject *
py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
@@ -24,7 +25,7 @@ py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 1
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@@ -33,7 +34,7 @@ py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(usedforsecurity), },
+ .ob_item = { &_Py_ID(data), &_Py_ID(usedforsecurity), &_Py_ID(string), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@@ -42,40 +43,51 @@ py_sha3_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"", "usedforsecurity", NULL};
+ static const char * const _keywords[] = {"data", "usedforsecurity", "string", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "sha3_224",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 0;
- PyObject *data = NULL;
+ PyObject *data_obj = NULL;
int usedforsecurity = 1;
+ PyObject *string = NULL;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser,
/*minpos*/ 0, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
if (!fastargs) {
goto exit;
}
- if (nargs < 1) {
- goto skip_optional_posonly;
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (fastargs[0]) {
+ data_obj = fastargs[0];
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
}
- noptargs--;
- data = fastargs[0];
-skip_optional_posonly:
+skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
- usedforsecurity = PyObject_IsTrue(fastargs[1]);
- if (usedforsecurity < 0) {
- goto exit;
+ if (fastargs[1]) {
+ usedforsecurity = PyObject_IsTrue(fastargs[1]);
+ if (usedforsecurity < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
}
+ string = fastargs[2];
skip_optional_kwonly:
- return_value = py_sha3_new_impl(type, data, usedforsecurity);
+ return_value = py_sha3_new_impl(type, data_obj, usedforsecurity, string);
exit:
return return_value;
@@ -158,24 +170,57 @@ _sha3_sha3_224_update(PyObject *self, PyObject *data)
}
PyDoc_STRVAR(_sha3_shake_128_digest__doc__,
-"digest($self, length, /)\n"
+"digest($self, /, length)\n"
"--\n"
"\n"
"Return the digest value as a bytes object.");
#define _SHA3_SHAKE_128_DIGEST_METHODDEF \
- {"digest", (PyCFunction)_sha3_shake_128_digest, METH_O, _sha3_shake_128_digest__doc__},
+ {"digest", _PyCFunction_CAST(_sha3_shake_128_digest), METH_FASTCALL|METH_KEYWORDS, _sha3_shake_128_digest__doc__},
static PyObject *
_sha3_shake_128_digest_impl(SHA3object *self, unsigned long length);
static PyObject *
-_sha3_shake_128_digest(PyObject *self, PyObject *arg)
+_sha3_shake_128_digest(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
+ .ob_item = { &_Py_ID(length), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"length", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "digest",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[1];
unsigned long length;
- if (!_PyLong_UnsignedLong_Converter(arg, &length)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+ /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!_PyLong_UnsignedLong_Converter(args[0], &length)) {
goto exit;
}
return_value = _sha3_shake_128_digest_impl((SHA3object *)self, length);
@@ -185,24 +230,57 @@ exit:
}
PyDoc_STRVAR(_sha3_shake_128_hexdigest__doc__,
-"hexdigest($self, length, /)\n"
+"hexdigest($self, /, length)\n"
"--\n"
"\n"
"Return the digest value as a string of hexadecimal digits.");
#define _SHA3_SHAKE_128_HEXDIGEST_METHODDEF \
- {"hexdigest", (PyCFunction)_sha3_shake_128_hexdigest, METH_O, _sha3_shake_128_hexdigest__doc__},
+ {"hexdigest", _PyCFunction_CAST(_sha3_shake_128_hexdigest), METH_FASTCALL|METH_KEYWORDS, _sha3_shake_128_hexdigest__doc__},
static PyObject *
_sha3_shake_128_hexdigest_impl(SHA3object *self, unsigned long length);
static PyObject *
-_sha3_shake_128_hexdigest(PyObject *self, PyObject *arg)
+_sha3_shake_128_hexdigest(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
+ .ob_item = { &_Py_ID(length), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"length", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "hexdigest",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[1];
unsigned long length;
- if (!_PyLong_UnsignedLong_Converter(arg, &length)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+ /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!_PyLong_UnsignedLong_Converter(args[0], &length)) {
goto exit;
}
return_value = _sha3_shake_128_hexdigest_impl((SHA3object *)self, length);
@@ -210,4 +288,4 @@ _sha3_shake_128_hexdigest(PyObject *self, PyObject *arg)
exit:
return return_value;
}
-/*[clinic end generated code: output=5b3ac1c06c6899ea input=a9049054013a1b77]*/
+/*[clinic end generated code: output=65e437799472b89f input=a9049054013a1b77]*/
diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h
index 2710f65a840..146a7e25001 100644
--- a/Modules/clinic/zlibmodule.c.h
+++ b/Modules/clinic/zlibmodule.c.h
@@ -1044,6 +1044,65 @@ exit:
return return_value;
}
+PyDoc_STRVAR(zlib_adler32_combine__doc__,
+"adler32_combine($module, adler1, adler2, len2, /)\n"
+"--\n"
+"\n"
+"Combine two Adler-32 checksums into one.\n"
+"\n"
+" adler1\n"
+" Adler-32 checksum for sequence A\n"
+" adler2\n"
+" Adler-32 checksum for sequence B\n"
+" len2\n"
+" Length of sequence B\n"
+"\n"
+"Given the Adler-32 checksum \'adler1\' of a sequence A and the\n"
+"Adler-32 checksum \'adler2\' of a sequence B of length \'len2\',\n"
+"return the Adler-32 checksum of A and B concatenated.");
+
+#define ZLIB_ADLER32_COMBINE_METHODDEF \
+ {"adler32_combine", _PyCFunction_CAST(zlib_adler32_combine), METH_FASTCALL, zlib_adler32_combine__doc__},
+
+static unsigned int
+zlib_adler32_combine_impl(PyObject *module, unsigned int adler1,
+ unsigned int adler2, PyObject *len2);
+
+static PyObject *
+zlib_adler32_combine(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ unsigned int adler1;
+ unsigned int adler2;
+ PyObject *len2;
+ unsigned int _return_value;
+
+ if (!_PyArg_CheckPositional("adler32_combine", nargs, 3, 3)) {
+ goto exit;
+ }
+ adler1 = (unsigned int)PyLong_AsUnsignedLongMask(args[0]);
+ if (adler1 == (unsigned int)-1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ adler2 = (unsigned int)PyLong_AsUnsignedLongMask(args[1]);
+ if (adler2 == (unsigned int)-1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ if (!PyLong_Check(args[2])) {
+ _PyArg_BadArgument("adler32_combine", "argument 3", "int", args[2]);
+ goto exit;
+ }
+ len2 = args[2];
+ _return_value = zlib_adler32_combine_impl(module, adler1, adler2, len2);
+ if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyLong_FromUnsignedLong((unsigned long)_return_value);
+
+exit:
+ return return_value;
+}
+
PyDoc_STRVAR(zlib_crc32__doc__,
"crc32($module, data, value=0, /)\n"
"--\n"
@@ -1098,6 +1157,65 @@ exit:
return return_value;
}
+PyDoc_STRVAR(zlib_crc32_combine__doc__,
+"crc32_combine($module, crc1, crc2, len2, /)\n"
+"--\n"
+"\n"
+"Combine two CRC-32 checksums into one.\n"
+"\n"
+" crc1\n"
+" CRC-32 checksum for sequence A\n"
+" crc2\n"
+" CRC-32 checksum for sequence B\n"
+" len2\n"
+" Length of sequence B\n"
+"\n"
+"Given the CRC-32 checksum \'crc1\' of a sequence A and the\n"
+"CRC-32 checksum \'crc2\' of a sequence B of length \'len2\',\n"
+"return the CRC-32 checksum of A and B concatenated.");
+
+#define ZLIB_CRC32_COMBINE_METHODDEF \
+ {"crc32_combine", _PyCFunction_CAST(zlib_crc32_combine), METH_FASTCALL, zlib_crc32_combine__doc__},
+
+static unsigned int
+zlib_crc32_combine_impl(PyObject *module, unsigned int crc1,
+ unsigned int crc2, PyObject *len2);
+
+static PyObject *
+zlib_crc32_combine(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ unsigned int crc1;
+ unsigned int crc2;
+ PyObject *len2;
+ unsigned int _return_value;
+
+ if (!_PyArg_CheckPositional("crc32_combine", nargs, 3, 3)) {
+ goto exit;
+ }
+ crc1 = (unsigned int)PyLong_AsUnsignedLongMask(args[0]);
+ if (crc1 == (unsigned int)-1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ crc2 = (unsigned int)PyLong_AsUnsignedLongMask(args[1]);
+ if (crc2 == (unsigned int)-1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ if (!PyLong_Check(args[2])) {
+ _PyArg_BadArgument("crc32_combine", "argument 3", "int", args[2]);
+ goto exit;
+ }
+ len2 = args[2];
+ _return_value = zlib_crc32_combine_impl(module, crc1, crc2, len2);
+ if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) {
+ goto exit;
+ }
+ return_value = PyLong_FromUnsignedLong((unsigned long)_return_value);
+
+exit:
+ return return_value;
+}
+
#ifndef ZLIB_COMPRESS_COPY_METHODDEF
#define ZLIB_COMPRESS_COPY_METHODDEF
#endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */
@@ -1121,4 +1239,4 @@ exit:
#ifndef ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF
#define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF
#endif /* !defined(ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF) */
-/*[clinic end generated code: output=33938c7613a8c1c7 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=3f7692eb3b5d5a0c input=a9049054013a1b77]*/
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index d49ce794d88..73bea8172c7 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -6,7 +6,6 @@
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_runtime.h" // _Py_ID()
#include "pycore_signal.h" // Py_NSIG
-#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
#include "pycore_time.h" // _PyTime_FromSecondsObject()
#include "pycore_traceback.h" // _Py_DumpTracebackThreads
#ifdef HAVE_UNISTD_H
@@ -98,7 +97,7 @@ faulthandler_get_fileno(PyObject **file_ptr)
PyObject *file = *file_ptr;
if (file == NULL || file == Py_None) {
- file = _PySys_GetRequiredAttr(&_Py_ID(stderr));
+ file = PySys_GetAttr(&_Py_ID(stderr));
if (file == NULL) {
return -1;
}
@@ -1069,18 +1068,6 @@ faulthandler_suppress_crash_report(void)
#endif
}
-static PyObject* _Py_NO_SANITIZE_UNDEFINED
-faulthandler_read_null(PyObject *self, PyObject *args)
-{
- volatile int *x;
- volatile int y;
-
- faulthandler_suppress_crash_report();
- x = NULL;
- y = *x;
- return PyLong_FromLong(y);
-
-}
static void
faulthandler_raise_sigsegv(void)
@@ -1158,23 +1145,12 @@ faulthandler_fatal_error_c_thread(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-static PyObject* _Py_NO_SANITIZE_UNDEFINED
+static PyObject*
faulthandler_sigfpe(PyObject *self, PyObject *Py_UNUSED(dummy))
{
faulthandler_suppress_crash_report();
-
- /* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
- PowerPC. Use volatile to disable compile-time optimizations. */
- volatile int x = 1, y = 0, z;
- z = x / y;
-
- /* If the division by zero didn't raise a SIGFPE (e.g. on PowerPC),
- raise it manually. */
raise(SIGFPE);
-
- /* This line is never reached, but we pretend to make something with z
- to silence a compiler warning. */
- return PyLong_FromLong(z);
+ Py_UNREACHABLE();
}
static PyObject *
@@ -1316,10 +1292,6 @@ static PyMethodDef module_methods[] = {
"Unregister the handler of the signal "
"'signum' registered by register().")},
#endif
- {"_read_null", faulthandler_read_null, METH_NOARGS,
- PyDoc_STR("_read_null($module, /)\n--\n\n"
- "Read from NULL, raise "
- "a SIGSEGV or SIGBUS signal depending on the platform.")},
{"_sigsegv", faulthandler_sigsegv, METH_VARARGS,
PyDoc_STR("_sigsegv($module, release_gil=False, /)\n--\n\n"
"Raise a SIGSEGV signal.")},
diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
index 220ee9ecdff..90363b9dca3 100644
--- a/Modules/fcntlmodule.c
+++ b/Modules/fcntlmodule.c
@@ -93,29 +93,54 @@ fcntl_fcntl_impl(PyObject *module, int fd, int code, PyObject *arg)
return NULL;
}
Py_ssize_t len = view.len;
- if (len > FCNTL_BUFSZ) {
- PyErr_SetString(PyExc_ValueError,
- "fcntl argument 3 is too long");
+ if (len <= FCNTL_BUFSZ) {
+ memcpy(buf, view.buf, len);
+ memcpy(buf + len, guard, GUARDSZ);
PyBuffer_Release(&view);
- return NULL;
- }
- memcpy(buf, view.buf, len);
- memcpy(buf + len, guard, GUARDSZ);
- PyBuffer_Release(&view);
- do {
- Py_BEGIN_ALLOW_THREADS
- ret = fcntl(fd, code, buf);
- Py_END_ALLOW_THREADS
- } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- if (ret < 0) {
- return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = fcntl(fd, code, buf);
+ Py_END_ALLOW_THREADS
+ } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (ret < 0) {
+ return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
+ }
+ if (memcmp(buf + len, guard, GUARDSZ) != 0) {
+ PyErr_SetString(PyExc_SystemError, "buffer overflow");
+ return NULL;
+ }
+ return PyBytes_FromStringAndSize(buf, len);
}
- if (memcmp(buf + len, guard, GUARDSZ) != 0) {
- PyErr_SetString(PyExc_SystemError, "buffer overflow");
- return NULL;
+ else {
+ PyObject *result = PyBytes_FromStringAndSize(NULL, len);
+ if (result == NULL) {
+ PyBuffer_Release(&view);
+ return NULL;
+ }
+ char *ptr = PyBytes_AsString(result);
+ memcpy(ptr, view.buf, len);
+ PyBuffer_Release(&view);
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = fcntl(fd, code, ptr);
+ Py_END_ALLOW_THREADS
+ } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (ret < 0) {
+ if (!async_err) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ }
+ Py_DECREF(result);
+ return NULL;
+ }
+ if (ptr[len] != '\0') {
+ PyErr_SetString(PyExc_SystemError, "buffer overflow");
+ Py_DECREF(result);
+ return NULL;
+ }
+ return result;
}
- return PyBytes_FromStringAndSize(buf, len);
#undef FCNTL_BUFSZ
}
PyErr_Format(PyExc_TypeError,
@@ -251,29 +276,54 @@ fcntl_ioctl_impl(PyObject *module, int fd, unsigned long code, PyObject *arg,
return NULL;
}
Py_ssize_t len = view.len;
- if (len > IOCTL_BUFSZ) {
- PyErr_SetString(PyExc_ValueError,
- "ioctl argument 3 is too long");
+ if (len <= IOCTL_BUFSZ) {
+ memcpy(buf, view.buf, len);
+ memcpy(buf + len, guard, GUARDSZ);
PyBuffer_Release(&view);
- return NULL;
- }
- memcpy(buf, view.buf, len);
- memcpy(buf + len, guard, GUARDSZ);
- PyBuffer_Release(&view);
- do {
- Py_BEGIN_ALLOW_THREADS
- ret = ioctl(fd, code, buf);
- Py_END_ALLOW_THREADS
- } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
- if (ret < 0) {
- return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = ioctl(fd, code, buf);
+ Py_END_ALLOW_THREADS
+ } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (ret < 0) {
+ return !async_err ? PyErr_SetFromErrno(PyExc_OSError) : NULL;
+ }
+ if (memcmp(buf + len, guard, GUARDSZ) != 0) {
+ PyErr_SetString(PyExc_SystemError, "buffer overflow");
+ return NULL;
+ }
+ return PyBytes_FromStringAndSize(buf, len);
}
- if (memcmp(buf + len, guard, GUARDSZ) != 0) {
- PyErr_SetString(PyExc_SystemError, "buffer overflow");
- return NULL;
+ else {
+ PyObject *result = PyBytes_FromStringAndSize(NULL, len);
+ if (result == NULL) {
+ PyBuffer_Release(&view);
+ return NULL;
+ }
+ char *ptr = PyBytes_AsString(result);
+ memcpy(ptr, view.buf, len);
+ PyBuffer_Release(&view);
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = ioctl(fd, code, ptr);
+ Py_END_ALLOW_THREADS
+ } while (ret == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (ret < 0) {
+ if (!async_err) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ }
+ Py_DECREF(result);
+ return NULL;
+ }
+ if (ptr[len] != '\0') {
+ PyErr_SetString(PyExc_SystemError, "buffer overflow");
+ Py_DECREF(result);
+ return NULL;
+ }
+ return result;
}
- return PyBytes_FromStringAndSize(buf, len);
#undef IOCTL_BUFSZ
}
PyErr_Format(PyExc_TypeError,
diff --git a/Modules/hashlib.h b/Modules/hashlib.h
index 7105e68af7b..a80b195a765 100644
--- a/Modules/hashlib.h
+++ b/Modules/hashlib.h
@@ -76,3 +76,32 @@
* to allow the user to optimize based on the platform they're using. */
#define HASHLIB_GIL_MINSIZE 2048
+static inline int
+_Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string)
+{
+ if (data != NULL && string == NULL) {
+ // called as H(data) or H(data=...)
+ *res = data;
+ return 1;
+ }
+ else if (data == NULL && string != NULL) {
+ // called as H(string=...)
+ *res = string;
+ return 1;
+ }
+ else if (data == NULL && string == NULL) {
+ // fast path when no data is given
+ assert(!PyErr_Occurred());
+ *res = NULL;
+ return 0;
+ }
+ else {
+ // called as H(data=..., string)
+ *res = NULL;
+ PyErr_SetString(PyExc_TypeError,
+ "'data' and 'string' are mutually exclusive "
+ "and support for 'string' keyword parameter "
+ "is slated for removal in a future version.");
+ return -1;
+ }
+}
diff --git a/Modules/main.c b/Modules/main.c
index ea1239ecc57..74e48c94732 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -128,7 +128,7 @@ pymain_get_importer(const wchar_t *filename, PyObject **importer_p, int *exitcod
{
PyObject *sys_path0 = NULL, *importer;
- sys_path0 = PyUnicode_FromWideChar(filename, wcslen(filename));
+ sys_path0 = PyUnicode_FromWideChar(filename, -1);
if (sys_path0 == NULL) {
goto error;
}
@@ -269,13 +269,14 @@ error:
static int
-pymain_start_pyrepl_no_main(void)
+pymain_start_pyrepl(int pythonstartup)
{
int res = 0;
PyObject *console = NULL;
PyObject *empty_tuple = NULL;
PyObject *kwargs = NULL;
PyObject *console_result = NULL;
+ PyObject *main_module = NULL;
PyObject *pyrepl = PyImport_ImportModule("_pyrepl.main");
if (pyrepl == NULL) {
@@ -299,7 +300,13 @@ pymain_start_pyrepl_no_main(void)
res = pymain_exit_err_print();
goto done;
}
- if (!PyDict_SetItemString(kwargs, "pythonstartup", _PyLong_GetOne())) {
+ main_module = PyImport_AddModuleRef("__main__");
+ if (main_module == NULL) {
+ res = pymain_exit_err_print();
+ goto done;
+ }
+ if (!PyDict_SetItemString(kwargs, "mainmodule", main_module)
+ && !PyDict_SetItemString(kwargs, "pythonstartup", pythonstartup ? Py_True : Py_False)) {
console_result = PyObject_Call(console, empty_tuple, kwargs);
if (console_result == NULL) {
res = pymain_exit_err_print();
@@ -311,6 +318,7 @@ done:
Py_XDECREF(empty_tuple);
Py_XDECREF(console);
Py_XDECREF(pyrepl);
+ Py_XDECREF(main_module);
return res;
}
@@ -328,7 +336,7 @@ pymain_run_module(const wchar_t *modname, int set_argv0)
fprintf(stderr, "Could not import runpy._run_module_as_main\n");
return pymain_exit_err_print();
}
- module = PyUnicode_FromWideChar(modname, wcslen(modname));
+ module = PyUnicode_FromWideChar(modname, -1);
if (module == NULL) {
fprintf(stderr, "Could not convert module name to unicode\n");
Py_DECREF(runmodule);
@@ -439,7 +447,7 @@ pymain_run_startup(PyConfig *config, int *exitcode)
if (env == NULL || env[0] == L'\0') {
return 0;
}
- startup = PyUnicode_FromWideChar(env, wcslen(env));
+ startup = PyUnicode_FromWideChar(env, -1);
if (startup == NULL) {
goto error;
}
@@ -489,16 +497,13 @@ error:
static int
pymain_run_interactive_hook(int *exitcode)
{
- PyObject *hook = PyImport_ImportModuleAttrString("sys",
- "__interactivehook__");
- if (hook == NULL) {
- if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
- // no sys.__interactivehook__ attribute
- PyErr_Clear();
- return 0;
- }
+ PyObject *hook;
+ if (PySys_GetOptionalAttrString("__interactivehook__", &hook) < 0) {
goto error;
}
+ if (hook == NULL) {
+ return 0;
+ }
if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) {
goto error;
@@ -562,7 +567,7 @@ pymain_run_stdin(PyConfig *config)
int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
return (run != 0);
}
- return pymain_run_module(L"_pyrepl", 0);
+ return pymain_start_pyrepl(0);
}
@@ -595,7 +600,7 @@ pymain_repl(PyConfig *config, int *exitcode)
*exitcode = (run != 0);
return;
}
- int run = pymain_start_pyrepl_no_main();
+ int run = pymain_start_pyrepl(1);
*exitcode = (run != 0);
return;
}
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 11d9b7418a2..71d9c1387f5 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -2008,13 +2008,11 @@ math.factorial
/
Find n!.
-
-Raise a ValueError if x is negative or non-integral.
[clinic start generated code]*/
static PyObject *
math_factorial(PyObject *module, PyObject *arg)
-/*[clinic end generated code: output=6686f26fae00e9ca input=713fb771677e8c31]*/
+/*[clinic end generated code: output=6686f26fae00e9ca input=366cc321df3d4773]*/
{
long x, two_valuation;
int overflow;
@@ -2163,6 +2161,27 @@ math_ldexp_impl(PyObject *module, double x, PyObject *i)
} else {
errno = 0;
r = ldexp(x, (int)exp);
+#ifdef _MSC_VER
+ if (DBL_MIN > r && r > -DBL_MIN) {
+ /* Denormal (or zero) results can be incorrectly rounded here (rather,
+ truncated). Fixed in newer versions of the C runtime, included
+ with Windows 11. */
+ int original_exp;
+ frexp(x, &original_exp);
+ if (original_exp > DBL_MIN_EXP) {
+ /* Shift down to the smallest normal binade. No bits lost. */
+ int shift = DBL_MIN_EXP - original_exp;
+ x = ldexp(x, shift);
+ exp -= shift;
+ }
+ /* Multiplying by 2**exp finishes the job, and the HW will round as
+ appropriate. Note: if exp < -DBL_MANT_DIG, all of x is shifted
+ to be < 0.5ULP of smallest denorm, so should be thrown away. If
+ exp is so very negative that ldexp underflows to 0, that's fine;
+ no need to check in advance. */
+ r = x*ldexp(1.0, (int)exp);
+ }
+#endif
if (isinf(r))
errno = ERANGE;
}
diff --git a/Modules/md5module.c b/Modules/md5module.c
index c36eb41d4d2..9b5ea2d6e02 100644
--- a/Modules/md5module.c
+++ b/Modules/md5module.c
@@ -276,17 +276,24 @@ static PyType_Spec md5_type_spec = {
/*[clinic input]
_md5.md5
- string: object(c_default="NULL") = b''
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string as string_obj: object(c_default="NULL") = None
Return a new MD5 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
-_md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity)
-/*[clinic end generated code: output=587071f76254a4ac input=7a144a1905636985]*/
+_md5_md5_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj)
+/*[clinic end generated code: output=d45e187d3d16f3a8 input=7ea5c5366dbb44bf]*/
{
+ PyObject *string;
+ if (_Py_hashlib_data_argument(&string, data, string_obj) < 0) {
+ return NULL;
+ }
+
MD5object *new;
Py_buffer buf;
diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c
index 6a385562845..7c4eb05488e 100644
--- a/Modules/mmapmodule.c
+++ b/Modules/mmapmodule.c
@@ -290,6 +290,24 @@ filter_page_exception_method(mmap_object *self, EXCEPTION_POINTERS *ptrs,
}
return EXCEPTION_CONTINUE_SEARCH;
}
+
+static void
+_PyErr_SetFromNTSTATUS(ULONG status)
+{
+#if defined(MS_WINDOWS_DESKTOP) || defined(MS_WINDOWS_SYSTEM)
+ PyErr_SetFromWindowsErr(LsaNtStatusToWinError((NTSTATUS)status));
+#else
+ if (status & 0x80000000) {
+ // HRESULT-shaped codes are supported by PyErr_SetFromWindowsErr
+ PyErr_SetFromWindowsErr((int)status);
+ }
+ else {
+ // No mapping for NTSTATUS values, so just return it for diagnostic purposes
+ // If we provide it as winerror it could incorrectly change the type of the exception.
+ PyErr_Format(PyExc_OSError, "Operating system error NTSTATUS=0x%08lX", status);
+ }
+#endif
+}
#endif
#if defined(MS_WINDOWS) && !defined(DONT_USE_SEH)
@@ -303,9 +321,7 @@ do { \
assert(record.ExceptionCode == EXCEPTION_IN_PAGE_ERROR || \
record.ExceptionCode == EXCEPTION_ACCESS_VIOLATION); \
if (record.ExceptionCode == EXCEPTION_IN_PAGE_ERROR) { \
- NTSTATUS status = (NTSTATUS) record.ExceptionInformation[2]; \
- ULONG code = LsaNtStatusToWinError(status); \
- PyErr_SetFromWindowsErr(code); \
+ _PyErr_SetFromNTSTATUS((ULONG)record.ExceptionInformation[2]); \
} \
else if (record.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { \
PyErr_SetFromWindowsErr(ERROR_NOACCESS); \
@@ -332,9 +348,7 @@ do { \
assert(record.ExceptionCode == EXCEPTION_IN_PAGE_ERROR || \
record.ExceptionCode == EXCEPTION_ACCESS_VIOLATION); \
if (record.ExceptionCode == EXCEPTION_IN_PAGE_ERROR) { \
- NTSTATUS status = (NTSTATUS) record.ExceptionInformation[2]; \
- ULONG code = LsaNtStatusToWinError(status); \
- PyErr_SetFromWindowsErr(code); \
+ _PyErr_SetFromNTSTATUS((ULONG)record.ExceptionInformation[2]); \
} \
else if (record.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { \
PyErr_SetFromWindowsErr(ERROR_NOACCESS); \
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 9cc0533f0dc..588894adeac 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -1782,7 +1782,7 @@ convertenviron(void)
return NULL;
}
#ifdef MS_WINDOWS
- v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
+ v = PyUnicode_FromWideChar(p+1, -1);
#else
v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
#endif
@@ -5052,7 +5052,7 @@ os__getfullpathname_impl(PyObject *module, path_t *path)
return PyErr_NoMemory();
}
- PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
+ PyObject *str = PyUnicode_FromWideChar(abspath, -1);
PyMem_RawFree(abspath);
if (str == NULL) {
return NULL;
@@ -5168,7 +5168,7 @@ os__findfirstfile_impl(PyObject *module, path_t *path)
}
wRealFileName = wFileData.cFileName;
- result = PyUnicode_FromWideChar(wRealFileName, wcslen(wRealFileName));
+ result = PyUnicode_FromWideChar(wRealFileName, -1);
FindClose(hFindFile);
return result;
}
@@ -5212,7 +5212,7 @@ os__getvolumepathname_impl(PyObject *module, path_t *path)
result = win32_error_object("_getvolumepathname", path->object);
goto exit;
}
- result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
+ result = PyUnicode_FromWideChar(mountpath, -1);
if (PyBytes_Check(path->object))
Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
@@ -5736,6 +5736,9 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
+ // For API sets that don't support these APIs, we have no choice
+ // but to silently create a directory with default ACL.
+#if defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM)
if (mode == 0700 /* 0o700 */) {
ULONG sdSize;
pSecAttr = &secAttr;
@@ -5751,6 +5754,7 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
error = GetLastError();
}
}
+#endif
if (!error) {
result = CreateDirectoryW(path->wide, pSecAttr);
if (secAttr.lpSecurityDescriptor &&
diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c
index 2240e2078b2..c5a8cead19a 100644
--- a/Modules/pwdmodule.c
+++ b/Modules/pwdmodule.c
@@ -301,18 +301,33 @@ pwd_getpwall_impl(PyObject *module)
struct passwd *p;
if ((d = PyList_New(0)) == NULL)
return NULL;
+
+#ifdef Py_GIL_DISABLED
+ static PyMutex getpwall_mutex = {0};
+ PyMutex_Lock(&getpwall_mutex);
+#endif
+ int failure = 0;
+ PyObject *v = NULL;
setpwent();
while ((p = getpwent()) != NULL) {
- PyObject *v = mkpwent(module, p);
+ v = mkpwent(module, p);
if (v == NULL || PyList_Append(d, v) != 0) {
- Py_XDECREF(v);
- Py_DECREF(d);
- endpwent();
- return NULL;
+ /* NOTE: cannot dec-ref here, while holding the mutex. */
+ failure = 1;
+ goto done;
}
Py_DECREF(v);
}
+
+done:
endpwent();
+#ifdef Py_GIL_DISABLED
+ PyMutex_Unlock(&getpwall_mutex);
+#endif
+ if (failure) {
+ Py_XDECREF(v);
+ Py_CLEAR(d);
+ }
return d;
}
#endif
diff --git a/Modules/sha1module.c b/Modules/sha1module.c
index f4a00cdb422..a746bf74f8d 100644
--- a/Modules/sha1module.c
+++ b/Modules/sha1module.c
@@ -272,19 +272,25 @@ static PyType_Spec sha1_type_spec = {
/*[clinic input]
_sha1.sha1
- string: object(c_default="NULL") = b''
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string as string_obj: object(c_default="NULL") = None
Return a new SHA1 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
-_sha1_sha1_impl(PyObject *module, PyObject *string, int usedforsecurity)
-/*[clinic end generated code: output=6f8b3af05126e18e input=bd54b68e2bf36a8a]*/
+_sha1_sha1_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj)
+/*[clinic end generated code: output=0d453775924f88a7 input=807f25264e0ac656]*/
{
SHA1object *new;
Py_buffer buf;
+ PyObject *string;
+ if (_Py_hashlib_data_argument(&string, data, string_obj) < 0) {
+ return NULL;
+ }
if (string) {
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
diff --git a/Modules/sha2module.c b/Modules/sha2module.c
index e88d7cb2d45..72931910c5d 100644
--- a/Modules/sha2module.c
+++ b/Modules/sha2module.c
@@ -594,18 +594,24 @@ static PyType_Spec sha512_type_spec = {
/*[clinic input]
_sha2.sha256
- string: object(c_default="NULL") = b''
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string as string_obj: object(c_default="NULL") = None
Return a new SHA-256 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
-_sha2_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity)
-/*[clinic end generated code: output=243c9dd289931f87 input=6249da1de607280a]*/
+_sha2_sha256_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj)
+/*[clinic end generated code: output=49828a7bcd418f45 input=9ce1d70e669abc14]*/
{
Py_buffer buf;
+ PyObject *string;
+ if (_Py_hashlib_data_argument(&string, data, string_obj) < 0) {
+ return NULL;
+ }
if (string) {
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
@@ -651,18 +657,25 @@ _sha2_sha256_impl(PyObject *module, PyObject *string, int usedforsecurity)
/*[clinic input]
_sha2.sha224
- string: object(c_default="NULL") = b''
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string as string_obj: object(c_default="NULL") = None
Return a new SHA-224 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
-_sha2_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity)
-/*[clinic end generated code: output=68191f232e4a3843 input=c42bcba47fd7d2b7]*/
+_sha2_sha224_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj)
+/*[clinic end generated code: output=2163cb03b6cf6157 input=612f7682a889bc2a]*/
{
Py_buffer buf;
+ PyObject *string;
+ if (_Py_hashlib_data_argument(&string, data, string_obj) < 0) {
+ return NULL;
+ }
+
if (string) {
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
}
@@ -706,19 +719,25 @@ _sha2_sha224_impl(PyObject *module, PyObject *string, int usedforsecurity)
/*[clinic input]
_sha2.sha512
- string: object(c_default="NULL") = b''
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string as string_obj: object(c_default="NULL") = None
Return a new SHA-512 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
-_sha2_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity)
-/*[clinic end generated code: output=d55c8996eca214d7 input=0576ae2a6ebfad25]*/
+_sha2_sha512_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj)
+/*[clinic end generated code: output=cc3fcfce001a4538 input=19c9f2c06d59563a]*/
{
SHA512object *new;
Py_buffer buf;
+ PyObject *string;
+ if (_Py_hashlib_data_argument(&string, data, string_obj) < 0) {
+ return NULL;
+ }
sha2_state *state = sha2_get_state(module);
@@ -763,19 +782,25 @@ _sha2_sha512_impl(PyObject *module, PyObject *string, int usedforsecurity)
/*[clinic input]
_sha2.sha384
- string: object(c_default="NULL") = b''
+ data: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string as string_obj: object(c_default="NULL") = None
Return a new SHA-384 hash object; optionally initialized with a string.
[clinic start generated code]*/
static PyObject *
-_sha2_sha384_impl(PyObject *module, PyObject *string, int usedforsecurity)
-/*[clinic end generated code: output=b29a0d81d51d1368 input=4e9199d8de0d2f9b]*/
+_sha2_sha384_impl(PyObject *module, PyObject *data, int usedforsecurity,
+ PyObject *string_obj)
+/*[clinic end generated code: output=b6e3db593b5a0330 input=9fd50c942ad9e0bf]*/
{
SHA512object *new;
Py_buffer buf;
+ PyObject *string;
+ if (_Py_hashlib_data_argument(&string, data, string_obj) < 0) {
+ return NULL;
+ }
sha2_state *state = sha2_get_state(module);
diff --git a/Modules/sha3module.c b/Modules/sha3module.c
index a7edf5c66a1..cfbf0cbcc04 100644
--- a/Modules/sha3module.c
+++ b/Modules/sha3module.c
@@ -105,18 +105,25 @@ sha3_update(Hacl_Hash_SHA3_state_t *state, uint8_t *buf, Py_ssize_t len)
/*[clinic input]
@classmethod
_sha3.sha3_224.__new__ as py_sha3_new
- data: object(c_default="NULL") = b''
- /
+
+ data as data_obj: object(c_default="NULL") = b''
*
usedforsecurity: bool = True
+ string: object(c_default="NULL") = None
Return a new SHA3 hash object.
[clinic start generated code]*/
static PyObject *
-py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity)
-/*[clinic end generated code: output=90409addc5d5e8b0 input=637e5f8f6a93982a]*/
+py_sha3_new_impl(PyTypeObject *type, PyObject *data_obj, int usedforsecurity,
+ PyObject *string)
+/*[clinic end generated code: output=dcec1eca20395f2a input=c106e0b4e2d67d58]*/
{
+ PyObject *data;
+ if (_Py_hashlib_data_argument(&data, data_obj, string) < 0) {
+ return NULL;
+ }
+
Py_buffer buf = {NULL, NULL};
SHA3State *state = _PyType_GetModuleState(type);
SHA3object *self = newSHA3object(type);
@@ -503,14 +510,13 @@ _SHAKE_digest(PyObject *op, unsigned long digestlen, int hex)
_sha3.shake_128.digest
length: unsigned_long
- /
Return the digest value as a bytes object.
[clinic start generated code]*/
static PyObject *
_sha3_shake_128_digest_impl(SHA3object *self, unsigned long length)
-/*[clinic end generated code: output=2313605e2f87bb8f input=418ef6a36d2e6082]*/
+/*[clinic end generated code: output=2313605e2f87bb8f input=93d6d6ff32904f18]*/
{
return _SHAKE_digest((PyObject *)self, length, 0);
}
@@ -520,14 +526,13 @@ _sha3_shake_128_digest_impl(SHA3object *self, unsigned long length)
_sha3.shake_128.hexdigest
length: unsigned_long
- /
Return the digest value as a string of hexadecimal digits.
[clinic start generated code]*/
static PyObject *
_sha3_shake_128_hexdigest_impl(SHA3object *self, unsigned long length)
-/*[clinic end generated code: output=bf8e2f1e490944a8 input=69fb29b0926ae321]*/
+/*[clinic end generated code: output=bf8e2f1e490944a8 input=562d74e7060b56ab]*/
{
return _SHAKE_digest((PyObject *)self, length, 1);
}
diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h
index 63624d511c3..200b2b8c7d8 100644
--- a/Modules/socketmodule.h
+++ b/Modules/socketmodule.h
@@ -259,7 +259,7 @@ typedef int SOCKET_T;
#endif
// AF_HYPERV is only supported on Windows
-#if defined(AF_HYPERV) && defined(MS_WINDOWS)
+#if defined(AF_HYPERV) && (defined(MS_WINDOWS_APP) || defined(MS_WINDOWS_SYSTEM))
# define HAVE_AF_HYPERV
#endif
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index 9c54af51402..ab20fff1509 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -56,7 +56,6 @@ Revision history:
#include "Python.h"
#include "osdefs.h" // SEP
-#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
#include <syslog.h>
@@ -92,7 +91,7 @@ syslog_get_argv(void)
Py_ssize_t slash;
PyObject *argv;
- if (_PySys_GetOptionalAttrString("argv", &argv) <= 0) {
+ if (PySys_GetOptionalAttrString("argv", &argv) <= 0) {
return NULL;
}
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 1bfbf3f6a0b..3271d87ddc2 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -187,7 +187,7 @@ time_clockid_converter(PyObject *obj, clockid_t *p)
{
#ifdef _AIX
long long clk_id = PyLong_AsLongLong(obj);
-#elif defined(__DragonFly__)
+#elif defined(__DragonFly__) || defined(__CYGWIN__)
long clk_id = PyLong_AsLong(obj);
#else
int clk_id = PyLong_AsInt(obj);
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index d4b4b91697c..f7009364644 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -17,6 +17,16 @@
#error "At least zlib version 1.2.2.1 is required"
#endif
+#if (SIZEOF_OFF_T == SIZEOF_SIZE_T)
+# define convert_to_z_off_t PyLong_AsSsize_t
+#elif (SIZEOF_OFF_T == SIZEOF_LONG_LONG)
+# define convert_to_z_off_t PyLong_AsLongLong
+#elif (SIZEOF_OFF_T == SIZEOF_LONG)
+# define convert_to_z_off_t PyLong_AsLong
+#else
+# error off_t does not match either size_t, long, or long long!
+#endif
+
// Blocks output buffer wrappers
#include "pycore_blocks_output_buffer.h"
@@ -1877,6 +1887,44 @@ zlib_adler32_impl(PyObject *module, Py_buffer *data, unsigned int value)
}
/*[clinic input]
+zlib.adler32_combine -> unsigned_int
+
+ adler1: unsigned_int(bitwise=True)
+ Adler-32 checksum for sequence A
+
+ adler2: unsigned_int(bitwise=True)
+ Adler-32 checksum for sequence B
+
+ len2: object(subclass_of='&PyLong_Type')
+ Length of sequence B
+ /
+
+Combine two Adler-32 checksums into one.
+
+Given the Adler-32 checksum 'adler1' of a sequence A and the
+Adler-32 checksum 'adler2' of a sequence B of length 'len2',
+return the Adler-32 checksum of A and B concatenated.
+[clinic start generated code]*/
+
+static unsigned int
+zlib_adler32_combine_impl(PyObject *module, unsigned int adler1,
+ unsigned int adler2, PyObject *len2)
+/*[clinic end generated code: output=61842cefb16afb1b input=51bb045c95130c6f]*/
+{
+#if defined(Z_WANT64)
+ z_off64_t len = convert_to_z_off_t(len2);
+#else
+ z_off_t len = convert_to_z_off_t(len2);
+#endif
+ if (PyErr_Occurred()) {
+ return (unsigned int)-1;
+ }
+ return adler32_combine(adler1, adler2, len);
+}
+
+
+
+/*[clinic input]
zlib.crc32 -> unsigned_int
data: Py_buffer
@@ -1923,13 +1971,50 @@ zlib_crc32_impl(PyObject *module, Py_buffer *data, unsigned int value)
return value;
}
+/*[clinic input]
+zlib.crc32_combine -> unsigned_int
+
+ crc1: unsigned_int(bitwise=True)
+ CRC-32 checksum for sequence A
+
+ crc2: unsigned_int(bitwise=True)
+ CRC-32 checksum for sequence B
+
+ len2: object(subclass_of='&PyLong_Type')
+ Length of sequence B
+ /
+
+Combine two CRC-32 checksums into one.
+
+Given the CRC-32 checksum 'crc1' of a sequence A and the
+CRC-32 checksum 'crc2' of a sequence B of length 'len2',
+return the CRC-32 checksum of A and B concatenated.
+[clinic start generated code]*/
+
+static unsigned int
+zlib_crc32_combine_impl(PyObject *module, unsigned int crc1,
+ unsigned int crc2, PyObject *len2)
+/*[clinic end generated code: output=c4def907c602e6eb input=9c8a065d9040dc66]*/
+{
+#if defined(Z_WANT64)
+ z_off64_t len = convert_to_z_off_t(len2);
+#else
+ z_off_t len = convert_to_z_off_t(len2);
+#endif
+ if (PyErr_Occurred()) {
+ return (unsigned int)-1;
+ }
+ return crc32_combine(crc1, crc2, len);
+}
static PyMethodDef zlib_methods[] =
{
ZLIB_ADLER32_METHODDEF
+ ZLIB_ADLER32_COMBINE_METHODDEF
ZLIB_COMPRESS_METHODDEF
ZLIB_COMPRESSOBJ_METHODDEF
ZLIB_CRC32_METHODDEF
+ ZLIB_CRC32_COMBINE_METHODDEF
ZLIB_DECOMPRESS_METHODDEF
ZLIB_DECOMPRESSOBJ_METHODDEF
{NULL, NULL}
@@ -1981,14 +2066,17 @@ static PyType_Spec ZlibDecompressor_type_spec = {
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE),
.slots = ZlibDecompressor_type_slots,
};
+
PyDoc_STRVAR(zlib_module_documentation,
"The functions in this module allow compression and decompression using the\n"
"zlib library, which is based on GNU zip.\n"
"\n"
"adler32(string[, start]) -- Compute an Adler-32 checksum.\n"
+"adler32_combine(adler1, adler2, len2, /) -- Combine two Adler-32 checksums.\n"
"compress(data[, level]) -- Compress data, with compression level 0-9 or -1.\n"
"compressobj([level[, ...]]) -- Return a compressor object.\n"
"crc32(string[, start]) -- Compute a CRC-32 checksum.\n"
+"crc32_combine(crc1, crc2, len2, /) -- Combine two CRC-32 checksums.\n"
"decompress(string,[wbits],[bufsize]) -- Decompresses a compressed string.\n"
"decompressobj([wbits[, zdict]]) -- Return a decompressor object.\n"
"\n"