python / python/cpython

posix_spawn crashes when python is run with gprofng

Abierto
#149,509 1 comentario 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

extension-modules type-bug
Lenguaje dominante
Python
Estrellas
77.2k
Forks
35.9k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

Bug report

Bug description:

I've been observing crashes when python code calls posix_spawn when being
run under gprofng.

As an example, I tested on a Fedora 42 x86_64 system with python3-3.13.13-1.fc42.x86_64
[Python 3.13.13 (main, Apr 8 2026, 00:00:00) [GCC 15.2.1 20260123 (Red Hat 15.2.1-7)] on linux]
and binutils-2.44-12.fc42.x86_64
[GNU gprofng binutils version 2.44]

Consider this script:

import os
os.posix_spawn("/usr/bin/echo", ["/usr/bin/echo", "world"], None)
print ("hello")

If I run this on its own, it works as expected:

$ python spawn.py
hello
world

But if I run it with gprofng, it crashes:

$ gprofng collect app python spawn.py
Creating experiment directory test.1.er (Process ID: 591620) ...
free(): invalid pointer
Aborted (core dumped)
$ world

The problem goes away if I change the third argument of the posix_spawn
command from None to os.environ. I also reproduce the crash with
cpython git main as of May 6 (65ed109b5de7bab28f1051336f0ae312205c4233).

The issue is that py_posix_spawn assumes that environ does not change
over the call to posix_spawn. However, when gprofng is used, it
interposes code wrapping the posix_spawn call that can modify the
environment (apparently to sanitize the environment from things like
LD_PRELOAD entries used by gprofng) and thus change environ.

In more detail, in py_posix_spawn, we have this before the spawn call:

    EXECV_CHAR **envlist = NULL;
    ...
    Py_ssize_t argc, envc;
    ...
    if (env == Py_None) {
#ifdef USE_DARWIN_NS_GET_ENVIRON
        environ = *_NSGetEnviron();
#endif
        envlist = environ;
    } else {
        envlist = parse_envlist(env, &envc);
        if (envlist == NULL) {
            goto exit;
        }
    }

and after the call:

    if (envlist && envlist != environ) {
        free_string_array(envlist, envc);
    }

So if the env argument is null and environ is changed by the call,
then we end up trying to free environ,
using a length taken from an uninitialized variable.

Here's one possible fix:

diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 5bd53c2146a..4fef8a60647 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -7961,6 +7961,7 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
         environ = *_NSGetEnviron();
 #endif
         envlist = environ;
+        envc = (Py_ssize_t)-1;
     } else {
         envlist = parse_envlist(env, &envc);
         if (envlist == NULL) {
@@ -8028,7 +8029,10 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
     if (attrp) {
         (void)posix_spawnattr_destroy(attrp);
     }
-    if (envlist && envlist != environ) {
+    /* Can't just test for envlist != environ because some tools, such as
+       gprofng, interpose code around the posix_spawn call that can change
+       environ. */
+    if (envlist && envc != (Py_ssize_t)-1) {
         free_string_array(envlist, envc);
     }
     if (argvlist) {
CPython versions tested on:

3.13, CPython main branch

Operating systems tested on:

Linux

Linked PRs
  • gh-149724

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza en Modules/posixmodule.c, en py_posix_spawn, y compara el manejo de environ antes y después de la llamada a posix_spawn con el reproductor proporcionado bajo gprofng. Se considerará terminado cuando el reproductor ya no se bloquee si el entorno cambia durante la llamada, mientras el comportamiento normal de posix_spawn permanezca intacto.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
c, python
Área
operating-systems
Tipo de issue
Error
Dificultad
3/5
Tiempo estimado
1-2 días
Estado de actividad
Estancado
Claridad
Bien especificado
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.