Привет, ЛОР!
Наткнулся тут на прекрасную историю о том, как использование казалось бы обычных функций из libc может оторвать жопу. И даже Rust не поможет!
Ссылка: https://www.edgedb.com/blog/c-stdlib-isn-t-threadsafe-and-even-safe-rust-didn-t-save-us
Для Ъ:
Функции getenv() и setenv() небезопасны в многопоточных программах. В частности, вызов setenv() во время выполнения getenv() в другом потоке может привести к порче памяти и падению программы. Это особенно релевантно на ARM64, потому как архитектура предоставляет меньше гарантий по части очерёдности выполнения команд.
И если бы это можно было списать на кривые руки авторов статьи, проблемы бы не было. Но тут суть в том, что огромное количество библиотек дёргают getenv() и setenv() под капотом с разными целями, в том числе гнутое gettext и прочие openssl.
Скажи, ЛОР, сишники совсем разучились писать безопасный код? Как с этим жить-то вообще?
UPD:
Подробный пост об этой проблеме: https://www.evanjones.ca/setenv-is-not-thread-safe.html
Прекрасное оттуда:
glibc uses an array to hold pointers to the "NAME=value" strings. It holds a lock in setenv() when changing this array, but not in getenv(). If a thread calling setenv() needs to resize the array of pointers, it copies the values to a new array and frees the previous one. This can cause other threads executing getenv() to crash, since they are now iterating deallocated memory.
То есть, вызов getenv() из glibc потенциально является use-after-free в многопоточной программе и от этого никак нельзя защититься.