Skip to content

Commit d0a3ef7

Browse files
authored
Merge branch 'main' into narrowing-to-constants-in-branches-with-is
2 parents 8c95c5f + 7ca9e7a commit d0a3ef7

File tree

25 files changed

+440
-292
lines changed

25 files changed

+440
-292
lines changed

.github/workflows/jit.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ on:
77
- 'Python/optimizer*.c'
88
- 'Python/executor_cases.c.h'
99
- 'Python/optimizer_cases.c.h'
10+
- '**_testinternalcapi**'
1011
- '!Python/perf_jit_trampoline.c'
1112
- '!**/*.md'
1213
- '!**/*.ini'
@@ -17,6 +18,7 @@ on:
1718
- 'Python/optimizer*.c'
1819
- 'Python/executor_cases.c.h'
1920
- 'Python/optimizer_cases.c.h'
21+
- '**_testinternalcapi**'
2022
- '!Python/perf_jit_trampoline.c'
2123
- '!**/*.md'
2224
- '!**/*.ini'

Doc/c-api/descriptor.rst

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@ found in the dictionary of type objects.
1010

1111
.. XXX document these!
1212
13-
.. c:var:: PyTypeObject PyProperty_Type
14-
15-
The type object for the built-in descriptor types.
16-
17-
1813
.. c:function:: PyObject* PyDescr_NewGetSet(PyTypeObject *type, struct PyGetSetDef *getset)
1914
2015
@@ -74,9 +69,26 @@ found in the dictionary of type objects.
7469
.. c:function:: PyObject* PyWrapper_New(PyObject *, PyObject *)
7570
7671
72+
.. c:macro:: PyDescr_COMMON
73+
74+
This is a :term:`soft deprecated` macro including the common fields for a
75+
descriptor object.
76+
77+
This was included in Python's C API by mistake; do not use it in extensions.
78+
For creating custom descriptor objects, create a class implementing the
79+
descriptor protocol (:c:member:`~PyTypeObject.tp_descr_get` and
80+
:c:member:`~PyTypeObject.tp_descr_set`).
81+
82+
7783
Built-in descriptors
7884
^^^^^^^^^^^^^^^^^^^^
7985
86+
.. c:var:: PyTypeObject PyProperty_Type
87+
88+
The type object for property objects. This is the same object as
89+
:class:`property` in the Python layer.
90+
91+
8092
.. c:var:: PyTypeObject PySuper_Type
8193
8294
The type object for super objects. This is the same object as

Doc/c-api/exceptions.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,17 @@ Exception Classes
793793
Return :c:member:`~PyTypeObject.tp_name` of the exception class *ob*.
794794
795795
796+
.. c:macro:: PyException_HEAD
797+
798+
This is a :term:`soft deprecated` macro including the base fields for an
799+
exception object.
800+
801+
This was included in Python's C API by mistake and is not designed for use
802+
in extensions. For creating custom exception objects, use
803+
:c:func:`PyErr_NewException` or otherwise create a class inheriting from
804+
:c:data:`PyExc_BaseException`.
805+
806+
796807
Exception Objects
797808
=================
798809

Include/internal/pycore_dict.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ extern Py_ssize_t _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject
114114

115115
extern int _PyDict_GetMethodStackRef(PyDictObject *dict, PyObject *name, _PyStackRef *method);
116116

117+
extern Py_ssize_t _PyDict_LookupIndexAndValue(PyDictObject *, PyObject *, PyObject **);
117118
extern Py_ssize_t _PyDict_LookupIndex(PyDictObject *, PyObject *);
118119
extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key);
119120

Include/internal/pycore_optimizer.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
115115

116116

117117
#define REF_IS_BORROWED 1
118+
#define REF_IS_INVALID 2
119+
#define REF_TAG_BITS 3
118120

119-
#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_IS_BORROWED)))
121+
#define JIT_BITS_TO_PTR_MASKED(REF) ((JitOptSymbol *)(((REF).bits) & (~REF_TAG_BITS)))
120122

121123
static inline JitOptSymbol *
122124
PyJitRef_Unwrap(JitOptRef ref)
@@ -133,6 +135,18 @@ PyJitRef_Wrap(JitOptSymbol *sym)
133135
return (JitOptRef){.bits=(uintptr_t)sym};
134136
}
135137

138+
static inline JitOptRef
139+
PyJitRef_WrapInvalid(void *ptr)
140+
{
141+
return (JitOptRef){.bits=(uintptr_t)ptr | REF_IS_INVALID};
142+
}
143+
144+
static inline bool
145+
PyJitRef_IsInvalid(JitOptRef ref)
146+
{
147+
return (ref.bits & REF_IS_INVALID) == REF_IS_INVALID;
148+
}
149+
136150
static inline JitOptRef
137151
PyJitRef_StripReferenceInfo(JitOptRef ref)
138152
{
@@ -227,15 +241,15 @@ PyAPI_FUNC(int) _PyDumpExecutors(FILE *out);
227241
PyAPI_FUNC(void) _Py_ClearExecutorDeletionList(PyInterpreterState *interp);
228242
#endif
229243

230-
int _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr, int stop_tracing_opcode);
244+
PyAPI_FUNC(int) _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr, int stop_tracing_opcode);
231245

232246
PyAPI_FUNC(int)
233247
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame,
234248
_Py_CODEUNIT *curr_instr, _Py_CODEUNIT *start_instr,
235249
_Py_CODEUNIT *close_loop_instr, int curr_stackdepth, int chain_depth, _PyExitData *exit,
236250
int oparg, _PyExecutorObject *current_executor);
237251

238-
void _PyJit_FinalizeTracing(PyThreadState *tstate, int err);
252+
PyAPI_FUNC(void) _PyJit_FinalizeTracing(PyThreadState *tstate, int err);
239253
void _PyJit_TracerFree(_PyThreadStateImpl *_tstate);
240254

241255
void _PyJit_Tracer_InvalidateDependency(PyThreadState *old_tstate, void *obj);

Include/internal/pycore_optimizer_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11+
#include <stdbool.h>
1112
#include "pycore_uop.h" // UOP_MAX_TRACE_LENGTH
1213

1314
// Holds locals, stack, locals, stack ... (in that order)
@@ -142,6 +143,8 @@ typedef struct _JitOptContext {
142143
JitOptRef *n_consumed;
143144
JitOptRef *limit;
144145
JitOptRef locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
146+
_PyUOpInstruction *out_buffer;
147+
int out_len;
145148
} JitOptContext;
146149

147150

Include/internal/pycore_tstate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ typedef struct _PyJitTracerState {
6060
_PyJitTracerTranslatorState translator_state;
6161
JitOptContext opt_context;
6262
_PyUOpInstruction code_buffer[UOP_MAX_TRACE_LENGTH];
63+
_PyUOpInstruction out_buffer[UOP_MAX_TRACE_LENGTH];
6364
} _PyJitTracerState;
6465

6566
#endif

Lib/test/support/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3303,3 +3303,10 @@ def linked_to_musl():
33033303
return _linked_to_musl
33043304
_linked_to_musl = tuple(map(int, version.split('.')))
33053305
return _linked_to_musl
3306+
3307+
3308+
def control_characters_c0() -> list[str]:
3309+
"""Returns a list of C0 control characters as strings.
3310+
C0 control characters defined as the byte range 0x00-0x1F, and 0x7F.
3311+
"""
3312+
return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"]

Lib/test/test_wsgiref.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from unittest import mock
22
from test import support
3-
from test.support import socket_helper
3+
from test.support import socket_helper, control_characters_c0
44
from test.test_httpservers import NoLogRequestHandler
55
from unittest import TestCase
66
from wsgiref.util import setup_testing_defaults
@@ -503,6 +503,16 @@ def testExtras(self):
503503
'\r\n'
504504
)
505505

506+
def testRaisesControlCharacters(self):
507+
headers = Headers()
508+
for c0 in control_characters_c0():
509+
self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", "val")
510+
self.assertRaises(ValueError, headers.__setitem__, "key", f"val{c0}")
511+
self.assertRaises(ValueError, headers.add_header, f"key{c0}", "val", param="param")
512+
self.assertRaises(ValueError, headers.add_header, "key", f"val{c0}", param="param")
513+
self.assertRaises(ValueError, headers.add_header, "key", "val", param=f"param{c0}")
514+
515+
506516
class ErrorHandler(BaseCGIHandler):
507517
"""Simple handler subclass for testing BaseHandler"""
508518

Lib/wsgiref/headers.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# existence of which force quoting of the parameter value.
1010
import re
1111
tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]')
12+
_control_chars_re = re.compile(r'[\x00-\x1F\x7F]')
1213

1314
def _formatparam(param, value=None, quote=1):
1415
"""Convenience function to format and return a key=value pair.
@@ -41,6 +42,8 @@ def __init__(self, headers=None):
4142
def _convert_string_type(self, value):
4243
"""Convert/check value type."""
4344
if type(value) is str:
45+
if _control_chars_re.search(value):
46+
raise ValueError("Control characters not allowed in headers")
4447
return value
4548
raise AssertionError("Header names/values must be"
4649
" of type str (got {0})".format(repr(value)))

0 commit comments

Comments
 (0)