Skip to content

Commit fcd1e07

Browse files
authored
Merge branch 'main' into issue-153252
2 parents 80d9b86 + 08759ff commit fcd1e07

4 files changed

Lines changed: 28 additions & 16 deletions

File tree

.github/workflows/build.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,6 @@ jobs:
554554
- Thread
555555
free-threading:
556556
- false
557-
- true
558557
sanitizer:
559558
- TSan
560559
include:
@@ -566,6 +565,17 @@ jobs:
566565
sanitizer: ${{ matrix.sanitizer }}
567566
free-threading: ${{ matrix.free-threading }}
568567

568+
# XXX: Temporarily allow this job to fail to not block PRs.
569+
build-san-free-threading:
570+
# ${{ '' } is a hack to nest jobs under the same sidebar category.
571+
name: Sanitizers${{ '' }} # zizmor: ignore[obfuscation]
572+
needs: build-context
573+
if: needs.build-context.outputs.run-ubuntu == 'true'
574+
uses: ./.github/workflows/reusable-san.yml
575+
with:
576+
sanitizer: TSan
577+
free-threading: true
578+
569579
cross-build-linux:
570580
name: Cross build Linux
571581
runs-on: ubuntu-26.04
@@ -669,6 +679,7 @@ jobs:
669679
- test-hypothesis
670680
- build-asan
671681
- build-san
682+
- build-san-free-threading
672683
- cross-build-linux
673684
- cifuzz
674685
if: always()
@@ -680,6 +691,7 @@ jobs:
680691
allowed-failures: >-
681692
build-android,
682693
build-emscripten,
694+
build-san-free-threading,
683695
build-windows-msi,
684696
build-ubuntu-ssltests,
685697
test-hypothesis,

Lib/test/test_ssl.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,19 +1604,24 @@ def dummycallback(sock, servername, ctx, cycle=ctx):
16041604
gc.collect()
16051605
self.assertIs(wr(), None)
16061606

1607-
@unittest.skipUnless(support.Py_GIL_DISABLED,
1608-
"test is only useful if the GIL is disabled")
16091607
@threading_helper.requires_working_threading()
16101608
def test_sni_callback_race(self):
1611-
# Replacing sni_callback while handshakes are in-flight must not
1609+
# Replacing sni_callback while a handshake is in-flight must not
16121610
# crash (use-after-free on the callback in free-threaded builds).
1611+
#
1612+
# Use a single handshake thread: OpenSSL has internal data races
1613+
# on shared SSL_CTX state when multiple handshakes run
1614+
# concurrently against the same context (gh-150191). Concurrency
1615+
# on the *setter* is what exercises the fix from gh-149816, so
1616+
# multiple toggler threads race against each other and against
1617+
# the one handshake worker.
16131618
client_ctx, server_ctx, hostname = testing_context()
16141619

16151620
server_ctx.sni_callback = lambda *a: None
1616-
done = threading.Event()
1621+
deadline = time.monotonic() + 0.1
16171622

16181623
def do_handshakes():
1619-
while not done.is_set():
1624+
while time.monotonic() < deadline:
16201625
c_in = ssl.MemoryBIO()
16211626
c_out = ssl.MemoryBIO()
16221627
s_in = ssl.MemoryBIO()
@@ -1643,19 +1648,11 @@ def do_handshakes():
16431648
c_in.write(s_out.read())
16441649

16451650
def toggle_callback():
1646-
while not done.is_set():
1651+
while time.monotonic() < deadline:
16471652
server_ctx.sni_callback = lambda *a: None
16481653
server_ctx.sni_callback = None
16491654

1650-
workers = max(4, (os.cpu_count() or 4) * 2)
1651-
threads = [threading.Thread(target=do_handshakes)
1652-
for _ in range(workers)]
1653-
threads.append(threading.Thread(target=toggle_callback))
1654-
1655-
with threading_helper.catch_threading_exception() as cm:
1656-
with threading_helper.start_threads(threads):
1657-
done.set()
1658-
self.assertIsNone(cm.exc_value)
1655+
threading_helper.run_concurrently([do_handshakes] + 4 * [toggle_callback])
16591656

16601657
def test_cert_store_stats(self):
16611658
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a potential :exc:`SystemError` during vector calls when memory allocation fails.
2+
A :exc:`MemoryError` is now raised instead.

Python/ceval.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ _PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_ssize_t nargs, PyObject
10561056
// +1 in case PY_VECTORCALL_ARGUMENTS_OFFSET is set.
10571057
result = PyMem_Malloc((nargs + 1) * sizeof(PyObject *));
10581058
if (result == NULL) {
1059+
PyErr_NoMemory();
10591060
return NULL;
10601061
}
10611062
}

0 commit comments

Comments
 (0)