python / python/cpython

3.11: _PyUnicode_Equal call sites lack error handling

Aperta
#98,879 5 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

interpreter-core type-bug
Lingua principale
Python
Stelle
77.2k
Fork
36k
Merge medio
1g 9h
PR unite (30g)
558

Descrizione

(Found while looking at https://github.com/python/cpython/issues/98783)

In https://github.com/python/cpython/commit/81c72044a181dbbfbf689d7a977d0d99090f26a8, several uses of _PyUnicode_EqualToASCIIId, which cannot fail, were replaced with _PyUnicode_Equal, which can fail: it calls PyUnicode_READY() in Python 3.11, and returns -1 on failure.

In Python 3.12, this is not a problem: _PyUnicode_Equal cannot fail, since it does not need to call PyUnicode_READY() since the wstr APIs were removed in https://github.com/python/cpython/commit/f9c9354a7a173eaca2aa19e667b5cf12167b7fed. But it is theoretically a problem in 3.11.

In 3.11, git grep "_PyUnicode_Equal(" turns up the following:

Include/cpython/unicodeobject.h:PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *, PyObject *);
Modules/_pickle.c:            use_newobj_ex = _PyUnicode_Equal(name, &_Py_ID(__newobj_ex__));
Modules/_pickle.c:                use_newobj = _PyUnicode_Equal(name, &_Py_ID(__newobj__));
Objects/longobject.c:    else if (_PyUnicode_Equal(byteorder, &_Py_ID(little)))
Objects/longobject.c:    else if (_PyUnicode_Equal(byteorder, &_Py_ID(big)))
Objects/longobject.c:    else if (_PyUnicode_Equal(byteorder, &_Py_ID(little)))
Objects/longobject.c:    else if (_PyUnicode_Equal(byteorder, &_Py_ID(big)))
Objects/typeobject.c:    if (mod != NULL && !_PyUnicode_Equal(mod, &_Py_ID(builtins)))
Objects/typeobject.c:        if (_PyUnicode_Equal(name, &_Py_ID(__dict__))) {
Objects/typeobject.c:        if (_PyUnicode_Equal(name, &_Py_ID(__weakref__))) {
Objects/typeobject.c:        if ((ctx->add_dict && _PyUnicode_Equal(slot, &_Py_ID(__dict__))) ||
Objects/typeobject.c:            (ctx->add_weak && _PyUnicode_Equal(slot, &_Py_ID(__weakref__))))
Objects/typeobject.c:            if (!_PyUnicode_Equal(slot, &_Py_ID(__qualname__)) &&
Objects/typeobject.c:                !_PyUnicode_Equal(slot, &_Py_ID(__classcell__)))
Objects/typeobject.c:    if (mod != NULL && !_PyUnicode_Equal(mod, &_Py_ID(builtins)))
Objects/typeobject.c:        _PyUnicode_Equal(name, &_Py_ID(__class__)))
Objects/typeobject.c:        if (_PyUnicode_Equal(name, &_Py_ID(__class__))) {
Objects/unicodeobject.c:_PyUnicode_Equal(PyObject *str1, PyObject *str2)
Python/ceval.c:            int res = _PyUnicode_Equal(left, right);
Python/errors.c:        if (!_PyUnicode_Equal(modulename, &_Py_ID(builtins)) &&
Python/errors.c:            !_PyUnicode_Equal(modulename, &_Py_ID(__main__))) {
Python/pythonrun.c:        if (!_PyUnicode_Equal(modulename, &_Py_ID(builtins)) &&
Python/pythonrun.c:            !_PyUnicode_Equal(modulename, &_Py_ID(__main__)))

Broken down:

  • _pickle.c
    • Could the result of _PyObject_LookupAttr(callable, &_Py_ID(__name__), &name) be unready?
  • longobject.c
  • typeobject.c
    • ctx->slots could be an arbitrary tuple of potentially-unready strings, so there should be some call to PyUnicode_READY() at or before type_new_visit_slots.
  • ceval.c
    • Already has the error checking (though it could be removed in 3.12!)
  • errors.c and pythonrun.c:
    • Arbitrary result of PyObject_GetAttr(exc_type, &_Py_ID(__module__)); might not be _READY()?

The good news is that this would be hard to run into in practice: it requires both using the old deprecated wstr APIs and running into a memory error during PyUnicode_READY().

cc @ericsnowcurrently @methane

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con git grep per _PyUnicode_Equal nel branch Python 3.11, quindi leggi i siti di chiamata elencati in Modules/_pickle.c, Objects/longobject.c, Objects/typeobject.c, Python/ceval.c, Python/errors.c e Python/pythonrun.c. Verifica se ogni input può essere un oggetto Unicode non pronto e come vengono propagati gli errori di PyUnicode_READY(). Il lavoro è completato quando i siti di chiamata interessati hanno una gestione sicura degli errori o una garanzia verificata di inizializzazione.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, python
Ambito
backend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.