-
-
Notifications
You must be signed in to change notification settings - Fork 372
refactor: Replace strerror with strerror_r #6817
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Attempted Approaches for Testing pthread_create Failure in sentrycrashccd_initWe attempted to create a test for Approaches Tried:
Conclusion:It's not viable to continue finding a way to force |
|
@sentry review |
Replace stack-allocated buffer with thread-local storage to prevent use-after-free when the macro is used as a function argument. The stack buffer was deallocated before vsnprintf could read it, causing undefined behavior. Using __thread ensures the buffer persists beyond the macro scope while maintaining thread safety, as each thread has its own buffer.
|
@sentry review |
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 26f7b17 | 1218.47 ms | 1253.82 ms | 35.35 ms |
| 139db8b | 1231.50 ms | 1258.19 ms | 26.69 ms |
| 134fbdf | 1219.71 ms | 1240.35 ms | 20.64 ms |
| 83bb978 | 1238.33 ms | 1260.04 ms | 21.71 ms |
| 331dad6 | 1210.40 ms | 1242.06 ms | 31.67 ms |
| 85a741b | 1217.02 ms | 1239.27 ms | 22.25 ms |
| 083e8c5 | 1227.74 ms | 1262.37 ms | 34.62 ms |
| d7461dc | 1233.69 ms | 1255.29 ms | 21.60 ms |
| 939d583 | 1209.96 ms | 1251.09 ms | 41.13 ms |
| 5fcb6a1 | 1198.86 ms | 1226.89 ms | 28.03 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 26f7b17 | 23.75 KiB | 960.93 KiB | 937.19 KiB |
| 139db8b | 23.75 KiB | 920.64 KiB | 896.89 KiB |
| 134fbdf | 23.75 KiB | 875.25 KiB | 851.50 KiB |
| 83bb978 | 23.75 KiB | 920.64 KiB | 896.89 KiB |
| 331dad6 | 23.75 KiB | 928.12 KiB | 904.37 KiB |
| 85a741b | 23.75 KiB | 959.44 KiB | 935.69 KiB |
| 083e8c5 | 23.75 KiB | 981.75 KiB | 958.00 KiB |
| d7461dc | 23.75 KiB | 874.45 KiB | 850.70 KiB |
| 939d583 | 23.75 KiB | 1023.82 KiB | 1000.07 KiB |
| 5fcb6a1 | 24.14 KiB | 1.01 MiB | 1014.60 KiB |
|
@JoshuaMoelans @mujacica as this issue is quite hard to test with automated testing and is almost completely in the native layer of this SDK, I would appreciate your wisdom and kindly ask if you could please take a look if you spot any obvious issues with it. |
📜 Description
Replaces all occurrences of
strerrorwithstrerror_rusing the thread-safeSENTRY_STRERROR_Rmacro across the SentryCrash codebase.💡 Motivation and Context
Closes #4190
The
strerrorfunction is not thread-safe and can cause issues in multi-threaded environments. This PR replaces all uses ofstrerrorwith the thread-safestrerror_rfunction via theSENTRY_STRERROR_Rmacro.📋 Changes Summary
Core Changes
Added
SENTRY_STRERROR_Rmacro inSentryAsyncSafeLog.h:strerror_rusing XSI-compliant version (returns int on macOS/iOS)strerror_rfailures gracefullyReplaced
strerrorcalls in 11 SentryCrash source files:SentryCrashMonitor_AppState.c(2 replacements)SentryCrashMonitor_MachException.c(4 replacements)SentryCrashMonitor_Signal.c(4 replacements)SentryCrashCachedData.c(1 replacement)SentryCrashReport.c(6 replacements)SentryCrashReportStore.c(2 replacements)SentryCrashCxaThrowSwapper.c(4 replacements)SentryCrashDebug.c(2 replacements)SentryCrashFileUtils.c(20 replacements)SentryCrashJSONCodec.c(2 replacements)SentryCrashSysCtl.c(9 replacements)Total: 56
strerrorcalls replaced withSENTRY_STRERROR_RTest Coverage
SentryCrashDebug_Tests.m: Added ests forsentrycrashdebug_isBeingTracederror handlingSentryCrashFileUtils_Tests.m: Added tests covering:open,read,write,close,stat,mkdir,rmdir,rename,remove)SENTRY_STRERROR_RSentryCrashSysCtl_Tests.m: Expanded tests covering:sysctlfailure scenariosDocumentation
AGENTS.md: Added comprehensive guidelines for testing error handling paths:Other Changes
SentryLogC.hto useSENTRY_STRERROR_RmacroSentryViewHierarchyProviderHelper.mandSentrySessionReplaySyncC.cto use thread-safe error handling💚 How did you test it?
Tested Error Paths
Added unit tests for all testable error handling paths:
File operations (
SentryCrashFileUtils.c):open()failures - tested with invalid paths and closed file descriptorsread()failures - tested with closed file descriptorswrite()failures - tested with closed file descriptorsclose()failures - tested with invalid file descriptorsstat()failures - tested with invalid pathsmkdir()failures - tested with invalid parent directoriesrmdir()failures - tested with non-empty directoriesrename()failures - tested with invalid source/target pathsremove()failures - tested with invalid pathsSystem calls (
SentryCrashSysCtl.c):sysctl()failures - tested with invalid parameters and system limitsDebug operations (
SentryCrashDebug.c):sysctl()failures insentrycrashdebug_isBeingTracedAll tests verify that error messages are retrieved using
SENTRY_STRERROR_R(errno)for thread-safe error handling.Untestable Error Paths
Some error handling paths cannot be reliably tested in a test environment. All of these paths have been verified through code review to correctly use
SENTRY_STRERROR_R(errno)for thread-safe error message retrieval.System Call Failures
The following functions handle system call failures but cannot be reliably tested:
SentryCrashReport.c:addTextFileElement()- Error handling whenopen()failssentrycrashreport_writeRecrashReport()- Error handling whenrename()orremove()failsWhy untestable:
open(),rename(),remove()) are difficult to force reliablyResource Exhaustion Failures
SentryCrashCachedData.c:sentrycrashccd_init- Error handling whenpthread_create()failsWhy untestable:
setrlimit(RLIMIT_NPROC), thread exhaustion, andDYLD_INTERPOSE- none worked reliablyRLIMIT_NPROClimits processes, not threads directlyDYLD_INTERPOSEonly works for dynamically linked symbols;pthread_createcalls may be statically linkedSentryCrashCxaThrowSwapper.c:addPair(used byperform_rebinding_with_section) - Error handling whenmalloc()failsWhy untestable:
setrlimit(RLIMIT_AS)- both failed due to system restrictions or virtual memory overcommitSentryCrashDebug.c:sentrycrashdebug_isBeingTraced- Error handling whensysctl()fails (hardcoded valid parameters)Why untestable:
sysctlcalls may be statically linkedFile I/O Failures
SentryCrashJSONCodec.c:updateDecoder_readFile()- Error handling whenread()failsWhy untestable:
sentrycrashjson_addJSONFromFilemanages the file descriptor internallyJSONFromFileContext(which contains the fd) is not exposedNote: In contrast,
SentryCrashFileUtils_Tests.mtests work because those functions take the fd as a parameter, allowing tests to open, close, and pass a closed fd.Verification
All untestable error paths have been:
SENTRY_STRERROR_R(errno)AGENTS.mdfor documenting untestable error paths📝 Checklist
sendDefaultPIIis enabled.