Skip to content

Commit 6f4f359

Browse files
committed
Add Unicode checks
- `_Py*UnicodeObject_CAST` macros assert they have the right bits for the shape - `_PyUnicode_IsModifiable` & `_PyUnicodeWriter_CanWrite` assert that UTF-8 storage hasn't been allocated yet
1 parent 2423814 commit 6f4f359

3 files changed

Lines changed: 14 additions & 7 deletions

File tree

‎Include/cpython/unicodeobject.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,10 @@ typedef struct {
186186
(assert(PyUnicode_Check(op)), \
187187
_Py_CAST(PyASCIIObject*, (op)))
188188
#define _PyCompactUnicodeObject_CAST(op) \
189-
(assert(PyUnicode_Check(op)), \
189+
(assert(!_PyASCIIObject_CAST(op)->state.ascii || !_PyASCIIObject_CAST(op)->state.compact), \
190190
_Py_CAST(PyCompactUnicodeObject*, (op)))
191191
#define _PyUnicodeObject_CAST(op) \
192-
(assert(PyUnicode_Check(op)), \
192+
(assert(!_PyASCIIObject_CAST(op)->state.compact), \
193193
_Py_CAST(PyUnicodeObject*, (op)))
194194

195195

‎Include/internal/pycore_unicodeobject.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern "C" {
1111
#include "pycore_fileutils.h" // _Py_error_handler
1212
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
1313
#include "pycore_runtime.h" // _Py_LATIN1_CHR()
14+
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_PTR_ACQUIRE
1415

1516

1617
// Maximum code point of Unicode 6.0: 0x10ffff (1,114,111).
@@ -108,6 +109,11 @@ _PyUnicode_EnsureUnicode(PyObject *obj)
108109
return 0;
109110
}
110111

112+
static inline char* _PyUnicode_UTF8(PyObject *op)
113+
{
114+
return FT_ATOMIC_LOAD_PTR_ACQUIRE(_PyCompactUnicodeObject_CAST(op)->utf8);
115+
}
116+
111117
#ifndef NDEBUG
112118
static inline int
113119
_PyUnicodeWriter_CanWrite(_PyUnicodeWriter *writer)
@@ -125,6 +131,9 @@ _PyUnicodeWriter_CanWrite(_PyUnicodeWriter *writer)
125131
assert(PyUnstable_Unicode_GET_CACHED_HASH(buffer) == -1);
126132
assert(!PyUnicode_CHECK_INTERNED(buffer));
127133
assert(!_Py_IsImmortal(buffer));
134+
assert(PyUnicode_IS_COMPACT_ASCII(buffer)
135+
|| _PyUnicode_UTF8(buffer) == NULL
136+
|| _PyUnicode_UTF8(buffer) == PyUnicode_DATA(buffer));
128137
return 1;
129138
}
130139
#endif

‎Objects/unicodeobject.c‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,6 @@ NOTE: In the interpreter's initialization phase, some globals are currently
114114
# define _PyUnicode_CHECK(op) PyUnicode_Check(op)
115115
#endif
116116

117-
static inline char* _PyUnicode_UTF8(PyObject *op)
118-
{
119-
return FT_ATOMIC_LOAD_PTR_ACQUIRE(_PyCompactUnicodeObject_CAST(op)->utf8);
120-
}
121-
122117
static inline char* PyUnicode_UTF8(PyObject *op)
123118
{
124119
assert(_PyUnicode_CHECK(op));
@@ -1767,6 +1762,9 @@ _PyUnicode_IsModifiable(PyObject *unicode)
17671762
return 0;
17681763
if (PyUnicode_CHECK_INTERNED(unicode))
17691764
return 0;
1765+
if (_PyUnicode_HAS_UTF8_MEMORY(unicode)) {
1766+
return 0;
1767+
}
17701768
#ifdef Py_DEBUG
17711769
/* singleton refcount is greater than 1 */
17721770
assert(!unicode_is_singleton(unicode));

0 commit comments

Comments
 (0)