summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Modules
diff options
context:
space:
mode:
authorshadchin <[email protected]>2026-02-07 19:56:35 +0300
committershadchin <[email protected]>2026-02-07 20:23:53 +0300
commit19d43a3e6fb4cb8ea11747d7d7bca7a3542fbb44 (patch)
tree0b1418938140a0b6470953bef6069454ffdf1bd0 /contrib/tools/python3/Modules
parent0879409bfc0891ab8103828a3bdbf0e960475fec (diff)
Update Python 3 to 3.13.12
commit_hash:71d3efea437a769b2b7910d196120bb02587046e
Diffstat (limited to 'contrib/tools/python3/Modules')
-rw-r--r--contrib/tools/python3/Modules/_collectionsmodule.c15
-rw-r--r--contrib/tools/python3/Modules/_ctypes/_ctypes.c9
-rw-r--r--contrib/tools/python3/Modules/_decimal/_decimal.c16
-rw-r--r--contrib/tools/python3/Modules/_elementtree.c40
-rw-r--r--contrib/tools/python3/Modules/_io/bufferedio.c4
-rw-r--r--contrib/tools/python3/Modules/_io/bytesio.c16
-rw-r--r--contrib/tools/python3/Modules/_io/textio.c3
-rw-r--r--contrib/tools/python3/Modules/_json.c3
-rw-r--r--contrib/tools/python3/Modules/_pickle.c186
-rw-r--r--contrib/tools/python3/Modules/_sqlite/connection.c88
-rw-r--r--contrib/tools/python3/Modules/_sqlite/connection.h1
-rw-r--r--contrib/tools/python3/Modules/_sqlite/ya.make4
-rw-r--r--contrib/tools/python3/Modules/_struct.c27
-rw-r--r--contrib/tools/python3/Modules/_zoneinfo.c16
-rw-r--r--contrib/tools/python3/Modules/arraymodule.c65
-rw-r--r--contrib/tools/python3/Modules/atexitmodule.c7
-rw-r--r--contrib/tools/python3/Modules/overlapped.c6
-rw-r--r--contrib/tools/python3/Modules/posixmodule.c47
-rw-r--r--contrib/tools/python3/Modules/socketmodule.c5
19 files changed, 386 insertions, 172 deletions
diff --git a/contrib/tools/python3/Modules/_collectionsmodule.c b/contrib/tools/python3/Modules/_collectionsmodule.c
index 2c30e5c70a6..f5fc0d02a16 100644
--- a/contrib/tools/python3/Modules/_collectionsmodule.c
+++ b/contrib/tools/python3/Modules/_collectionsmodule.c
@@ -2203,11 +2203,11 @@ defdict_missing(defdictobject *dd, PyObject *key)
value = _PyObject_CallNoArgs(factory);
if (value == NULL)
return value;
- if (PyObject_SetItem((PyObject *)dd, key, value) < 0) {
- Py_DECREF(value);
- return NULL;
- }
- return value;
+ PyObject *result = NULL;
+ (void)PyDict_SetDefaultRef((PyObject *)dd, key, value, &result);
+ // 'result' is NULL, or a strong reference to 'value' or 'dd[key]'
+ Py_DECREF(value);
+ return result;
}
static inline PyObject*
@@ -2549,7 +2549,12 @@ _collections__count_elements_impl(PyObject *module, PyObject *mapping,
if (_PyDict_SetItem_KnownHash(mapping, key, one, hash) < 0)
goto done;
} else {
+ /* oldval is a borrowed reference. Keep it alive across
+ PyNumber_Add(), which can execute arbitrary user code and
+ mutate (or even clear) the underlying dict. */
+ Py_INCREF(oldval);
newval = PyNumber_Add(oldval, one);
+ Py_DECREF(oldval);
if (newval == NULL)
goto done;
if (_PyDict_SetItem_KnownHash(mapping, key, newval, hash) < 0)
diff --git a/contrib/tools/python3/Modules/_ctypes/_ctypes.c b/contrib/tools/python3/Modules/_ctypes/_ctypes.c
index ad088b0ce8e..aac812813d9 100644
--- a/contrib/tools/python3/Modules/_ctypes/_ctypes.c
+++ b/contrib/tools/python3/Modules/_ctypes/_ctypes.c
@@ -1338,7 +1338,13 @@ PyCPointerType_from_param_impl(PyObject *type, PyTypeObject *cls,
/* If we expect POINTER(<type>), but receive a <type> instance, accept
it by calling byref(<type>).
*/
- assert(typeinfo->proto);
+ if (typeinfo->proto == NULL) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "cannot convert argument: POINTER _type_ type is not set"
+ );
+ return NULL;
+ }
switch (PyObject_IsInstance(value, typeinfo->proto)) {
case 1:
Py_INCREF(value); /* _byref steals a refcount */
@@ -4273,6 +4279,7 @@ _build_result(PyObject *result, PyObject *callargs,
v = PyTuple_GET_ITEM(callargs, i);
v = PyObject_CallMethodNoArgs(v, &_Py_ID(__ctypes_from_outparam__));
if (v == NULL || numretvals == 1) {
+ Py_XDECREF(tup);
Py_DECREF(callargs);
return v;
}
diff --git a/contrib/tools/python3/Modules/_decimal/_decimal.c b/contrib/tools/python3/Modules/_decimal/_decimal.c
index d1fbfd7d303..cbe7af13240 100644
--- a/contrib/tools/python3/Modules/_decimal/_decimal.c
+++ b/contrib/tools/python3/Modules/_decimal/_decimal.c
@@ -3462,7 +3462,8 @@ dec_format(PyObject *dec, PyObject *args)
if (size > 0 && fmt[size-1] == 'N') {
if (PyErr_WarnEx(PyExc_DeprecationWarning,
- "Format specifier 'N' is deprecated", 1) < 0) {
+ "Format specifier 'N' is deprecated and "
+ "slated for removal in Python 3.18", 1) < 0) {
return NULL;
}
}
@@ -5922,10 +5923,15 @@ _decimal_exec(PyObject *m)
/* DecimalTuple */
ASSIGN_PTR(collections, PyImport_ImportModule("collections"));
- ASSIGN_PTR(state->DecimalTuple, (PyTypeObject *)PyObject_CallMethod(collections,
- "namedtuple", "(ss)", "DecimalTuple",
- "sign digits exponent"));
-
+ ASSIGN_PTR(obj, PyObject_CallMethod(collections, "namedtuple", "(ss)",
+ "DecimalTuple",
+ "sign digits exponent"));
+ if (!PyType_Check(obj)) {
+ PyErr_SetString(PyExc_TypeError,
+ "type is expected from namedtuple call");
+ goto error;
+ }
+ ASSIGN_PTR(state->DecimalTuple, (PyTypeObject *)obj);
ASSIGN_PTR(obj, PyUnicode_FromString("decimal"));
CHECK_INT(PyDict_SetItemString(state->DecimalTuple->tp_dict, "__module__", obj));
Py_CLEAR(obj);
diff --git a/contrib/tools/python3/Modules/_elementtree.c b/contrib/tools/python3/Modules/_elementtree.c
index 020b7454add..dfa03663c38 100644
--- a/contrib/tools/python3/Modules/_elementtree.c
+++ b/contrib/tools/python3/Modules/_elementtree.c
@@ -1803,16 +1803,20 @@ element_subscr(PyObject* self_, PyObject* item)
return element_getitem(self_, i);
}
else if (PySlice_Check(item)) {
+ // Note: 'slicelen' is computed once we are sure that 'self->extra'
+ // cannot be mutated by user-defined code.
+ // See https://github.com/python/cpython/issues/143200.
Py_ssize_t start, stop, step, slicelen, i;
size_t cur;
PyObject* list;
- if (!self->extra)
- return PyList_New(0);
-
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
+
+ if (self->extra == NULL) {
+ return PyList_New(0);
+ }
slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
step);
@@ -1855,28 +1859,26 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
return element_setitem(self_, i, value);
}
else if (PySlice_Check(item)) {
+ // Note: 'slicelen' is computed once we are sure that 'self->extra'
+ // cannot be mutated by user-defined code.
+ // See https://github.com/python/cpython/issues/143200.
Py_ssize_t start, stop, step, slicelen, newlen, i;
size_t cur;
PyObject* recycle = NULL;
PyObject* seq;
- if (!self->extra) {
- if (create_extra(self, NULL) < 0)
- return -1;
- }
-
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return -1;
}
- slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
- step);
if (value == NULL) {
/* Delete slice */
- size_t cur;
- Py_ssize_t i;
-
+ if (self->extra == NULL) {
+ return 0;
+ }
+ slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
+ step);
if (slicelen <= 0)
return 0;
@@ -1945,8 +1947,16 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
}
newlen = PySequence_Fast_GET_SIZE(seq);
- if (step != 1 && newlen != slicelen)
- {
+ if (self->extra == NULL) {
+ if (create_extra(self, NULL) < 0) {
+ Py_DECREF(seq);
+ return -1;
+ }
+ }
+ slicelen = PySlice_AdjustIndices(self->extra->length, &start, &stop,
+ step);
+
+ if (step != 1 && newlen != slicelen) {
Py_DECREF(seq);
PyErr_Format(PyExc_ValueError,
"attempt to assign sequence of size %zd "
diff --git a/contrib/tools/python3/Modules/_io/bufferedio.c b/contrib/tools/python3/Modules/_io/bufferedio.c
index 65d69d0d5e1..2e8566168de 100644
--- a/contrib/tools/python3/Modules/_io/bufferedio.c
+++ b/contrib/tools/python3/Modules/_io/bufferedio.c
@@ -1486,8 +1486,8 @@ buffered_iternext(buffered *self)
_PyIO_State *state = find_io_state_by_def(Py_TYPE(self));
tp = Py_TYPE(self);
- if (Py_IS_TYPE(tp, state->PyBufferedReader_Type) ||
- Py_IS_TYPE(tp, state->PyBufferedRandom_Type))
+ if (tp == state->PyBufferedReader_Type ||
+ tp == state->PyBufferedRandom_Type)
{
/* Skip method call overhead for speed */
line = _buffered_readline(self, -1);
diff --git a/contrib/tools/python3/Modules/_io/bytesio.c b/contrib/tools/python3/Modules/_io/bytesio.c
index b7aac773158..e149823afd3 100644
--- a/contrib/tools/python3/Modules/_io/bytesio.c
+++ b/contrib/tools/python3/Modules/_io/bytesio.c
@@ -180,18 +180,18 @@ resize_buffer(bytesio *self, size_t size)
Py_NO_INLINE static Py_ssize_t
write_bytes(bytesio *self, PyObject *b)
{
- if (check_closed(self)) {
- return -1;
- }
- if (check_exports(self)) {
- return -1;
- }
-
Py_buffer buf;
+ Py_ssize_t len;
if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0) {
return -1;
}
- Py_ssize_t len = buf.len;
+
+ if (check_closed(self) || check_exports(self)) {
+ len = -1;
+ goto done;
+ }
+
+ len = buf.len;
if (len == 0) {
goto done;
}
diff --git a/contrib/tools/python3/Modules/_io/textio.c b/contrib/tools/python3/Modules/_io/textio.c
index 047d0fdfc76..db6c709c00c 100644
--- a/contrib/tools/python3/Modules/_io/textio.c
+++ b/contrib/tools/python3/Modules/_io/textio.c
@@ -3133,6 +3133,9 @@ _io_TextIOWrapper_close_impl(textio *self)
if (r > 0) {
Py_RETURN_NONE; /* stream already closed */
}
+ if (self->detached) {
+ Py_RETURN_NONE; /* gh-142594 null pointer issue */
+ }
else {
PyObject *exc = NULL;
if (self->finalizing) {
diff --git a/contrib/tools/python3/Modules/_json.c b/contrib/tools/python3/Modules/_json.c
index cc41b9ab867..afefc71bfbd 100644
--- a/contrib/tools/python3/Modules/_json.c
+++ b/contrib/tools/python3/Modules/_json.c
@@ -308,11 +308,12 @@ raise_errmsg(const char *msg, PyObject *s, Py_ssize_t end)
PyObject *exc;
exc = PyObject_CallFunction(JSONDecodeError, "zOn", msg, s, end);
- Py_DECREF(JSONDecodeError);
if (exc) {
PyErr_SetObject(JSONDecodeError, exc);
Py_DECREF(exc);
}
+
+ Py_DECREF(JSONDecodeError);
}
static void
diff --git a/contrib/tools/python3/Modules/_pickle.c b/contrib/tools/python3/Modules/_pickle.c
index 409b31872d5..27a6d9e8c6a 100644
--- a/contrib/tools/python3/Modules/_pickle.c
+++ b/contrib/tools/python3/Modules/_pickle.c
@@ -640,6 +640,7 @@ typedef struct PicklerObject {
int fast_nesting;
int fix_imports; /* Indicate whether Pickler should fix
the name of globals for Python 2.x. */
+ int running; /* True when a method of Pickler is executing. */
PyObject *fast_memo;
PyObject *buffer_callback; /* Callback for out-of-band buffers, or NULL */
} PicklerObject;
@@ -683,6 +684,8 @@ typedef struct UnpicklerObject {
int proto; /* Protocol of the pickle loaded. */
int fix_imports; /* Indicate whether Unpickler should fix
the name of globals pickled by Python 2.x. */
+ int running; /* True when a method of Unpickler is executing. */
+
} UnpicklerObject;
typedef struct {
@@ -695,6 +698,32 @@ typedef struct {
UnpicklerObject *unpickler;
} UnpicklerMemoProxyObject;
+#define BEGIN_USING_PICKLER(SELF, RET) do { \
+ if ((SELF)->running) { \
+ PyErr_SetString(PyExc_RuntimeError, \
+ "Pickler object is already used"); \
+ return (RET); \
+ } \
+ (SELF)->running = 1; \
+ } while (0)
+
+#define END_USING_PICKLER(SELF) do { \
+ (SELF)->running = 0; \
+ } while (0)
+
+#define BEGIN_USING_UNPICKLER(SELF, RET) do { \
+ if ((SELF)->running) { \
+ PyErr_SetString(PyExc_RuntimeError, \
+ "Unpickler object is already used"); \
+ return (RET); \
+ } \
+ (SELF)->running = 1; \
+ } while (0)
+
+#define END_USING_UNPICKLER(SELF) do { \
+ (SELF)->running = 0; \
+ } while (0)
+
/* Forward declarations */
static int save(PickleState *state, PicklerObject *, PyObject *, int);
static int save_reduce(PickleState *, PicklerObject *, PyObject *, PyObject *);
@@ -1124,6 +1153,7 @@ _Pickler_New(PickleState *st)
self->fast = 0;
self->fast_nesting = 0;
self->fix_imports = 0;
+ self->running = 0;
self->fast_memo = NULL;
self->buffer_callback = NULL;
@@ -1627,6 +1657,7 @@ _Unpickler_New(PyObject *module)
self->marks_size = 0;
self->proto = 0;
self->fix_imports = 0;
+ self->running = 0;
PyObject_GC_Track(self);
return self;
@@ -2523,53 +2554,61 @@ save_picklebuffer(PickleState *st, PicklerObject *self, PyObject *obj)
"PickleBuffer can only be pickled with protocol >= 5");
return -1;
}
- const Py_buffer* view = PyPickleBuffer_GetBuffer(obj);
- if (view == NULL) {
+ Py_buffer view;
+ if (PyObject_GetBuffer(obj, &view, PyBUF_FULL_RO) != 0) {
return -1;
}
- if (view->suboffsets != NULL || !PyBuffer_IsContiguous(view, 'A')) {
+ if (view.suboffsets != NULL || !PyBuffer_IsContiguous(&view, 'A')) {
PyErr_SetString(st->PicklingError,
"PickleBuffer can not be pickled when "
"pointing to a non-contiguous buffer");
- return -1;
+ goto error;
}
+
+ int rc = 0;
int in_band = 1;
if (self->buffer_callback != NULL) {
PyObject *ret = PyObject_CallOneArg(self->buffer_callback, obj);
if (ret == NULL) {
- return -1;
+ goto error;
}
in_band = PyObject_IsTrue(ret);
Py_DECREF(ret);
if (in_band == -1) {
- return -1;
+ goto error;
}
}
if (in_band) {
/* Write data in-band */
- if (view->readonly) {
- return _save_bytes_data(st, self, obj, (const char *)view->buf,
- view->len);
+ if (view.readonly) {
+ rc = _save_bytes_data(st, self, obj, (const char *)view.buf,
+ view.len);
}
else {
- return _save_bytearray_data(st, self, obj, (const char *)view->buf,
- view->len);
+ rc = _save_bytearray_data(st, self, obj, (const char *)view.buf,
+ view.len);
}
}
else {
/* Write data out-of-band */
const char next_buffer_op = NEXT_BUFFER;
if (_Pickler_Write(self, &next_buffer_op, 1) < 0) {
- return -1;
+ goto error;
}
- if (view->readonly) {
+ if (view.readonly) {
const char readonly_buffer_op = READONLY_BUFFER;
if (_Pickler_Write(self, &readonly_buffer_op, 1) < 0) {
- return -1;
+ goto error;
}
}
}
- return 0;
+
+ PyBuffer_Release(&view);
+ return rc;
+
+error:
+ PyBuffer_Release(&view);
+ return -1;
}
/* A copy of PyUnicode_AsRawUnicodeEscapeString() that also translates
@@ -4603,17 +4642,23 @@ _pickle_Pickler_dump_impl(PicklerObject *self, PyTypeObject *cls,
Py_TYPE(self)->tp_name);
return NULL;
}
+ BEGIN_USING_PICKLER(self, NULL);
- if (_Pickler_ClearBuffer(self) < 0)
- return NULL;
-
- if (dump(st, self, obj) < 0)
- return NULL;
-
- if (_Pickler_FlushToFile(self) < 0)
- return NULL;
-
+ if (_Pickler_ClearBuffer(self) < 0) {
+ goto error;
+ }
+ if (dump(st, self, obj) < 0) {
+ goto error;
+ }
+ if (_Pickler_FlushToFile(self) < 0) {
+ goto error;
+ }
+ END_USING_PICKLER(self);
Py_RETURN_NONE;
+
+error:
+ END_USING_PICKLER(self);
+ return NULL;
}
/*[clinic input]
@@ -4752,47 +4797,54 @@ _pickle_Pickler___init___impl(PicklerObject *self, PyObject *file,
PyObject *buffer_callback)
/*[clinic end generated code: output=0abedc50590d259b input=a7c969699bf5dad3]*/
{
+ BEGIN_USING_PICKLER(self, -1);
/* In case of multiple __init__() calls, clear previous content. */
if (self->write != NULL)
(void)Pickler_clear(self);
- if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0)
- return -1;
-
- if (_Pickler_SetOutputStream(self, file) < 0)
- return -1;
-
- if (_Pickler_SetBufferCallback(self, buffer_callback) < 0)
- return -1;
-
+ if (_Pickler_SetProtocol(self, protocol, fix_imports) < 0) {
+ goto error;
+ }
+ if (_Pickler_SetOutputStream(self, file) < 0) {
+ goto error;
+ }
+ if (_Pickler_SetBufferCallback(self, buffer_callback) < 0) {
+ goto error;
+ }
/* memo and output_buffer may have already been created in _Pickler_New */
if (self->memo == NULL) {
self->memo = PyMemoTable_New();
- if (self->memo == NULL)
- return -1;
+ if (self->memo == NULL) {
+ goto error;
+ }
}
self->output_len = 0;
if (self->output_buffer == NULL) {
self->max_output_len = WRITE_BUF_SIZE;
self->output_buffer = PyBytes_FromStringAndSize(NULL,
self->max_output_len);
- if (self->output_buffer == NULL)
- return -1;
+ if (self->output_buffer == NULL) {
+ goto error;
+ }
}
self->fast = 0;
self->fast_nesting = 0;
self->fast_memo = NULL;
- if (self->dispatch_table != NULL) {
- return 0;
- }
- if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(dispatch_table),
- &self->dispatch_table) < 0) {
- return -1;
+ if (self->dispatch_table == NULL) {
+ if (PyObject_GetOptionalAttr((PyObject *)self, &_Py_ID(dispatch_table),
+ &self->dispatch_table) < 0) {
+ goto error;
+ }
}
+ END_USING_PICKLER(self);
return 0;
+
+error:
+ END_USING_PICKLER(self);
+ return -1;
}
@@ -6979,22 +7031,22 @@ static PyObject *
_pickle_Unpickler_load_impl(UnpicklerObject *self, PyTypeObject *cls)
/*[clinic end generated code: output=cc88168f608e3007 input=f5d2f87e61d5f07f]*/
{
- UnpicklerObject *unpickler = (UnpicklerObject*)self;
-
PickleState *st = _Pickle_GetStateByClass(cls);
/* Check whether the Unpickler was initialized correctly. This prevents
segfaulting if a subclass overridden __init__ with a function that does
not call Unpickler.__init__(). Here, we simply ensure that self->read
is not NULL. */
- if (unpickler->read == NULL) {
+ if (self->read == NULL) {
PyErr_Format(st->UnpicklingError,
"Unpickler.__init__() was not called by %s.__init__()",
- Py_TYPE(unpickler)->tp_name);
+ Py_TYPE(self)->tp_name);
return NULL;
}
-
- return load(st, unpickler);
+ BEGIN_USING_UNPICKLER(self, NULL);
+ PyObject *res = load(st, self);
+ END_USING_UNPICKLER(self);
+ return res;
}
/* The name of find_class() is misleading. In newer pickle protocols, this
@@ -7235,35 +7287,41 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file,
const char *errors, PyObject *buffers)
/*[clinic end generated code: output=09f0192649ea3f85 input=ca4c1faea9553121]*/
{
+ BEGIN_USING_UNPICKLER(self, -1);
/* In case of multiple __init__() calls, clear previous content. */
if (self->read != NULL)
(void)Unpickler_clear(self);
- if (_Unpickler_SetInputStream(self, file) < 0)
- return -1;
-
- if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0)
- return -1;
-
- if (_Unpickler_SetBuffers(self, buffers) < 0)
- return -1;
-
+ if (_Unpickler_SetInputStream(self, file) < 0) {
+ goto error;
+ }
+ if (_Unpickler_SetInputEncoding(self, encoding, errors) < 0) {
+ goto error;
+ }
+ if (_Unpickler_SetBuffers(self, buffers) < 0) {
+ goto error;
+ }
self->fix_imports = fix_imports;
PyTypeObject *tp = Py_TYPE(self);
PickleState *state = _Pickle_FindStateByType(tp);
self->stack = (Pdata *)Pdata_New(state);
- if (self->stack == NULL)
- return -1;
-
+ if (self->stack == NULL) {
+ goto error;
+ }
self->memo_size = 32;
self->memo = _Unpickler_NewMemo(self->memo_size);
- if (self->memo == NULL)
- return -1;
-
+ if (self->memo == NULL) {
+ goto error;
+ }
self->proto = 0;
+ END_USING_UNPICKLER(self);
return 0;
+
+error:
+ END_USING_UNPICKLER(self);
+ return -1;
}
diff --git a/contrib/tools/python3/Modules/_sqlite/connection.c b/contrib/tools/python3/Modules/_sqlite/connection.c
index a359fdc855c..b83dc9ae0cc 100644
--- a/contrib/tools/python3/Modules/_sqlite/connection.c
+++ b/contrib/tools/python3/Modules/_sqlite/connection.c
@@ -143,7 +143,8 @@ class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionTyp
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=67369db2faf80891]*/
static int _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
-static void free_callback_context(callback_context *ctx);
+static void incref_callback_context(callback_context *ctx);
+static void decref_callback_context(callback_context *ctx);
static void set_callback_context(callback_context **ctx_pp,
callback_context *ctx);
static int connection_close(pysqlite_Connection *self);
@@ -930,8 +931,9 @@ func_callback(sqlite3_context *context, int argc, sqlite3_value **argv)
args = _pysqlite_build_py_params(context, argc, argv);
if (args) {
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
py_retval = PyObject_CallObject(ctx->callable, args);
+ decref_callback_context(ctx);
Py_DECREF(args);
}
@@ -958,7 +960,7 @@ step_callback(sqlite3_context *context, int argc, sqlite3_value **params)
PyObject* stepmethod = NULL;
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*));
if (aggregate_instance == NULL) {
@@ -996,6 +998,7 @@ step_callback(sqlite3_context *context, int argc, sqlite3_value **params)
}
error:
+ decref_callback_context(ctx);
Py_XDECREF(stepmethod);
Py_XDECREF(function_result);
@@ -1027,9 +1030,10 @@ final_callback(sqlite3_context *context)
PyObject *exc = PyErr_GetRaisedException();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
function_result = PyObject_CallMethodNoArgs(*aggregate_instance,
ctx->state->str_finalize);
+ decref_callback_context(ctx);
Py_DECREF(*aggregate_instance);
ok = 0;
@@ -1101,6 +1105,7 @@ create_callback_context(PyTypeObject *cls, PyObject *callable)
callback_context *ctx = PyMem_Malloc(sizeof(callback_context));
if (ctx != NULL) {
PyObject *module = PyType_GetModule(cls);
+ ctx->refcount = 1;
ctx->callable = Py_NewRef(callable);
ctx->module = Py_NewRef(module);
ctx->state = pysqlite_get_state(module);
@@ -1112,11 +1117,33 @@ static void
free_callback_context(callback_context *ctx)
{
assert(ctx != NULL);
+ assert(ctx->refcount == 0);
Py_XDECREF(ctx->callable);
Py_XDECREF(ctx->module);
PyMem_Free(ctx);
}
+static inline void
+incref_callback_context(callback_context *ctx)
+{
+ assert(PyGILState_Check());
+ assert(ctx != NULL);
+ assert(ctx->refcount > 0);
+ ctx->refcount++;
+}
+
+static inline void
+decref_callback_context(callback_context *ctx)
+{
+ assert(PyGILState_Check());
+ assert(ctx != NULL);
+ assert(ctx->refcount > 0);
+ ctx->refcount--;
+ if (ctx->refcount == 0) {
+ free_callback_context(ctx);
+ }
+}
+
static void
set_callback_context(callback_context **ctx_pp, callback_context *ctx)
{
@@ -1124,7 +1151,7 @@ set_callback_context(callback_context **ctx_pp, callback_context *ctx)
callback_context *tmp = *ctx_pp;
*ctx_pp = ctx;
if (tmp != NULL) {
- free_callback_context(tmp);
+ decref_callback_context(tmp);
}
}
@@ -1135,7 +1162,7 @@ destructor_callback(void *ctx)
// This function may be called without the GIL held, so we need to
// ensure that we destroy 'ctx' with the GIL held.
PyGILState_STATE gstate = PyGILState_Ensure();
- free_callback_context((callback_context *)ctx);
+ decref_callback_context((callback_context *)ctx);
PyGILState_Release(gstate);
}
}
@@ -1180,7 +1207,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self,
func_callback,
NULL,
NULL,
- &destructor_callback); // will decref func
+ &destructor_callback); // will free 'ctx'
if (rc != SQLITE_OK) {
/* Workaround for SQLite bug: no error code or string is available here */
@@ -1204,7 +1231,7 @@ inverse_callback(sqlite3_context *context, int argc, sqlite3_value **params)
PyGILState_STATE gilstate = PyGILState_Ensure();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
int size = sizeof(PyObject *);
PyObject **cls = (PyObject **)sqlite3_aggregate_context(context, size);
@@ -1236,6 +1263,7 @@ inverse_callback(sqlite3_context *context, int argc, sqlite3_value **params)
Py_DECREF(res);
exit:
+ decref_callback_context(ctx);
Py_XDECREF(method);
PyGILState_Release(gilstate);
}
@@ -1252,7 +1280,7 @@ value_callback(sqlite3_context *context)
PyGILState_STATE gilstate = PyGILState_Ensure();
callback_context *ctx = (callback_context *)sqlite3_user_data(context);
- assert(ctx != NULL);
+ incref_callback_context(ctx);
int size = sizeof(PyObject *);
PyObject **cls = (PyObject **)sqlite3_aggregate_context(context, size);
@@ -1260,6 +1288,8 @@ value_callback(sqlite3_context *context)
assert(*cls != NULL);
PyObject *res = PyObject_CallMethodNoArgs(*cls, ctx->state->str_value);
+ decref_callback_context(ctx);
+
if (res == NULL) {
int attr_err = PyErr_ExceptionMatches(PyExc_AttributeError);
set_sqlite_error(context, attr_err
@@ -1377,7 +1407,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self,
0,
&step_callback,
&final_callback,
- &destructor_callback); // will decref func
+ &destructor_callback); // will free 'ctx'
if (rc != SQLITE_OK) {
/* Workaround for SQLite bug: no error code or string is available here */
PyErr_SetString(self->OperationalError, "Error creating aggregate");
@@ -1387,7 +1417,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self,
}
static int
-authorizer_callback(void *ctx, int action, const char *arg1,
+authorizer_callback(void *ctx_vp, int action, const char *arg1,
const char *arg2 , const char *dbname,
const char *access_attempt_source)
{
@@ -1396,8 +1426,9 @@ authorizer_callback(void *ctx, int action, const char *arg1,
PyObject *ret;
int rc = SQLITE_DENY;
- assert(ctx != NULL);
- PyObject *callable = ((callback_context *)ctx)->callable;
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+ PyObject *callable = ctx->callable;
ret = PyObject_CallFunction(callable, "issss", action, arg1, arg2, dbname,
access_attempt_source);
@@ -1419,21 +1450,23 @@ authorizer_callback(void *ctx, int action, const char *arg1,
Py_DECREF(ret);
}
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
return rc;
}
static int
-progress_callback(void *ctx)
+progress_callback(void *ctx_vp)
{
PyGILState_STATE gilstate = PyGILState_Ensure();
int rc;
PyObject *ret;
- assert(ctx != NULL);
- PyObject *callable = ((callback_context *)ctx)->callable;
- ret = PyObject_CallNoArgs(callable);
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+
+ ret = PyObject_CallNoArgs(ctx->callable);
if (!ret) {
/* abort query if error occurred */
rc = -1;
@@ -1446,6 +1479,7 @@ progress_callback(void *ctx)
print_or_clear_traceback(ctx);
}
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
return rc;
}
@@ -1457,7 +1491,7 @@ progress_callback(void *ctx)
* to ensure future compatibility.
*/
static int
-trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
+trace_callback(unsigned int type, void *ctx_vp, void *stmt, void *sql)
{
if (type != SQLITE_TRACE_STMT) {
return 0;
@@ -1465,8 +1499,9 @@ trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
PyGILState_STATE gilstate = PyGILState_Ensure();
- assert(ctx != NULL);
- pysqlite_state *state = ((callback_context *)ctx)->state;
+ callback_context *ctx = (callback_context *)ctx_vp;
+ incref_callback_context(ctx);
+ pysqlite_state *state = ctx->state;
assert(state != NULL);
PyObject *py_statement = NULL;
@@ -1480,7 +1515,7 @@ trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
PyErr_SetString(state->DataError,
"Expanded SQL string exceeds the maximum string length");
- print_or_clear_traceback((callback_context *)ctx);
+ print_or_clear_traceback(ctx);
// Fall back to unexpanded sql
py_statement = PyUnicode_FromString((const char *)sql);
@@ -1490,16 +1525,16 @@ trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
sqlite3_free((void *)expanded_sql);
}
if (py_statement) {
- PyObject *callable = ((callback_context *)ctx)->callable;
- PyObject *ret = PyObject_CallOneArg(callable, py_statement);
+ PyObject *ret = PyObject_CallOneArg(ctx->callable, py_statement);
Py_DECREF(py_statement);
Py_XDECREF(ret);
}
if (PyErr_Occurred()) {
- print_or_clear_traceback((callback_context *)ctx);
+ print_or_clear_traceback(ctx);
}
exit:
+ decref_callback_context(ctx);
PyGILState_Release(gilstate);
return 0;
}
@@ -1914,6 +1949,8 @@ collation_callback(void *context, int text1_length, const void *text1_data,
PyObject* retval = NULL;
long longval;
int result = 0;
+ callback_context *ctx = (callback_context *)context;
+ incref_callback_context(ctx);
/* This callback may be executed multiple times per sqlite3_step(). Bail if
* the previous call failed */
@@ -1930,8 +1967,6 @@ collation_callback(void *context, int text1_length, const void *text1_data,
goto finally;
}
- callback_context *ctx = (callback_context *)context;
- assert(ctx != NULL);
PyObject *args[] = { NULL, string1, string2 }; // Borrowed refs.
size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
retval = PyObject_Vectorcall(ctx->callable, args + 1, nargsf, NULL);
@@ -1953,6 +1988,7 @@ collation_callback(void *context, int text1_length, const void *text1_data,
}
finally:
+ decref_callback_context(ctx);
Py_XDECREF(string1);
Py_XDECREF(string2);
Py_XDECREF(retval);
diff --git a/contrib/tools/python3/Modules/_sqlite/connection.h b/contrib/tools/python3/Modules/_sqlite/connection.h
index 7a748ee3ea0..703396a0c8d 100644
--- a/contrib/tools/python3/Modules/_sqlite/connection.h
+++ b/contrib/tools/python3/Modules/_sqlite/connection.h
@@ -36,6 +36,7 @@ typedef struct _callback_context
PyObject *callable;
PyObject *module;
pysqlite_state *state;
+ Py_ssize_t refcount;
} callback_context;
enum autocommit_mode {
diff --git a/contrib/tools/python3/Modules/_sqlite/ya.make b/contrib/tools/python3/Modules/_sqlite/ya.make
index eef017d69e9..52461066edb 100644
--- a/contrib/tools/python3/Modules/_sqlite/ya.make
+++ b/contrib/tools/python3/Modules/_sqlite/ya.make
@@ -2,9 +2,9 @@
PY3_LIBRARY()
-VERSION(3.13.11)
+VERSION(3.13.12)
-ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.11.tar.gz)
+ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.13.12.tar.gz)
LICENSE(Python-2.0)
diff --git a/contrib/tools/python3/Modules/_struct.c b/contrib/tools/python3/Modules/_struct.c
index a9f8fa4bbde..016a1d3cf21 100644
--- a/contrib/tools/python3/Modules/_struct.c
+++ b/contrib/tools/python3/Modules/_struct.c
@@ -1498,8 +1498,6 @@ prepare_s(PyStructObject *self)
return -1;
}
- self->s_size = size;
- self->s_len = len;
codes = PyMem_Malloc((ncodes + 1) * sizeof(formatcode));
if (codes == NULL) {
PyErr_NoMemory();
@@ -1509,6 +1507,8 @@ prepare_s(PyStructObject *self)
if (self->s_codes != NULL)
PyMem_Free(self->s_codes);
self->s_codes = codes;
+ self->s_size = size;
+ self->s_len = len;
s = fmt;
size = 0;
@@ -1695,6 +1695,14 @@ fail:
return NULL;
}
+#define ENSURE_STRUCT_IS_READY(self) \
+ do { \
+ if (!(self)->s_codes) { \
+ PyErr_SetString(PyExc_RuntimeError, \
+ "Struct object is not initialized"); \
+ return NULL; \
+ } \
+ } while (0);
/*[clinic input]
Struct.unpack
@@ -1715,7 +1723,7 @@ Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer)
/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/
{
_structmodulestate *state = get_struct_state_structinst(self);
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (buffer->len != self->s_size) {
PyErr_Format(state->StructError,
"unpack requires a buffer of %zd bytes",
@@ -1747,7 +1755,7 @@ Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer,
/*[clinic end generated code: output=57fac875e0977316 input=cafd4851d473c894]*/
{
_structmodulestate *state = get_struct_state_structinst(self);
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (offset < 0) {
if (offset + self->s_size > 0) {
@@ -1890,8 +1898,7 @@ Struct_iter_unpack(PyStructObject *self, PyObject *buffer)
{
_structmodulestate *state = get_struct_state_structinst(self);
unpackiterobject *iter;
-
- assert(self->s_codes != NULL);
+ ENSURE_STRUCT_IS_READY(self);
if (self->s_size == 0) {
PyErr_Format(state->StructError,
@@ -2032,8 +2039,8 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
/* Validate arguments. */
soself = (PyStructObject *)self;
+ ENSURE_STRUCT_IS_READY(soself);
assert(PyStruct_Check(self, state));
- assert(soself->s_codes != NULL);
if (nargs != soself->s_len)
{
PyErr_Format(state->StructError,
@@ -2077,8 +2084,8 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
/* Validate arguments. +1 is for the first arg as buffer. */
soself = (PyStructObject *)self;
+ ENSURE_STRUCT_IS_READY(soself);
assert(PyStruct_Check(self, state));
- assert(soself->s_codes != NULL);
if (nargs != (soself->s_len + 2))
{
if (nargs == 0) {
@@ -2164,6 +2171,7 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
static PyObject *
s_get_format(PyStructObject *self, void *unused)
{
+ ENSURE_STRUCT_IS_READY(self);
return PyUnicode_FromStringAndSize(PyBytes_AS_STRING(self->s_format),
PyBytes_GET_SIZE(self->s_format));
}
@@ -2474,8 +2482,7 @@ The optional first format char indicates byte order, size and alignment:\n\
The remaining chars indicate types of args and must match exactly;\n\
these can be preceded by a decimal repeat count:\n\
x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;\n\
- ?: _Bool (requires C99; if not available, char is used instead)\n\
- h:short; H:unsigned short; i:int; I:unsigned int;\n\
+ ?:_Bool; h:short; H:unsigned short; i:int; I:unsigned int;\n\
l:long; L:unsigned long; f:float; d:double; e:half-float.\n\
Special cases (preceding decimal count indicates length):\n\
s:string (array of char); p: pascal string (with count byte).\n\
diff --git a/contrib/tools/python3/Modules/_zoneinfo.c b/contrib/tools/python3/Modules/_zoneinfo.c
index 63643b7bfc7..2cb48d91494 100644
--- a/contrib/tools/python3/Modules/_zoneinfo.c
+++ b/contrib/tools/python3/Modules/_zoneinfo.c
@@ -287,16 +287,11 @@ static PyObject *
get_weak_cache(zoneinfo_state *state, PyTypeObject *type)
{
if (type == state->ZoneInfoType) {
+ Py_INCREF(state->ZONEINFO_WEAK_CACHE);
return state->ZONEINFO_WEAK_CACHE;
}
else {
- PyObject *cache =
- PyObject_GetAttrString((PyObject *)type, "_weak_cache");
- // We are assuming that the type lives at least as long as the function
- // that calls get_weak_cache, and that it holds a reference to the
- // cache, so we'll return a "borrowed reference".
- Py_XDECREF(cache);
- return cache;
+ return PyObject_GetAttrString((PyObject *)type, "_weak_cache");
}
}
@@ -323,6 +318,7 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
PyObject *weak_cache = get_weak_cache(state, type);
instance = PyObject_CallMethod(weak_cache, "get", "O", key, Py_None);
if (instance == NULL) {
+ Py_DECREF(weak_cache);
return NULL;
}
@@ -330,6 +326,7 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
Py_DECREF(instance);
PyObject *tmp = zoneinfo_new_instance(state, type, key);
if (tmp == NULL) {
+ Py_DECREF(weak_cache);
return NULL;
}
@@ -337,12 +334,14 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
PyObject_CallMethod(weak_cache, "setdefault", "OO", key, tmp);
Py_DECREF(tmp);
if (instance == NULL) {
+ Py_DECREF(weak_cache);
return NULL;
}
((PyZoneInfo_ZoneInfo *)instance)->source = SOURCE_CACHE;
}
update_strong_cache(state, type, key, instance);
+ Py_DECREF(weak_cache);
return instance;
}
@@ -504,12 +503,14 @@ zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyTypeObject *cls,
PyObject *item = NULL;
PyObject *pop = PyUnicode_FromString("pop");
if (pop == NULL) {
+ Py_DECREF(weak_cache);
return NULL;
}
PyObject *iter = PyObject_GetIter(only_keys);
if (iter == NULL) {
Py_DECREF(pop);
+ Py_DECREF(weak_cache);
return NULL;
}
@@ -534,6 +535,7 @@ zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyTypeObject *cls,
Py_DECREF(pop);
}
+ Py_DECREF(weak_cache);
if (PyErr_Occurred()) {
return NULL;
}
diff --git a/contrib/tools/python3/Modules/arraymodule.c b/contrib/tools/python3/Modules/arraymodule.c
index 1f800af6ad5..4c7cc4d47c0 100644
--- a/contrib/tools/python3/Modules/arraymodule.c
+++ b/contrib/tools/python3/Modules/arraymodule.c
@@ -202,6 +202,33 @@ Note that the basic Get and Set functions do NOT check that the index is
in bounds; that's the responsibility of the caller.
****************************************************************************/
+/* Macro to check array buffer validity and bounds after calling
+ user-defined methods (like __index__ or __float__) that might modify
+ the array during the call.
+*/
+#define CHECK_ARRAY_BOUNDS(OP, IDX) \
+ do { \
+ if ((IDX) >= 0 && ((OP)->ob_item == NULL || \
+ (IDX) >= Py_SIZE((OP)))) { \
+ PyErr_SetString(PyExc_IndexError, \
+ "array assignment index out of range"); \
+ return -1; \
+ } \
+ } while (0)
+
+#define CHECK_ARRAY_BOUNDS_WITH_CLEANUP(OP, IDX, VAL, CLEANUP) \
+ do { \
+ if ((IDX) >= 0 && ((OP)->ob_item == NULL || \
+ (IDX) >= Py_SIZE((OP)))) { \
+ PyErr_SetString(PyExc_IndexError, \
+ "array assignment index out of range"); \
+ if (CLEANUP) { \
+ Py_DECREF(VAL); \
+ } \
+ return -1; \
+ } \
+ } while (0)
+
static PyObject *
b_getitem(arrayobject *ap, Py_ssize_t i)
{
@@ -218,7 +245,10 @@ b_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
the overflow checking */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
- else if (x < -128) {
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
+ if (x < -128) {
PyErr_SetString(PyExc_OverflowError,
"signed char is less than minimum");
return -1;
@@ -247,6 +277,9 @@ BB_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'B' == unsigned char, maps to PyArg_Parse's 'b' formatter */
if (!PyArg_Parse(v, "b;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((unsigned char *)ap->ob_item)[i] = x;
return 0;
@@ -323,6 +356,9 @@ h_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'h' == signed short, maps to PyArg_Parse's 'h' formatter */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((short *)ap->ob_item)[i] = x;
return 0;
@@ -352,6 +388,9 @@ HH_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
"unsigned short is greater than maximum");
return -1;
}
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((short *)ap->ob_item)[i] = (short)x;
return 0;
@@ -370,6 +409,9 @@ i_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
/* 'i' == signed int, maps to PyArg_Parse's 'i' formatter */
if (!PyArg_Parse(v, "i;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((int *)ap->ob_item)[i] = x;
return 0;
@@ -410,6 +452,9 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned int *)ap->ob_item)[i] = (unsigned int)x;
@@ -431,6 +476,9 @@ l_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
long x;
if (!PyArg_Parse(v, "l;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((long *)ap->ob_item)[i] = x;
return 0;
@@ -462,6 +510,9 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned long *)ap->ob_item)[i] = x;
@@ -483,6 +534,9 @@ q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
long long x;
if (!PyArg_Parse(v, "L;array item must be integer", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((long long *)ap->ob_item)[i] = x;
return 0;
@@ -515,6 +569,9 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
}
return -1;
}
+
+ CHECK_ARRAY_BOUNDS_WITH_CLEANUP(ap, i, v, do_decref);
+
if (i >= 0)
((unsigned long long *)ap->ob_item)[i] = x;
@@ -536,6 +593,9 @@ f_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
float x;
if (!PyArg_Parse(v, "f;array item must be float", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((float *)ap->ob_item)[i] = x;
return 0;
@@ -553,6 +613,9 @@ d_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
double x;
if (!PyArg_Parse(v, "d;array item must be float", &x))
return -1;
+
+ CHECK_ARRAY_BOUNDS(ap, i);
+
if (i >= 0)
((double *)ap->ob_item)[i] = x;
return 0;
diff --git a/contrib/tools/python3/Modules/atexitmodule.c b/contrib/tools/python3/Modules/atexitmodule.c
index c009235b7a3..23fcc1b9d35 100644
--- a/contrib/tools/python3/Modules/atexitmodule.c
+++ b/contrib/tools/python3/Modules/atexitmodule.c
@@ -57,6 +57,9 @@ static void
atexit_delete_cb(struct atexit_state *state, int i)
{
atexit_py_callback *cb = state->callbacks[i];
+ if (cb == NULL) {
+ return;
+ }
state->callbacks[i] = NULL;
Py_DECREF(cb->func);
@@ -287,7 +290,9 @@ atexit_unregister(PyObject *module, PyObject *func)
continue;
}
- int eq = PyObject_RichCompareBool(cb->func, func, Py_EQ);
+ PyObject *to_compare = Py_NewRef(cb->func);
+ int eq = PyObject_RichCompareBool(to_compare, func, Py_EQ);
+ Py_DECREF(to_compare);
if (eq < 0) {
return NULL;
}
diff --git a/contrib/tools/python3/Modules/overlapped.c b/contrib/tools/python3/Modules/overlapped.c
index 77ee70ae133..567593e05c4 100644
--- a/contrib/tools/python3/Modules/overlapped.c
+++ b/contrib/tools/python3/Modules/overlapped.c
@@ -1794,7 +1794,7 @@ _overlapped_Overlapped_WSASendTo_impl(OverlappedObject *self, HANDLE handle,
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
@@ -1868,7 +1868,7 @@ _overlapped_Overlapped_WSARecvFrom_impl(OverlappedObject *self,
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
@@ -1935,7 +1935,7 @@ _overlapped_Overlapped_WSARecvFromInto_impl(OverlappedObject *self,
case ERROR_IO_PENDING:
Py_RETURN_NONE;
default:
- self->type = TYPE_NOT_STARTED;
+ Overlapped_clear(self);
return SetFromWindowsErr(err);
}
}
diff --git a/contrib/tools/python3/Modules/posixmodule.c b/contrib/tools/python3/Modules/posixmodule.c
index 698e707b62d..24df9546064 100644
--- a/contrib/tools/python3/Modules/posixmodule.c
+++ b/contrib/tools/python3/Modules/posixmodule.c
@@ -1534,7 +1534,7 @@ static int
fd_and_follow_symlinks_invalid(const char *function_name, int fd,
int follow_symlinks)
{
- if ((fd > 0) && (!follow_symlinks)) {
+ if ((fd >= 0) && (!follow_symlinks)) {
PyErr_Format(PyExc_ValueError,
"%s: cannot use fd and follow_symlinks together",
function_name);
@@ -1699,7 +1699,7 @@ convertenviron(void)
#ifdef MS_WINDOWS
k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
#else
- k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
+ k = PyBytes_FromStringAndSize(*e, (Py_ssize_t)(p-*e));
#endif
if (k == NULL) {
Py_DECREF(d);
@@ -6741,8 +6741,8 @@ static EXECV_CHAR**
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
{
Py_ssize_t i, pos, envc;
- PyObject *keys=NULL, *vals=NULL;
- PyObject *key2, *val2, *keyval;
+ PyObject *keys = NULL, *vals = NULL;
+ PyObject *key = NULL, *val = NULL, *key2 = NULL, *val2 = NULL;
EXECV_CHAR **envlist;
i = PyMapping_Size(env);
@@ -6767,20 +6767,22 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
}
for (pos = 0; pos < i; pos++) {
- PyObject *key = PyList_GetItem(keys, pos); // Borrowed ref.
+ // The 'key' and 'val' must be strong references because of
+ // possible side-effects by PyUnicode_FS{Converter,Decoder}().
+ key = PyList_GetItemRef(keys, pos);
if (key == NULL) {
goto error;
}
- PyObject *val = PyList_GetItem(vals, pos); // Borrowed ref.
+ val = PyList_GetItemRef(vals, pos);
if (val == NULL) {
goto error;
}
#if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
- if (!PyUnicode_FSDecoder(key, &key2))
+ if (!PyUnicode_FSDecoder(key, &key2)) {
goto error;
+ }
if (!PyUnicode_FSDecoder(val, &val2)) {
- Py_DECREF(key2);
goto error;
}
/* Search from index 1 because on Windows starting '=' is allowed for
@@ -6789,39 +6791,38 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
{
PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
- Py_DECREF(key2);
- Py_DECREF(val2);
goto error;
}
- keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
+ PyObject *keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
#else
- if (!PyUnicode_FSConverter(key, &key2))
+ if (!PyUnicode_FSConverter(key, &key2)) {
goto error;
+ }
if (!PyUnicode_FSConverter(val, &val2)) {
- Py_DECREF(key2);
goto error;
}
if (PyBytes_GET_SIZE(key2) == 0 ||
strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
{
PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
- Py_DECREF(key2);
- Py_DECREF(val2);
goto error;
}
- keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
- PyBytes_AS_STRING(val2));
+ PyObject *keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
+ PyBytes_AS_STRING(val2));
#endif
- Py_DECREF(key2);
- Py_DECREF(val2);
- if (!keyval)
+ if (!keyval) {
goto error;
+ }
if (!fsconvert_strdup(keyval, &envlist[envc++])) {
Py_DECREF(keyval);
goto error;
}
+ Py_CLEAR(key);
+ Py_CLEAR(val);
+ Py_CLEAR(key2);
+ Py_CLEAR(val2);
Py_DECREF(keyval);
}
Py_DECREF(vals);
@@ -6832,6 +6833,10 @@ parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
return envlist;
error:
+ Py_XDECREF(key);
+ Py_XDECREF(val);
+ Py_XDECREF(key2);
+ Py_XDECREF(val2);
Py_XDECREF(keys);
Py_XDECREF(vals);
free_string_array(envlist, envc);
@@ -7353,7 +7358,7 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
if (argc < 1) {
PyErr_Format(PyExc_ValueError,
"%s: argv must not be empty", func_name);
- return NULL;
+ goto exit;
}
if (!PyMapping_Check(env) && env != Py_None) {
diff --git a/contrib/tools/python3/Modules/socketmodule.c b/contrib/tools/python3/Modules/socketmodule.c
index edc79c9d3b8..6df7401133a 100644
--- a/contrib/tools/python3/Modules/socketmodule.c
+++ b/contrib/tools/python3/Modules/socketmodule.c
@@ -2649,6 +2649,11 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
/* RDS sockets use sockaddr_in: fall-through */
#endif /* AF_RDS */
+#ifdef AF_DIVERT
+ case AF_DIVERT:
+ /* FreeBSD divert(4) sockets use sockaddr_in: fall-through */
+#endif /* AF_DIVERT */
+
case AF_INET:
{
*len_ret = sizeof (struct sockaddr_in);