summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Modules
diff options
context:
space:
mode:
authorshadchin <[email protected]>2023-12-13 02:43:57 +0300
committershadchin <[email protected]>2023-12-13 03:08:48 +0300
commit5b48aabc614c6d407f885f3b228dc484ad4c5ba9 (patch)
tree602eb5cc5d85bf730c1de1fa50a13c2ee552830d /contrib/tools/python3/src/Modules
parent35d7049b38602e8cbfcd3f96257329a1abce947e (diff)
Update Python 3 to 3.11.7
Diffstat (limited to 'contrib/tools/python3/src/Modules')
-rw-r--r--contrib/tools/python3/src/Modules/_blake2/blake2module.c25
-rw-r--r--contrib/tools/python3/src/Modules/_datetimemodule.c2
-rw-r--r--contrib/tools/python3/src/Modules/_io/bytesio.c7
-rw-r--r--contrib/tools/python3/src/Modules/_io/textio.c50
-rw-r--r--contrib/tools/python3/src/Modules/_io/winconsoleio.c36
-rw-r--r--contrib/tools/python3/src/Modules/_pickle.c14
-rw-r--r--contrib/tools/python3/src/Modules/_sqlite/ya.make4
-rw-r--r--contrib/tools/python3/src/Modules/_sre/sre.c5
-rw-r--r--contrib/tools/python3/src/Modules/_sre/sre_lib.h14
-rw-r--r--contrib/tools/python3/src/Modules/_zoneinfo.c371
-rw-r--r--contrib/tools/python3/src/Modules/cjkcodecs/_codecs_iso2022.c9
-rw-r--r--contrib/tools/python3/src/Modules/clinic/posixmodule.c.h6
-rw-r--r--contrib/tools/python3/src/Modules/itertoolsmodule.c13
-rw-r--r--contrib/tools/python3/src/Modules/posixmodule.c14
-rw-r--r--contrib/tools/python3/src/Modules/socketmodule.c13
-rw-r--r--contrib/tools/python3/src/Modules/termios.c37
-rw-r--r--contrib/tools/python3/src/Modules/ya.make4
17 files changed, 332 insertions, 292 deletions
diff --git a/contrib/tools/python3/src/Modules/_blake2/blake2module.c b/contrib/tools/python3/src/Modules/_blake2/blake2module.c
index 44d783b40d0..93478f5c8bd 100644
--- a/contrib/tools/python3/src/Modules/_blake2/blake2module.c
+++ b/contrib/tools/python3/src/Modules/_blake2/blake2module.c
@@ -74,6 +74,12 @@ _blake2_free(void *module)
Py_DECREF(x); \
} while(0)
+#define ADD_INT_CONST(NAME, VALUE) do { \
+ if (PyModule_AddIntConstant(m, NAME, VALUE) < 0) { \
+ return -1; \
+ } \
+} while (0)
+
static int
blake2_exec(PyObject *m)
{
@@ -95,10 +101,10 @@ blake2_exec(PyObject *m)
ADD_INT(d, "MAX_KEY_SIZE", BLAKE2B_KEYBYTES);
ADD_INT(d, "MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES);
- PyModule_AddIntConstant(m, "BLAKE2B_SALT_SIZE", BLAKE2B_SALTBYTES);
- PyModule_AddIntConstant(m, "BLAKE2B_PERSON_SIZE", BLAKE2B_PERSONALBYTES);
- PyModule_AddIntConstant(m, "BLAKE2B_MAX_KEY_SIZE", BLAKE2B_KEYBYTES);
- PyModule_AddIntConstant(m, "BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES);
+ ADD_INT_CONST("BLAKE2B_SALT_SIZE", BLAKE2B_SALTBYTES);
+ ADD_INT_CONST("BLAKE2B_PERSON_SIZE", BLAKE2B_PERSONALBYTES);
+ ADD_INT_CONST("BLAKE2B_MAX_KEY_SIZE", BLAKE2B_KEYBYTES);
+ ADD_INT_CONST("BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES);
/* BLAKE2s */
st->blake2s_type = (PyTypeObject *)PyType_FromModuleAndSpec(
@@ -117,14 +123,17 @@ blake2_exec(PyObject *m)
ADD_INT(d, "MAX_KEY_SIZE", BLAKE2S_KEYBYTES);
ADD_INT(d, "MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES);
- PyModule_AddIntConstant(m, "BLAKE2S_SALT_SIZE", BLAKE2S_SALTBYTES);
- PyModule_AddIntConstant(m, "BLAKE2S_PERSON_SIZE", BLAKE2S_PERSONALBYTES);
- PyModule_AddIntConstant(m, "BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES);
- PyModule_AddIntConstant(m, "BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES);
+ ADD_INT_CONST("BLAKE2S_SALT_SIZE", BLAKE2S_SALTBYTES);
+ ADD_INT_CONST("BLAKE2S_PERSON_SIZE", BLAKE2S_PERSONALBYTES);
+ ADD_INT_CONST("BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES);
+ ADD_INT_CONST("BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES);
return 0;
}
+#undef ADD_INT
+#undef ADD_INT_CONST
+
static PyModuleDef_Slot _blake2_slots[] = {
{Py_mod_exec, blake2_exec},
{0, NULL}
diff --git a/contrib/tools/python3/src/Modules/_datetimemodule.c b/contrib/tools/python3/src/Modules/_datetimemodule.c
index 5c67f38ec21..df0ce722d59 100644
--- a/contrib/tools/python3/src/Modules/_datetimemodule.c
+++ b/contrib/tools/python3/src/Modules/_datetimemodule.c
@@ -4649,7 +4649,7 @@ time_fromisoformat(PyObject *cls, PyObject *tstr) {
}
int hour = 0, minute = 0, second = 0, microsecond = 0;
- int tzoffset, tzimicrosecond = 0;
+ int tzoffset = 0, tzimicrosecond = 0;
int rv = parse_isoformat_time(p, len,
&hour, &minute, &second, &microsecond,
&tzoffset, &tzimicrosecond);
diff --git a/contrib/tools/python3/src/Modules/_io/bytesio.c b/contrib/tools/python3/src/Modules/_io/bytesio.c
index 930ef7e29db..e84eef4c759 100644
--- a/contrib/tools/python3/src/Modules/_io/bytesio.c
+++ b/contrib/tools/python3/src/Modules/_io/bytesio.c
@@ -124,12 +124,13 @@ unshare_buffer(bytesio *self, size_t size)
static int
resize_buffer(bytesio *self, size_t size)
{
+ assert(self->buf != NULL);
+ assert(self->exports == 0);
+
/* Here, unsigned types are used to avoid dealing with signed integer
overflow, which is undefined in C. */
size_t alloc = PyBytes_GET_SIZE(self->buf);
- assert(self->buf != NULL);
-
/* For simplicity, stay in the range of the signed type. Anyway, Python
doesn't allow strings to be longer than this. */
if (size > PY_SSIZE_T_MAX)
@@ -1083,7 +1084,7 @@ bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
"bytesiobuf_getbuffer: view==NULL argument is obsolete");
return -1;
}
- if (SHARED_BUF(b)) {
+ if (b->exports == 0 && SHARED_BUF(b)) {
if (unshare_buffer(b, b->string_size) < 0)
return -1;
}
diff --git a/contrib/tools/python3/src/Modules/_io/textio.c b/contrib/tools/python3/src/Modules/_io/textio.c
index 7d5afb4c444..b994dc3d7c4 100644
--- a/contrib/tools/python3/src/Modules/_io/textio.c
+++ b/contrib/tools/python3/src/Modules/_io/textio.c
@@ -1099,6 +1099,15 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
else if (io_check_errors(errors)) {
return -1;
}
+ Py_ssize_t errors_len;
+ const char *errors_str = PyUnicode_AsUTF8AndSize(errors, &errors_len);
+ if (errors_str == NULL) {
+ return -1;
+ }
+ if (strlen(errors_str) != (size_t)errors_len) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ return -1;
+ }
if (validate_newline(newline) < 0) {
return -1;
@@ -1171,11 +1180,11 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
Py_INCREF(buffer);
/* Build the decoder object */
- if (_textiowrapper_set_decoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0)
+ if (_textiowrapper_set_decoder(self, codec_info, errors_str) != 0)
goto error;
/* Build the encoder object */
- if (_textiowrapper_set_encoder(self, codec_info, PyUnicode_AsUTF8(errors)) != 0)
+ if (_textiowrapper_set_encoder(self, codec_info, errors_str) != 0)
goto error;
/* Finished sorting out the codec details */
@@ -1272,24 +1281,34 @@ textiowrapper_change_encoding(textio *self, PyObject *encoding,
errors = &_Py_ID(strict);
}
}
+ Py_INCREF(errors);
+ const char *c_encoding = PyUnicode_AsUTF8(encoding);
+ if (c_encoding == NULL) {
+ Py_DECREF(encoding);
+ Py_DECREF(errors);
+ return -1;
+ }
const char *c_errors = PyUnicode_AsUTF8(errors);
if (c_errors == NULL) {
Py_DECREF(encoding);
+ Py_DECREF(errors);
return -1;
}
// Create new encoder & decoder
PyObject *codec_info = _PyCodec_LookupTextEncoding(
- PyUnicode_AsUTF8(encoding), "codecs.open()");
+ c_encoding, "codecs.open()");
if (codec_info == NULL) {
Py_DECREF(encoding);
+ Py_DECREF(errors);
return -1;
}
if (_textiowrapper_set_decoder(self, codec_info, c_errors) != 0 ||
_textiowrapper_set_encoder(self, codec_info, c_errors) != 0) {
Py_DECREF(codec_info);
Py_DECREF(encoding);
+ Py_DECREF(errors);
return -1;
}
Py_DECREF(codec_info);
@@ -1327,6 +1346,26 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding,
int write_through;
const char *newline = NULL;
+ if (encoding != Py_None && !PyUnicode_Check(encoding)) {
+ PyErr_Format(PyExc_TypeError,
+ "reconfigure() argument 'encoding' must be str or None, not %s",
+ Py_TYPE(encoding)->tp_name);
+ return NULL;
+ }
+ if (errors != Py_None && !PyUnicode_Check(errors)) {
+ PyErr_Format(PyExc_TypeError,
+ "reconfigure() argument 'errors' must be str or None, not %s",
+ Py_TYPE(errors)->tp_name);
+ return NULL;
+ }
+ if (newline_obj != NULL && newline_obj != Py_None &&
+ !PyUnicode_Check(newline_obj))
+ {
+ PyErr_Format(PyExc_TypeError,
+ "reconfigure() argument 'newline' must be str or None, not %s",
+ Py_TYPE(newline_obj)->tp_name);
+ return NULL;
+ }
/* Check if something is in the read buffer */
if (self->decoded_chars != NULL) {
if (encoding != Py_None || errors != Py_None || newline_obj != NULL) {
@@ -1345,9 +1384,12 @@ _io_TextIOWrapper_reconfigure_impl(textio *self, PyObject *encoding,
line_buffering = convert_optional_bool(line_buffering_obj,
self->line_buffering);
+ if (line_buffering < 0) {
+ return NULL;
+ }
write_through = convert_optional_bool(write_through_obj,
self->write_through);
- if (line_buffering < 0 || write_through < 0) {
+ if (write_through < 0) {
return NULL;
}
diff --git a/contrib/tools/python3/src/Modules/_io/winconsoleio.c b/contrib/tools/python3/src/Modules/_io/winconsoleio.c
index 89431b1e4c3..dcb7d32e78c 100644
--- a/contrib/tools/python3/src/Modules/_io/winconsoleio.c
+++ b/contrib/tools/python3/src/Modules/_io/winconsoleio.c
@@ -132,6 +132,23 @@ char _PyIO_get_console_type(PyObject *path_or_fd) {
return m;
}
+static DWORD
+_find_last_utf8_boundary(const char *buf, DWORD len)
+{
+ /* This function never returns 0, returns the original len instead */
+ DWORD count = 1;
+ if (len == 0 || (buf[len - 1] & 0x80) == 0) {
+ return len;
+ }
+ for (;; count++) {
+ if (count > 3 || count >= len) {
+ return len;
+ }
+ if ((buf[len - count] & 0xc0) != 0x80) {
+ return len - count;
+ }
+ }
+}
/*[clinic input]
module _io
@@ -954,7 +971,7 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b)
{
BOOL res = TRUE;
wchar_t *wbuf;
- DWORD len, wlen, orig_len, n = 0;
+ DWORD len, wlen, n = 0;
HANDLE handle;
if (self->fd == -1)
@@ -984,21 +1001,8 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b)
have to reduce and recalculate. */
while (wlen > 32766 / sizeof(wchar_t)) {
len /= 2;
- orig_len = len;
- /* Reduce the length until we hit the final byte of a UTF-8 sequence
- * (top bit is unset). Fix for github issue 82052.
- */
- while (len > 0 && (((char *)b->buf)[len-1] & 0x80) != 0)
- --len;
- /* If we hit a length of 0, something has gone wrong. This shouldn't
- * be possible, as valid UTF-8 can have at most 3 non-final bytes
- * before a final one, and our buffer is way longer than that.
- * But to be on the safe side, if we hit this issue we just restore
- * the original length and let the console API sort it out.
- */
- if (len == 0) {
- len = orig_len;
- }
+ /* Fix for github issues gh-110913 and gh-82052. */
+ len = _find_last_utf8_boundary(b->buf, len);
wlen = MultiByteToWideChar(CP_UTF8, 0, b->buf, len, NULL, 0);
}
Py_END_ALLOW_THREADS
diff --git a/contrib/tools/python3/src/Modules/_pickle.c b/contrib/tools/python3/src/Modules/_pickle.c
index fb16ffc3856..0adb61fd65a 100644
--- a/contrib/tools/python3/src/Modules/_pickle.c
+++ b/contrib/tools/python3/src/Modules/_pickle.c
@@ -4691,6 +4691,13 @@ Pickler_traverse(PicklerObject *self, visitproc visit, void *arg)
Py_VISIT(self->fast_memo);
Py_VISIT(self->reducer_override);
Py_VISIT(self->buffer_callback);
+ PyMemoTable *memo = self->memo;
+ if (memo && memo->mt_table) {
+ Py_ssize_t i = memo->mt_allocated;
+ while (--i >= 0) {
+ Py_VISIT(memo->mt_table[i].me_key);
+ }
+ }
return 0;
}
@@ -7215,6 +7222,13 @@ Unpickler_traverse(UnpicklerObject *self, visitproc visit, void *arg)
Py_VISIT(self->stack);
Py_VISIT(self->pers_func);
Py_VISIT(self->buffers);
+ PyObject **memo = self->memo;
+ if (memo) {
+ Py_ssize_t i = self->memo_size;
+ while (--i >= 0) {
+ Py_VISIT(memo[i]);
+ }
+ }
return 0;
}
diff --git a/contrib/tools/python3/src/Modules/_sqlite/ya.make b/contrib/tools/python3/src/Modules/_sqlite/ya.make
index c32056e4a78..4f539fcbb8a 100644
--- a/contrib/tools/python3/src/Modules/_sqlite/ya.make
+++ b/contrib/tools/python3/src/Modules/_sqlite/ya.make
@@ -2,9 +2,9 @@
LIBRARY()
-VERSION(3.11.6)
+VERSION(3.11.7)
-ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.11.6.tar.gz)
+ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.11.7.tar.gz)
LICENSE(Python-2.0)
diff --git a/contrib/tools/python3/src/Modules/_sre/sre.c b/contrib/tools/python3/src/Modules/_sre/sre.c
index 448e761c988..3bad9d8d0ff 100644
--- a/contrib/tools/python3/src/Modules/_sre/sre.c
+++ b/contrib/tools/python3/src/Modules/_sre/sre.c
@@ -1437,6 +1437,9 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags,
for (i = 0; i < n; i++) {
PyObject *o = PyList_GET_ITEM(code, i);
unsigned long value = PyLong_AsUnsignedLong(o);
+ if (value == (unsigned long)-1 && PyErr_Occurred()) {
+ break;
+ }
self->code[i] = (SRE_CODE) value;
if ((unsigned long) self->code[i] != value) {
PyErr_SetString(PyExc_OverflowError,
@@ -1936,8 +1939,6 @@ _validate_inner(SRE_CODE *code, SRE_CODE *end, Py_ssize_t groups)
GET_SKIP;
GET_ARG; /* 0 for lookahead, width for lookbehind */
code--; /* Back up over arg to simplify math below */
- if (arg & 0x80000000)
- FAIL; /* Width too large */
/* Stop 1 before the end; we check the SUCCESS below */
if (_validate_inner(code+1, code+skip-2, groups))
FAIL;
diff --git a/contrib/tools/python3/src/Modules/_sre/sre_lib.h b/contrib/tools/python3/src/Modules/_sre/sre_lib.h
index f8d556b2db8..95c1ada908d 100644
--- a/contrib/tools/python3/src/Modules/_sre/sre_lib.h
+++ b/contrib/tools/python3/src/Modules/_sre/sre_lib.h
@@ -589,8 +589,8 @@ entrance:
/* optimization info block */
/* <INFO> <1=skip> <2=flags> <3=min> ... */
if (pattern[3] && (uintptr_t)(end - ptr) < pattern[3]) {
- TRACE(("reject (got %zd chars, need %zd)\n",
- end - ptr, (Py_ssize_t) pattern[3]));
+ TRACE(("reject (got %tu chars, need %zu)\n",
+ end - ptr, (size_t) pattern[3]));
RETURN_FAILURE;
}
pattern += pattern[1] + 1;
@@ -1507,7 +1507,7 @@ dispatch:
/* <ASSERT> <skip> <back> <pattern> */
TRACE(("|%p|%p|ASSERT %d\n", pattern,
ptr, pattern[1]));
- if (ptr - (SRE_CHAR *)state->beginning < (Py_ssize_t)pattern[1])
+ if ((uintptr_t)(ptr - (SRE_CHAR *)state->beginning) < pattern[1])
RETURN_FAILURE;
state->ptr = ptr - pattern[1];
DO_JUMP0(JUMP_ASSERT, jump_assert, pattern+2);
@@ -1520,7 +1520,7 @@ dispatch:
/* <ASSERT_NOT> <skip> <back> <pattern> */
TRACE(("|%p|%p|ASSERT_NOT %d\n", pattern,
ptr, pattern[1]));
- if (ptr - (SRE_CHAR *)state->beginning >= (Py_ssize_t)pattern[1]) {
+ if ((uintptr_t)(ptr - (SRE_CHAR *)state->beginning) >= pattern[1]) {
state->ptr = ptr - pattern[1];
LASTMARK_SAVE();
if (state->repeat)
@@ -1655,9 +1655,9 @@ SRE(search)(SRE_STATE* state, SRE_CODE* pattern)
flags = pattern[2];
- if (pattern[3] && end - ptr < (Py_ssize_t)pattern[3]) {
- TRACE(("reject (got %u chars, need %u)\n",
- (unsigned int)(end - ptr), pattern[3]));
+ if (pattern[3] && (uintptr_t)(end - ptr) < pattern[3]) {
+ TRACE(("reject (got %tu chars, need %zu)\n",
+ end - ptr, (size_t) pattern[3]));
return 0;
}
if (pattern[3] > 1) {
diff --git a/contrib/tools/python3/src/Modules/_zoneinfo.c b/contrib/tools/python3/src/Modules/_zoneinfo.c
index 5f584ff93e9..e2ed67c026c 100644
--- a/contrib/tools/python3/src/Modules/_zoneinfo.c
+++ b/contrib/tools/python3/src/Modules/_zoneinfo.c
@@ -59,21 +59,21 @@ struct TransitionRuleType {
typedef struct {
TransitionRuleType base;
- uint8_t month;
- uint8_t week;
- uint8_t day;
- int8_t hour;
- int8_t minute;
- int8_t second;
+ uint8_t month; /* 1 - 12 */
+ uint8_t week; /* 1 - 5 */
+ uint8_t day; /* 0 - 6 */
+ int16_t hour; /* -167 - 167, RFC 8536 §3.3.1 */
+ int8_t minute; /* signed 2 digits */
+ int8_t second; /* signed 2 digits */
} CalendarRule;
typedef struct {
TransitionRuleType base;
- uint8_t julian;
- unsigned int day;
- int8_t hour;
- int8_t minute;
- int8_t second;
+ uint8_t julian; /* 0, 1 */
+ uint16_t day; /* 0 - 365 */
+ int16_t hour; /* -167 - 167, RFC 8536 §3.3.1 */
+ int8_t minute; /* signed 2 digits */
+ int8_t second; /* signed 2 digits */
} DayRule;
struct StrongCacheNode {
@@ -122,15 +122,14 @@ ts_to_local(size_t *trans_idx, int64_t *trans_utc, long *utcoff,
static int
parse_tz_str(PyObject *tz_str_obj, _tzrule *out);
-static Py_ssize_t
-parse_abbr(const char *const p, PyObject **abbr);
-static Py_ssize_t
-parse_tz_delta(const char *const p, long *total_seconds);
-static Py_ssize_t
-parse_transition_time(const char *const p, int8_t *hour, int8_t *minute,
- int8_t *second);
-static Py_ssize_t
-parse_transition_rule(const char *const p, TransitionRuleType **out);
+static int
+parse_abbr(const char **p, PyObject **abbr);
+static int
+parse_tz_delta(const char **p, long *total_seconds);
+static int
+parse_transition_time(const char **p, int *hour, int *minute, int *second);
+static int
+parse_transition_rule(const char **p, TransitionRuleType **out);
static _ttinfo *
find_tzrule_ttinfo(_tzrule *rule, int64_t ts, unsigned char fold, int year);
@@ -1212,14 +1211,14 @@ calendarrule_year_to_timestamp(TransitionRuleType *base_self, int year)
}
int64_t ordinal = ymd_to_ord(year, self->month, month_day) - EPOCHORDINAL;
- return ((ordinal * 86400) + (int64_t)(self->hour * 3600) +
- (int64_t)(self->minute * 60) + (int64_t)(self->second));
+ return ordinal * 86400 + (int64_t)self->hour * 3600 +
+ (int64_t)self->minute * 60 + self->second;
}
/* Constructor for CalendarRule. */
int
-calendarrule_new(uint8_t month, uint8_t week, uint8_t day, int8_t hour,
- int8_t minute, int8_t second, CalendarRule *out)
+calendarrule_new(int month, int week, int day, int hour,
+ int minute, int second, CalendarRule *out)
{
// These bounds come from the POSIX standard, which describes an Mm.n.d
// rule as:
@@ -1228,33 +1227,36 @@ calendarrule_new(uint8_t month, uint8_t week, uint8_t day, int8_t hour,
// 5, 1 <= m <= 12, where week 5 means "the last d day in month m" which
// may occur in either the fourth or the fifth week). Week 1 is the first
// week in which the d'th day occurs. Day zero is Sunday.
- if (month <= 0 || month > 12) {
- PyErr_Format(PyExc_ValueError, "Month must be in (0, 12]");
+ if (month < 1 || month > 12) {
+ PyErr_Format(PyExc_ValueError, "Month must be in [1, 12]");
return -1;
}
- if (week <= 0 || week > 5) {
- PyErr_Format(PyExc_ValueError, "Week must be in (0, 5]");
+ if (week < 1 || week > 5) {
+ PyErr_Format(PyExc_ValueError, "Week must be in [1, 5]");
return -1;
}
- // If the 'day' parameter type is changed to a signed type,
- // "day < 0" check must be added.
- if (/* day < 0 || */ day > 6) {
+ if (day < 0 || day > 6) {
PyErr_Format(PyExc_ValueError, "Day must be in [0, 6]");
return -1;
}
+ if (hour < -167 || hour > 167) {
+ PyErr_Format(PyExc_ValueError, "Hour must be in [0, 167]");
+ return -1;
+ }
+
TransitionRuleType base = {&calendarrule_year_to_timestamp};
CalendarRule new_offset = {
.base = base,
- .month = month,
- .week = week,
- .day = day,
- .hour = hour,
- .minute = minute,
- .second = second,
+ .month = (uint8_t)month,
+ .week = (uint8_t)week,
+ .day = (uint8_t)day,
+ .hour = (int16_t)hour,
+ .minute = (int8_t)minute,
+ .second = (int8_t)second,
};
*out = new_offset;
@@ -1294,40 +1296,45 @@ dayrule_year_to_timestamp(TransitionRuleType *base_self, int year)
// always transitions on a given calendar day (other than February 29th),
// you would use a Julian day, e.g. J91 always refers to April 1st and J365
// always refers to December 31st.
- unsigned int day = self->day;
+ uint16_t day = self->day;
if (self->julian && day >= 59 && is_leap_year(year)) {
day += 1;
}
- return ((days_before_year + day) * 86400) + (self->hour * 3600) +
- (self->minute * 60) + self->second;
+ return (days_before_year + day) * 86400 + (int64_t)self->hour * 3600 +
+ (int64_t)self->minute * 60 + self->second;
}
/* Constructor for DayRule. */
static int
-dayrule_new(uint8_t julian, unsigned int day, int8_t hour, int8_t minute,
- int8_t second, DayRule *out)
+dayrule_new(int julian, int day, int hour, int minute,
+ int second, DayRule *out)
{
// The POSIX standard specifies that Julian days must be in the range (1 <=
// n <= 365) and that non-Julian (they call it "0-based Julian") days must
// be in the range (0 <= n <= 365).
if (day < julian || day > 365) {
- PyErr_Format(PyExc_ValueError, "day must be in [%u, 365], not: %u",
+ PyErr_Format(PyExc_ValueError, "day must be in [%d, 365], not: %d",
julian, day);
return -1;
}
+ if (hour < -167 || hour > 167) {
+ PyErr_Format(PyExc_ValueError, "Hour must be in [0, 167]");
+ return -1;
+ }
+
TransitionRuleType base = {
&dayrule_year_to_timestamp,
};
DayRule tmp = {
.base = base,
- .julian = julian,
- .day = day,
- .hour = hour,
- .minute = minute,
- .second = second,
+ .julian = (uint8_t)julian,
+ .day = (int16_t)day,
+ .hour = (int16_t)hour,
+ .minute = (int8_t)minute,
+ .second = (int8_t)second,
};
*out = tmp;
@@ -1484,21 +1491,18 @@ parse_tz_str(PyObject *tz_str_obj, _tzrule *out)
const char *p = tz_str;
// Read the `std` abbreviation, which must be at least 3 characters long.
- Py_ssize_t num_chars = parse_abbr(p, &std_abbr);
- if (num_chars < 1) {
- PyErr_Format(PyExc_ValueError, "Invalid STD format in %R", tz_str_obj);
+ if (parse_abbr(&p, &std_abbr)) {
+ if (!PyErr_Occurred()) {
+ PyErr_Format(PyExc_ValueError, "Invalid STD format in %R", tz_str_obj);
+ }
goto error;
}
- p += num_chars;
-
// Now read the STD offset, which is required
- num_chars = parse_tz_delta(p, &std_offset);
- if (num_chars < 0) {
+ if (parse_tz_delta(&p, &std_offset)) {
PyErr_Format(PyExc_ValueError, "Invalid STD offset in %R", tz_str_obj);
goto error;
}
- p += num_chars;
// If the string ends here, there is no DST, otherwise we must parse the
// DST abbreviation and start and end dates and times.
@@ -1506,12 +1510,12 @@ parse_tz_str(PyObject *tz_str_obj, _tzrule *out)
goto complete;
}
- num_chars = parse_abbr(p, &dst_abbr);
- if (num_chars < 1) {
- PyErr_Format(PyExc_ValueError, "Invalid DST format in %R", tz_str_obj);
+ if (parse_abbr(&p, &dst_abbr)) {
+ if (!PyErr_Occurred()) {
+ PyErr_Format(PyExc_ValueError, "Invalid DST format in %R", tz_str_obj);
+ }
goto error;
}
- p += num_chars;
if (*p == ',') {
// From the POSIX standard:
@@ -1521,14 +1525,11 @@ parse_tz_str(PyObject *tz_str_obj, _tzrule *out)
dst_offset = std_offset + 3600;
}
else {
- num_chars = parse_tz_delta(p, &dst_offset);
- if (num_chars < 0) {
+ if (parse_tz_delta(&p, &dst_offset)) {
PyErr_Format(PyExc_ValueError, "Invalid DST offset in %R",
tz_str_obj);
goto error;
}
-
- p += num_chars;
}
TransitionRuleType **transitions[2] = {&start, &end};
@@ -1541,14 +1542,12 @@ parse_tz_str(PyObject *tz_str_obj, _tzrule *out)
}
p++;
- num_chars = parse_transition_rule(p, transitions[i]);
- if (num_chars < 0) {
+ if (parse_transition_rule(&p, transitions[i])) {
PyErr_Format(PyExc_ValueError,
"Malformed transition rule in TZ string: %R",
tz_str_obj);
goto error;
}
- p += num_chars;
}
if (*p != '\0') {
@@ -1582,26 +1581,30 @@ error:
}
static int
-parse_uint(const char *const p, uint8_t *value)
+parse_digits(const char **p, int min, int max, int *value)
{
- if (!isdigit(*p)) {
- return -1;
+ assert(max <= 3);
+ *value = 0;
+ for (int i = 0; i < max; i++, (*p)++) {
+ if (!Py_ISDIGIT(**p)) {
+ return (i < min) ? -1 : 0;
+ }
+ *value *= 10;
+ *value += (**p) - '0';
}
-
- *value = (*p) - '0';
return 0;
}
/* Parse the STD and DST abbreviations from a TZ string. */
-static Py_ssize_t
-parse_abbr(const char *const p, PyObject **abbr)
+static int
+parse_abbr(const char **p, PyObject **abbr)
{
- const char *ptr = p;
- char buff = *ptr;
+ const char *ptr = *p;
const char *str_start;
const char *str_end;
if (*ptr == '<') {
+ char buff;
ptr++;
str_start = ptr;
while ((buff = *ptr) != '>') {
@@ -1625,7 +1628,7 @@ parse_abbr(const char *const p, PyObject **abbr)
ptr++;
}
else {
- str_start = p;
+ str_start = ptr;
// From the POSIX standard:
//
// In the unquoted form, all characters in these fields shall be
@@ -1635,6 +1638,9 @@ parse_abbr(const char *const p, PyObject **abbr)
ptr++;
}
str_end = ptr;
+ if (str_end == str_start) {
+ return -1;
+ }
}
*abbr = PyUnicode_FromStringAndSize(str_start, str_end - str_start);
@@ -1642,12 +1648,13 @@ parse_abbr(const char *const p, PyObject **abbr)
return -1;
}
- return ptr - p;
+ *p = ptr;
+ return 0;
}
/* Parse a UTC offset from a TZ str. */
-static Py_ssize_t
-parse_tz_delta(const char *const p, long *total_seconds)
+static int
+parse_tz_delta(const char **p, long *total_seconds)
{
// From the POSIX spec:
//
@@ -1662,75 +1669,30 @@ parse_tz_delta(const char *const p, long *total_seconds)
// The POSIX spec says that the values for `hour` must be between 0 and 24
// hours, but RFC 8536 §3.3.1 specifies that the hours part of the
// transition times may be signed and range from -167 to 167.
- long sign = -1;
- long hours = 0;
- long minutes = 0;
- long seconds = 0;
+ int hours = 0;
+ int minutes = 0;
+ int seconds = 0;
- const char *ptr = p;
- char buff = *ptr;
- if (buff == '-' || buff == '+') {
- // Negative numbers correspond to *positive* offsets, from the spec:
- //
- // If preceded by a '-', the timezone shall be east of the Prime
- // Meridian; otherwise, it shall be west (which may be indicated by
- // an optional preceding '+' ).
- if (buff == '-') {
- sign = 1;
- }
-
- ptr++;
- }
-
- // The hour can be 1 or 2 numeric characters
- for (size_t i = 0; i < 2; ++i) {
- buff = *ptr;
- if (!isdigit(buff)) {
- if (i == 0) {
- return -1;
- }
- else {
- break;
- }
- }
-
- hours *= 10;
- hours += buff - '0';
- ptr++;
- }
-
- if (hours > 24 || hours < 0) {
+ if (parse_transition_time(p, &hours, &minutes, &seconds)) {
return -1;
}
- // Minutes and seconds always of the format ":dd"
- long *outputs[2] = {&minutes, &seconds};
- for (size_t i = 0; i < 2; ++i) {
- if (*ptr != ':') {
- goto complete;
- }
- ptr++;
-
- for (size_t j = 0; j < 2; ++j) {
- buff = *ptr;
- if (!isdigit(buff)) {
- return -1;
- }
- *(outputs[i]) *= 10;
- *(outputs[i]) += buff - '0';
- ptr++;
- }
+ if (hours > 24 || hours < -24) {
+ return -1;
}
-complete:
- *total_seconds = sign * ((hours * 3600) + (minutes * 60) + seconds);
-
- return ptr - p;
+ // Negative numbers correspond to *positive* offsets, from the spec:
+ //
+ // If preceded by a '-', the timezone shall be east of the Prime
+ // Meridian; otherwise, it shall be west (which may be indicated by
+ // an optional preceding '+' ).
+ *total_seconds = -((hours * 3600L) + (minutes * 60) + seconds);
+ return 0;
}
/* Parse the date portion of a transition rule. */
-static Py_ssize_t
-parse_transition_rule(const char *const p, TransitionRuleType **out)
+static int
+parse_transition_rule(const char **p, TransitionRuleType **out)
{
// The full transition rule indicates when to change back and forth between
// STD and DST, and has the form:
@@ -1742,10 +1704,10 @@ parse_transition_rule(const char *const p, TransitionRuleType **out)
// does not include the ',' at the end of the first rule.
//
// The POSIX spec states that if *time* is not given, the default is 02:00.
- const char *ptr = p;
- int8_t hour = 2;
- int8_t minute = 0;
- int8_t second = 0;
+ const char *ptr = *p;
+ int hour = 2;
+ int minute = 0;
+ int second = 0;
// Rules come in one of three flavors:
//
@@ -1754,44 +1716,30 @@ parse_transition_rule(const char *const p, TransitionRuleType **out)
// 3. Mm.n.d: Specifying by month, week and day-of-week.
if (*ptr == 'M') {
- uint8_t month, week, day;
+ int month, week, day;
ptr++;
- if (parse_uint(ptr, &month)) {
+
+ if (parse_digits(&ptr, 1, 2, &month)) {
return -1;
}
- ptr++;
- if (*ptr != '.') {
- uint8_t tmp;
- if (parse_uint(ptr, &tmp)) {
- return -1;
- }
-
- month *= 10;
- month += tmp;
- ptr++;
+ if (*ptr++ != '.') {
+ return -1;
}
-
- uint8_t *values[2] = {&week, &day};
- for (size_t i = 0; i < 2; ++i) {
- if (*ptr != '.') {
- return -1;
- }
- ptr++;
-
- if (parse_uint(ptr, values[i])) {
- return -1;
- }
- ptr++;
+ if (parse_digits(&ptr, 1, 1, &week)) {
+ return -1;
+ }
+ if (*ptr++ != '.') {
+ return -1;
+ }
+ if (parse_digits(&ptr, 1, 1, &day)) {
+ return -1;
}
if (*ptr == '/') {
ptr++;
- Py_ssize_t num_chars =
- parse_transition_time(ptr, &hour, &minute, &second);
- if (num_chars < 0) {
+ if (parse_transition_time(&ptr, &hour, &minute, &second)) {
return -1;
}
- ptr += num_chars;
}
CalendarRule *rv = PyMem_Calloc(1, sizeof(CalendarRule));
@@ -1807,33 +1755,22 @@ parse_transition_rule(const char *const p, TransitionRuleType **out)
*out = (TransitionRuleType *)rv;
}
else {
- uint8_t julian = 0;
- unsigned int day = 0;
+ int julian = 0;
+ int day = 0;
if (*ptr == 'J') {
julian = 1;
ptr++;
}
- for (size_t i = 0; i < 3; ++i) {
- if (!isdigit(*ptr)) {
- if (i == 0) {
- return -1;
- }
- break;
- }
- day *= 10;
- day += (*ptr) - '0';
- ptr++;
+ if (parse_digits(&ptr, 1, 3, &day)) {
+ return -1;
}
if (*ptr == '/') {
ptr++;
- Py_ssize_t num_chars =
- parse_transition_time(ptr, &hour, &minute, &second);
- if (num_chars < 0) {
+ if (parse_transition_time(&ptr, &hour, &minute, &second)) {
return -1;
}
- ptr += num_chars;
}
DayRule *rv = PyMem_Calloc(1, sizeof(DayRule));
@@ -1848,13 +1785,13 @@ parse_transition_rule(const char *const p, TransitionRuleType **out)
*out = (TransitionRuleType *)rv;
}
- return ptr - p;
+ *p = ptr;
+ return 0;
}
/* Parse the time portion of a transition rule (e.g. following an /) */
-static Py_ssize_t
-parse_transition_time(const char *const p, int8_t *hour, int8_t *minute,
- int8_t *second)
+static int
+parse_transition_time(const char **p, int *hour, int *minute, int *second)
{
// From the spec:
//
@@ -1866,12 +1803,9 @@ parse_transition_time(const char *const p, int8_t *hour, int8_t *minute,
// h[h][:mm[:ss]]
//
// RFC 8536 also allows transition times to be signed and to range from
- // -167 to +167, but the current version only supports [0, 99].
- //
- // TODO: Support the full range of transition hours.
- int8_t *components[3] = {hour, minute, second};
- const char *ptr = p;
- int8_t sign = 1;
+ // -167 to +167.
+ const char *ptr = *p;
+ int sign = 1;
if (*ptr == '-' || *ptr == '+') {
if (*ptr == '-') {
@@ -1880,32 +1814,31 @@ parse_transition_time(const char *const p, int8_t *hour, int8_t *minute,
ptr++;
}
- for (size_t i = 0; i < 3; ++i) {
- if (i > 0) {
- if (*ptr != ':') {
- break;
- }
- ptr++;
+ // The hour can be 1 to 3 numeric characters
+ if (parse_digits(&ptr, 1, 3, hour)) {
+ return -1;
+ }
+ *hour *= sign;
+
+ // Minutes and seconds always of the format ":dd"
+ if (*ptr == ':') {
+ ptr++;
+ if (parse_digits(&ptr, 2, 2, minute)) {
+ return -1;
}
+ *minute *= sign;
- uint8_t buff = 0;
- for (size_t j = 0; j < 2; j++) {
- if (!isdigit(*ptr)) {
- if (i == 0 && j > 0) {
- break;
- }
+ if (*ptr == ':') {
+ ptr++;
+ if (parse_digits(&ptr, 2, 2, second)) {
return -1;
}
-
- buff *= 10;
- buff += (*ptr) - '0';
- ptr++;
+ *second *= sign;
}
-
- *(components[i]) = sign * buff;
}
- return ptr - p;
+ *p = ptr;
+ return 0;
}
/* Constructor for a _tzrule.
@@ -2260,8 +2193,8 @@ get_local_timestamp(PyObject *dt, int64_t *local_ts)
}
}
- *local_ts = (int64_t)(ord - EPOCHORDINAL) * 86400 +
- (int64_t)(hour * 3600 + minute * 60 + second);
+ *local_ts = (int64_t)(ord - EPOCHORDINAL) * 86400L +
+ (int64_t)(hour * 3600L + minute * 60 + second);
return 0;
}
diff --git a/contrib/tools/python3/src/Modules/cjkcodecs/_codecs_iso2022.c b/contrib/tools/python3/src/Modules/cjkcodecs/_codecs_iso2022.c
index 7394cf67e0e..6d906ecdd39 100644
--- a/contrib/tools/python3/src/Modules/cjkcodecs/_codecs_iso2022.c
+++ b/contrib/tools/python3/src/Modules/cjkcodecs/_codecs_iso2022.c
@@ -181,8 +181,9 @@ ENCODER(iso2022)
encoded = MAP_UNMAPPABLE;
for (dsg = CONFIG_DESIGNATIONS; dsg->mark; dsg++) {
+ Py_UCS4 buf[2] = {c, 0};
Py_ssize_t length = 1;
- encoded = dsg->encoder(&c, &length);
+ encoded = dsg->encoder(buf, &length);
if (encoded == MAP_MULTIPLE_AVAIL) {
/* this implementation won't work for pair
* of non-bmp characters. */
@@ -191,9 +192,11 @@ ENCODER(iso2022)
return MBERR_TOOFEW;
length = -1;
}
- else
+ else {
+ buf[1] = INCHAR2;
length = 2;
- encoded = dsg->encoder(&c, &length);
+ }
+ encoded = dsg->encoder(buf, &length);
if (encoded != MAP_UNMAPPABLE) {
insize = length;
break;
diff --git a/contrib/tools/python3/src/Modules/clinic/posixmodule.c.h b/contrib/tools/python3/src/Modules/clinic/posixmodule.c.h
index e5efd1a3a54..8d5a5fecbb2 100644
--- a/contrib/tools/python3/src/Modules/clinic/posixmodule.c.h
+++ b/contrib/tools/python3/src/Modules/clinic/posixmodule.c.h
@@ -6259,7 +6259,7 @@ exit:
#endif /* (defined HAVE_TRUNCATE || defined MS_WINDOWS) */
-#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG))
+#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && !defined(__wasi__))
PyDoc_STRVAR(os_posix_fallocate__doc__,
"posix_fallocate($module, fd, offset, length, /)\n"
@@ -6304,7 +6304,7 @@ exit:
return return_value;
}
-#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) */
+#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && !defined(__wasi__)) */
#if (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG))
@@ -9388,4 +9388,4 @@ exit:
#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */
-/*[clinic end generated code: output=8277545a0dea1505 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b649ad9a4e1f2427 input=a9049054013a1b77]*/
diff --git a/contrib/tools/python3/src/Modules/itertoolsmodule.c b/contrib/tools/python3/src/Modules/itertoolsmodule.c
index d5cdfc591e2..7a02a0d25b2 100644
--- a/contrib/tools/python3/src/Modules/itertoolsmodule.c
+++ b/contrib/tools/python3/src/Modules/itertoolsmodule.c
@@ -119,21 +119,30 @@ pairwise_next(pairwiseobject *po)
return NULL;
}
if (old == NULL) {
- po->old = old = (*Py_TYPE(it)->tp_iternext)(it);
+ old = (*Py_TYPE(it)->tp_iternext)(it);
+ Py_XSETREF(po->old, old);
if (old == NULL) {
Py_CLEAR(po->it);
return NULL;
}
+ it = po->it;
+ if (it == NULL) {
+ Py_CLEAR(po->old);
+ return NULL;
+ }
}
+ Py_INCREF(old);
new = (*Py_TYPE(it)->tp_iternext)(it);
if (new == NULL) {
Py_CLEAR(po->it);
Py_CLEAR(po->old);
+ Py_DECREF(old);
return NULL;
}
/* Future optimization: Reuse the result tuple as we do in enumerate() */
result = PyTuple_Pack(2, old, new);
- Py_SETREF(po->old, new);
+ Py_XSETREF(po->old, new);
+ Py_DECREF(old);
return result;
}
diff --git a/contrib/tools/python3/src/Modules/posixmodule.c b/contrib/tools/python3/src/Modules/posixmodule.c
index a45e8887dad..b494cb56e6c 100644
--- a/contrib/tools/python3/src/Modules/posixmodule.c
+++ b/contrib/tools/python3/src/Modules/posixmodule.c
@@ -10992,7 +10992,10 @@ os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
#endif
-#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
+/* GH-111804: Due to posix_fallocate() not having consistent semantics across
+ OSs, support was dropped in WASI preview2. */
+#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) && \
+ !defined(__wasi__)
/*[clinic input]
os.posix_fallocate
@@ -11030,7 +11033,7 @@ os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
errno = result;
return posix_error();
}
-#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
+#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG && !defined(__wasi__) */
#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
@@ -11104,7 +11107,6 @@ win32_putenv(PyObject *name, PyObject *value)
}
Py_ssize_t size;
- /* PyUnicode_AsWideCharString() rejects embedded null characters */
wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
Py_DECREF(unicode);
@@ -11118,6 +11120,12 @@ win32_putenv(PyObject *name, PyObject *value)
PyMem_Free(env);
return NULL;
}
+ if (wcslen(env) != (size_t)size) {
+ PyErr_SetString(PyExc_ValueError,
+ "embedded null character");
+ PyMem_Free(env);
+ return NULL;
+ }
/* _wputenv() and SetEnvironmentVariableW() update the environment in the
Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
diff --git a/contrib/tools/python3/src/Modules/socketmodule.c b/contrib/tools/python3/src/Modules/socketmodule.c
index da18bf96667..5089a884441 100644
--- a/contrib/tools/python3/src/Modules/socketmodule.c
+++ b/contrib/tools/python3/src/Modules/socketmodule.c
@@ -2822,12 +2822,14 @@ For IP sockets, the address info is a pair (hostaddr, port).");
static PyObject *
sock_setblocking(PySocketSockObject *s, PyObject *arg)
{
- long block;
+ long value;
+ int block;
- block = PyLong_AsLong(arg);
- if (block == -1 && PyErr_Occurred())
+ value = PyLong_AsLong(arg);
+ if (value == -1 && PyErr_Occurred())
return NULL;
+ block = (value != 0);
s->sock_timeout = _PyTime_FromSeconds(block ? -1 : 0);
if (internal_setblocking(s, block) == -1) {
return NULL;
@@ -5541,8 +5543,9 @@ socket_sethostname(PyObject *self, PyObject *args)
Py_buffer buf;
int res, flag = 0;
-#ifdef _AIX
-/* issue #18259, not declared in any useful header file */
+#if defined(_AIX) || (defined(__sun) && defined(__SVR4) && Py_SUNOS_VERSION <= 510)
+/* issue #18259, sethostname is not declared in any useful header file on AIX
+ * the same is true for Solaris 10 */
extern int sethostname(const char *, size_t);
#endif
diff --git a/contrib/tools/python3/src/Modules/termios.c b/contrib/tools/python3/src/Modules/termios.c
index 3900a6f0b89..be5d099072c 100644
--- a/contrib/tools/python3/src/Modules/termios.c
+++ b/contrib/tools/python3/src/Modules/termios.c
@@ -183,17 +183,25 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term)
return PyErr_SetFromErrno(state->TermiosError);
}
- mode.c_iflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 0));
- mode.c_oflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 1));
- mode.c_cflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 2));
- mode.c_lflag = (tcflag_t) PyLong_AsLong(PyList_GetItem(term, 3));
- speed_t ispeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 4));
- speed_t ospeed = (speed_t) PyLong_AsLong(PyList_GetItem(term, 5));
- PyObject *cc = PyList_GetItem(term, 6);
- if (PyErr_Occurred()) {
- return NULL;
- }
+ speed_t ispeed, ospeed;
+#define SET_FROM_LIST(TYPE, VAR, LIST, N) do { \
+ PyObject *item = PyList_GET_ITEM(LIST, N); \
+ long num = PyLong_AsLong(item); \
+ if (num == -1 && PyErr_Occurred()) { \
+ return NULL; \
+ } \
+ VAR = (TYPE)num; \
+} while (0)
+ SET_FROM_LIST(tcflag_t, mode.c_iflag, term, 0);
+ SET_FROM_LIST(tcflag_t, mode.c_oflag, term, 1);
+ SET_FROM_LIST(tcflag_t, mode.c_cflag, term, 2);
+ SET_FROM_LIST(tcflag_t, mode.c_lflag, term, 3);
+ SET_FROM_LIST(speed_t, ispeed, term, 4);
+ SET_FROM_LIST(speed_t, ospeed, term, 5);
+#undef SET_FROM_LIST
+
+ PyObject *cc = PyList_GET_ITEM(term, 6);
if (!PyList_Check(cc) || PyList_Size(cc) != NCCS) {
PyErr_Format(PyExc_TypeError,
"tcsetattr: attributes[6] must be %d element list",
@@ -208,8 +216,13 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term)
if (PyBytes_Check(v) && PyBytes_Size(v) == 1)
mode.c_cc[i] = (cc_t) * PyBytes_AsString(v);
- else if (PyLong_Check(v))
- mode.c_cc[i] = (cc_t) PyLong_AsLong(v);
+ else if (PyLong_Check(v)) {
+ long num = PyLong_AsLong(v);
+ if (num == -1 && PyErr_Occurred()) {
+ return NULL;
+ }
+ mode.c_cc[i] = (cc_t)num;
+ }
else {
PyErr_SetString(PyExc_TypeError,
"tcsetattr: elements of attributes must be characters or integers");
diff --git a/contrib/tools/python3/src/Modules/ya.make b/contrib/tools/python3/src/Modules/ya.make
index 0301557e238..e578584b6e9 100644
--- a/contrib/tools/python3/src/Modules/ya.make
+++ b/contrib/tools/python3/src/Modules/ya.make
@@ -2,9 +2,9 @@
LIBRARY()
-VERSION(3.11.6)
+VERSION(3.11.7)
-ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.11.6.tar.gz)
+ORIGINAL_SOURCE(https://github.com/python/cpython/archive/v3.11.7.tar.gz)
LICENSE(Python-2.0)