posix_spawn crashes when python is run with gprofng
還沒有人認領這個 Issue。
- 主要語言
- Python
- 星號
- 77.2k
- 分支
- 36k
- PR 合併指標
- PR 指標待擷取
描述
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
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
研究方向
從 Modules/posixmodule.c 中的 py_posix_spawn 開始,使用提供的 gprofng 下的重現程式比較 posix_spawn 呼叫前後對 environ 的處理。當環境在呼叫期間發生變更時重現程式不再當機,同時 posix_spawn 的一般行為維持不變,即可視為完成。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- c, python
- 領域
- operating-systems
- Issue 類型
- 缺陷
- 難度
- 3/5
- 預估耗時
- 1-2 天
- 活躍度
- 停滯
- 描述清晰度
- 描述清楚
- 新手友好度
- 35/100