Skip to content

Commit 5dd4c43

Browse files
authored
Merge branch 'main' into docs/opengraph-0.12
2 parents 86a3631 + 525784a commit 5dd4c43

File tree

10 files changed

+115
-44
lines changed

10 files changed

+115
-44
lines changed

Doc/library/codecs.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ particular, the following variants typically exist:
12511251
+-----------------+--------------------------------+--------------------------------+
12521252
| iso8859_3 | iso-8859-3, latin3, L3 | Esperanto, Maltese |
12531253
+-----------------+--------------------------------+--------------------------------+
1254-
| iso8859_4 | iso-8859-4, latin4, L4 | Baltic languages |
1254+
| iso8859_4 | iso-8859-4, latin4, L4 | Northern Europe |
12551255
+-----------------+--------------------------------+--------------------------------+
12561256
| iso8859_5 | iso-8859-5, cyrillic | Belarusian, Bulgarian, |
12571257
| | | Macedonian, Russian, Serbian |

Lib/test/_test_eintr.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ def os_open(self, path):
380380

381381
@unittest.skipIf(sys.platform == "darwin",
382382
"hangs under macOS; see bpo-25234, bpo-35363")
383+
@unittest.skipIf(sys.platform.startswith('netbsd'),
384+
"hangs on NetBSD; see gh-137397")
383385
def test_os_open(self):
384386
self._test_open("fd = os.open(path, os.O_RDONLY)\nos.close(fd)",
385387
self.os_open)

Lib/test/test_socket.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,40 @@ def testSetSockOpt(self):
15381538
reuse = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
15391539
self.assertFalse(reuse == 0, "failed to set reuse mode")
15401540

1541+
def test_setsockopt_errors(self):
1542+
# See issue #107546.
1543+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1544+
self.addCleanup(sock.close)
1545+
1546+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # No error expected.
1547+
1548+
with self.assertRaises(OverflowError):
1549+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 2 ** 100)
1550+
1551+
with self.assertRaises(OverflowError):
1552+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, - 2 ** 100)
1553+
1554+
with self.assertRaises(OverflowError):
1555+
sock.setsockopt(socket.SOL_SOCKET, 2 ** 100, 1)
1556+
1557+
with self.assertRaises(OverflowError):
1558+
sock.setsockopt(2 ** 100, socket.SO_REUSEADDR, 1)
1559+
1560+
with self.assertRaisesRegex(TypeError, "socket option should be int, bytes-like object or None"):
1561+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, dict())
1562+
1563+
with self.assertRaisesRegex(TypeError, "requires 4 arguments when the third argument is None"):
1564+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, None)
1565+
1566+
with self.assertRaisesRegex(TypeError, "only takes 4 arguments when the third argument is None"):
1567+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1, 2)
1568+
1569+
with self.assertRaisesRegex(TypeError, "takes at least 3 arguments"):
1570+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
1571+
1572+
with self.assertRaisesRegex(TypeError, "takes at most 4 arguments"):
1573+
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1, 2, 3)
1574+
15411575
def testSendAfterClose(self):
15421576
# testing send() after close() with timeout
15431577
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:

Lib/test/test_ssl.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
HOST = socket_helper.HOST
5050
IS_OPENSSL_3_0_0 = ssl.OPENSSL_VERSION_INFO >= (3, 0, 0)
5151
CAN_GET_SELECTED_OPENSSL_GROUP = ssl.OPENSSL_VERSION_INFO >= (3, 2)
52+
CAN_IGNORE_UNKNOWN_OPENSSL_GROUPS = ssl.OPENSSL_VERSION_INFO >= (3, 3)
5253
CAN_GET_AVAILABLE_OPENSSL_GROUPS = ssl.OPENSSL_VERSION_INFO >= (3, 5)
5354
PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS')
5455

@@ -964,8 +965,14 @@ def test_get_ciphers(self):
964965

965966
def test_set_groups(self):
966967
ctx = ssl.create_default_context()
967-
self.assertIsNone(ctx.set_groups('P-256:X25519'))
968-
self.assertRaises(ssl.SSLError, ctx.set_groups, 'P-256:xxx')
968+
# We use P-256 and P-384 (FIPS 186-4) that are alloed by OpenSSL
969+
# even if FIPS module is enabled. Ignoring unknown groups is only
970+
# supported since OpenSSL 3.3.
971+
self.assertIsNone(ctx.set_groups('P-256:P-384'))
972+
973+
self.assertRaises(ssl.SSLError, ctx.set_groups, 'P-256:foo')
974+
if CAN_IGNORE_UNKNOWN_OPENSSL_GROUPS:
975+
self.assertIsNone(ctx.set_groups('P-256:?foo'))
969976

970977
@unittest.skipUnless(CAN_GET_AVAILABLE_OPENSSL_GROUPS,
971978
"OpenSSL version doesn't support getting groups")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve the error messages that may be raised by
2+
:meth:`~socket.socket.setsockopt`.

Modules/socketmodule.c

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3332,32 +3332,59 @@ sock_setsockopt(PyObject *self, PyObject *args)
33323332
{
33333333
PySocketSockObject *s = _PySocketSockObject_CAST(self);
33343334

3335+
Py_ssize_t arglen;
33353336
int level;
33363337
int optname;
33373338
int res;
3338-
Py_buffer optval;
3339+
Py_buffer buffer;
33393340
int flag;
33403341
unsigned int optlen;
3341-
PyObject *none;
3342+
PyObject *optval;
3343+
3344+
if (!PyArg_ParseTuple(args, "iiO|I:setsockopt",
3345+
&level, &optname, &optval, &optlen))
3346+
{
3347+
return NULL;
3348+
}
3349+
3350+
arglen = PyTuple_Size(args);
3351+
if (arglen == 3 && optval == Py_None) {
3352+
PyErr_Format(PyExc_TypeError,
3353+
"setsockopt() requires 4 arguments when the third argument is None",
3354+
arglen);
3355+
return NULL;
3356+
}
3357+
if (arglen == 4 && optval != Py_None) {
3358+
PyErr_Format(PyExc_TypeError,
3359+
"setsockopt() only takes 4 arguments when the third argument is None (got %T)",
3360+
optval);
3361+
return NULL;
3362+
}
33423363

33433364
#ifdef AF_VSOCK
33443365
if (s->sock_family == AF_VSOCK) {
3366+
if (!PyIndex_Check(optval)) {
3367+
PyErr_Format(PyExc_TypeError,
3368+
"setsockopt() argument 3 for AF_VSOCK must be an int (got %T)",
3369+
optval);
3370+
}
33453371
uint64_t vflag; // Must be set width of 64 bits
33463372
/* setsockopt(level, opt, flag) */
3347-
if (PyArg_ParseTuple(args, "iiK:setsockopt",
3348-
&level, &optname, &vflag)) {
3349-
// level should always be set to AF_VSOCK
3350-
res = setsockopt(get_sock_fd(s), level, optname,
3351-
(void*)&vflag, sizeof vflag);
3352-
goto done;
3373+
if (!PyArg_Parse(optval, "K", &vflag)) {
3374+
return NULL;
33533375
}
3354-
return NULL;
3376+
// level should always be set to AF_VSOCK
3377+
res = setsockopt(get_sock_fd(s), level, optname,
3378+
(void*)&vflag, sizeof vflag);
3379+
goto done;
33553380
}
33563381
#endif
33573382

33583383
/* setsockopt(level, opt, flag) */
3359-
if (PyArg_ParseTuple(args, "iii:setsockopt",
3360-
&level, &optname, &flag)) {
3384+
if (PyIndex_Check(optval)) {
3385+
if (!PyArg_Parse(optval, "i", &flag)) {
3386+
return NULL;
3387+
}
33613388
#ifdef MS_WINDOWS
33623389
if (optname == SIO_TCP_SET_ACK_FREQUENCY) {
33633390
DWORD dummy;
@@ -3374,36 +3401,40 @@ sock_setsockopt(PyObject *self, PyObject *args)
33743401
goto done;
33753402
}
33763403

3377-
PyErr_Clear();
3378-
/* setsockopt(level, opt, None, flag) */
3379-
if (PyArg_ParseTuple(args, "iiO!I:setsockopt",
3380-
&level, &optname, Py_TYPE(Py_None), &none, &optlen)) {
3404+
/* setsockopt(level, opt, None, optlen) */
3405+
if (optval == Py_None) {
33813406
assert(sizeof(socklen_t) >= sizeof(unsigned int));
33823407
res = setsockopt(get_sock_fd(s), level, optname,
33833408
NULL, (socklen_t)optlen);
33843409
goto done;
33853410
}
33863411

3387-
PyErr_Clear();
33883412
/* setsockopt(level, opt, buffer) */
3389-
if (!PyArg_ParseTuple(args, "iiy*:setsockopt",
3390-
&level, &optname, &optval))
3391-
return NULL;
3392-
3413+
if (PyObject_CheckBuffer(optval)) {
3414+
if (!PyArg_Parse(optval, "y*", &buffer)) {
3415+
return NULL;
3416+
}
33933417
#ifdef MS_WINDOWS
3394-
if (optval.len > INT_MAX) {
3395-
PyBuffer_Release(&optval);
3396-
PyErr_Format(PyExc_OverflowError,
3397-
"socket option is larger than %i bytes",
3398-
INT_MAX);
3399-
return NULL;
3400-
}
3401-
res = setsockopt(get_sock_fd(s), level, optname,
3402-
optval.buf, (int)optval.len);
3418+
if (buffer.len > INT_MAX) {
3419+
PyBuffer_Release(&buffer);
3420+
PyErr_Format(PyExc_OverflowError,
3421+
"socket option is larger than %i bytes",
3422+
INT_MAX);
3423+
return NULL;
3424+
}
3425+
res = setsockopt(get_sock_fd(s), level, optname,
3426+
buffer.buf, (int)buffer.len);
34033427
#else
3404-
res = setsockopt(get_sock_fd(s), level, optname, optval.buf, optval.len);
3428+
res = setsockopt(get_sock_fd(s), level, optname, buffer.buf, buffer.len);
34053429
#endif
3406-
PyBuffer_Release(&optval);
3430+
PyBuffer_Release(&buffer);
3431+
goto done;
3432+
}
3433+
3434+
PyErr_Format(PyExc_TypeError,
3435+
"socket option should be int, bytes-like object or None (got %T)",
3436+
optval);
3437+
return NULL;
34073438

34083439
done:
34093440
if (res < 0) {

Objects/typeobject.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10585,7 +10585,10 @@ _Py_slot_tp_getattr_hook(PyObject *self, PyObject *name)
1058510585
getattr = _PyType_LookupRef(tp, &_Py_ID(__getattr__));
1058610586
if (getattr == NULL) {
1058710587
/* No __getattr__ hook: use a simpler dispatcher */
10588+
#ifndef Py_GIL_DISABLED
10589+
// Replacing the slot is only thread-safe if there is a GIL.
1058810590
tp->tp_getattro = _Py_slot_tp_getattro;
10591+
#endif
1058910592
return _Py_slot_tp_getattro(self, name);
1059010593
}
1059110594
/* speed hack: we could use lookup_maybe, but that would resolve the

Python/specialize.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -935,8 +935,7 @@ analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, un
935935
PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__));
936936
has_getattr = getattr != NULL;
937937
if (has_custom_getattribute) {
938-
if (getattro_slot == _Py_slot_tp_getattro &&
939-
!has_getattr &&
938+
if (!has_getattr &&
940939
Py_IS_TYPE(getattribute, &PyFunction_Type)) {
941940
*descr = getattribute;
942941
*tp_version = ga_version;
@@ -1259,12 +1258,6 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
12591258
return -1;
12601259
case GETATTRIBUTE_IS_PYTHON_FUNCTION:
12611260
{
1262-
#ifndef Py_GIL_DISABLED
1263-
// In free-threaded builds it's possible for tp_getattro to change
1264-
// after the call to analyze_descriptor. That is fine: the version
1265-
// guard will fail.
1266-
assert(type->tp_getattro == _Py_slot_tp_getattro);
1267-
#endif
12681261
assert(Py_IS_TYPE(descr, &PyFunction_Type));
12691262
_PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
12701263
if (!function_check_args(descr, 2, LOAD_ATTR)) {

Tools/tsan/suppressions_free_threading.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,5 @@ race:list_inplace_repeat_lock_held
4343
race:PyObject_Realloc
4444

4545
# gh-133467. Some of these could be hard to trigger.
46-
race_top:_Py_slot_tp_getattr_hook
4746
race_top:set_tp_bases
4847
race_top:type_set_bases_unlocked

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5219,7 +5219,7 @@ AC_CHECK_FUNCS([ \
52195219
posix_spawn_file_actions_addclosefrom_np \
52205220
pread preadv preadv2 process_vm_readv \
52215221
pthread_cond_timedwait_relative_np pthread_condattr_setclock pthread_init \
5222-
pthread_kill pthread_get_name_np pthread_getname_np pthread_set_name_np
5222+
pthread_kill pthread_get_name_np pthread_getname_np pthread_set_name_np \
52235223
pthread_setname_np pthread_getattr_np \
52245224
ptsname ptsname_r pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
52255225
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \

0 commit comments

Comments
 (0)