Skip to content

Commit 1aa3725

Browse files
Merge branch 'main' into improve-globglob-docstrings
2 parents 7c16dc8 + 50c479e commit 1aa3725

File tree

5 files changed

+38
-4
lines changed

5 files changed

+38
-4
lines changed

Doc/c-api/datetime.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ macros.
3030

3131
This is not compatible with subinterpreters.
3232

33+
.. versionchanged:: 3.15
34+
35+
This macro is now thread safe.
36+
3337
.. c:type:: PyDateTime_CAPI
3438
3539
Structure containing the fields for the datetime C API.
@@ -44,6 +48,11 @@ macros.
4448

4549
This variable is only available once :c:macro:`PyDateTime_IMPORT` succeeds.
4650

51+
.. versionchanged:: 3.15
52+
53+
This variable should not be accessed directly as direct access is not thread-safe.
54+
Use :c:func:`PyDateTime_IMPORT` instead.
55+
4756
.. c:type:: PyDateTime_Date
4857
4958
This subtype of :c:type:`PyObject` represents a Python date object.

Doc/whatsnew/3.15.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,6 +1563,8 @@ New features
15631563
thread state.
15641564
(Contributed by Victor Stinner in :gh:`139653`.)
15651565

1566+
* Add :c:func:`PyUnstable_SetImmortal` C-API function to mark objects as :term:`immortal`.
1567+
(Contributed by Kumar Aditya in :gh:`143300`.)
15661568

15671569
Changed C APIs
15681570
--------------
@@ -1571,6 +1573,9 @@ Changed C APIs
15711573
flag is set then :c:macro:`Py_TPFLAGS_HAVE_GC` must be set too.
15721574
(Contributed by Sergey Miryanov in :gh:`134786`.)
15731575

1576+
* :c:macro:`PyDateTime_IMPORT` is now thread safe. Code that directly checks ``PyDateTimeAPI``
1577+
for ``NULL`` should be updated to call :c:macro:`PyDateTime_IMPORT` instead.
1578+
(Contributed by Kumar Aditya in :gh:`141563`.)
15741579

15751580
Porting to Python 3.15
15761581
----------------------

Lib/test/test_repl.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,22 @@ def test_multiline_string_parsing(self):
143143
output = kill_python(p)
144144
self.assertEqual(p.returncode, 0)
145145

146+
@cpython_only
147+
def test_lexer_buffer_realloc_with_null_start(self):
148+
# gh-144759: NULL pointer arithmetic in the lexer when start and
149+
# multi_line_start are NULL (uninitialized in tok_mode_stack[0])
150+
# and the lexer buffer is reallocated while parsing long input.
151+
long_value = "a" * 2000
152+
user_input = dedent(f"""\
153+
x = f'{{{long_value!r}}}'
154+
print(x)
155+
""")
156+
p = spawn_repl()
157+
p.stdin.write(user_input)
158+
output = kill_python(p)
159+
self.assertEqual(p.returncode, 0)
160+
self.assertIn(long_value, output)
161+
146162
def test_close_stdin(self):
147163
user_input = dedent('''
148164
import os
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix undefined behavior in the lexer when ``start`` and ``multi_line_start``
2+
pointers are ``NULL`` in ``_PyLexer_remember_fstring_buffers()`` and
3+
``_PyLexer_restore_fstring_buffers()``. The ``NULL`` pointer arithmetic
4+
(``NULL - valid_pointer``) is now guarded with explicit ``NULL`` checks.

Parser/lexer/buffer.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ _PyLexer_remember_fstring_buffers(struct tok_state *tok)
1313

1414
for (index = tok->tok_mode_stack_index; index >= 0; --index) {
1515
mode = &(tok->tok_mode_stack[index]);
16-
mode->start_offset = mode->start - tok->buf;
17-
mode->multi_line_start_offset = mode->multi_line_start - tok->buf;
16+
mode->start_offset = mode->start == NULL ? -1 : mode->start - tok->buf;
17+
mode->multi_line_start_offset = mode->multi_line_start == NULL ? -1 : mode->multi_line_start - tok->buf;
1818
}
1919
}
2020

@@ -27,8 +27,8 @@ _PyLexer_restore_fstring_buffers(struct tok_state *tok)
2727

2828
for (index = tok->tok_mode_stack_index; index >= 0; --index) {
2929
mode = &(tok->tok_mode_stack[index]);
30-
mode->start = tok->buf + mode->start_offset;
31-
mode->multi_line_start = tok->buf + mode->multi_line_start_offset;
30+
mode->start = mode->start_offset < 0 ? NULL : tok->buf + mode->start_offset;
31+
mode->multi_line_start = mode->multi_line_start_offset < 0 ? NULL : tok->buf + mode->multi_line_start_offset;
3232
}
3333
}
3434

0 commit comments

Comments
 (0)