-
-
Notifications
You must be signed in to change notification settings - Fork 8.4k
ci: Enable UBSan for 'longlong' builds in CI, add stack size for sanitizer builds. #17735
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
Conversation
3b2a4a8
to
008b8c5
Compare
This comment was marked as outdated.
This comment was marked as outdated.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #17735 +/- ##
=======================================
Coverage 98.38% 98.38%
=======================================
Files 171 171
Lines 22297 22297
=======================================
Hits 21938 21938
Misses 359 359 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code size report:
|
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
1dc48bf
to
818de93
Compare
f7b8aee
to
86ec523
Compare
5aea471
to
dc24ac6
Compare
@jepler Curious of your opinion on this PR, if you have any time to look? |
I tested the new Also tested on PYBD_SF2, PYBV10, RPI_PICO. It passes on all of those. Very good! |
dc24ac6
to
9438e5b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm in favor of it.
I looked into alternatives for detecting ubsan/asan and while gcc documentation shows they were grumpy at having to implement __has_feature
, it does work as needed.
@@ -43,6 +43,11 @@ typedef unsigned int uint; | |||
#ifndef __has_builtin | |||
#define __has_builtin(x) (0) | |||
#endif | |||
#ifndef __has_feature | |||
// This macro is supported by Clang and gcc>=14 | |||
#define __has_feature(x) (0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gcc isn't keen on __has_feature. Their docs say
Note that ‘__has_feature’ and ‘__has_extension’ are not recommended for use in new code, and are only provided for compatibility with Clang.
That said, I don't see a better way to autodetect the sanitizers, though. (gcc has a predefined macro for asan but clang doesn't; neither defines a macro for ubsan)
Given that you defensively check whether has_feature is available and that this works in practice in clang and gcc-14 (I checked gcc-14) and obey the MP_UBSAN / MP_ASAN in preference to detection I think it's fine. There's also explicit documentation from clang that this is how to check for asan. The corresponding bit was missing from the ubsan documentation but it does work too (tested in gcc-14 and clang-19).
I retested the revised Apart from the above comment about the license, this looks good to go in. |
Also rewrite the sanitizer argument variables to not assume a variant. longlong variant currently fails in this config, due to a bug fixed in follow-up commit. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Clang and gcc>=14 can use __has_feature() to detect if a sanitizer is enabled, but older GCC has no mechanism - need to set a macro explicitly for this to be recognised. Necessary for increasing some resource limits in sanitizer builds. Important not to use to avoid real issues! This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
The specific problem seems to be that the runtime "Python stack frame" function call is several times more expensive in stack usage when running with UBSan on older GCC (observed on gcc 11.4 as used in CI, would get 'RuntimeError: maximum recursion depth exceeded' when running some tests with UBSan enabled.) Other stack usage (i.e. from pushing things on the stack in Python) stays the same. Whatever causes the usage seems to be mostly gone in later GCC versions. Includes a refactor to apply the same stack size multipliers for the default thread stack size same as the main stack size. This goes in a new port-specific header as it depends on macros in misc.h, so can't be in mpconfigport.h. A side effect of this is that the default thread stack size is now doubled on ARM, same as the main stack size. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Necessary on the unix port when running with sanitizers, as the newly increased stack size can run all tests at N=5000 without raising RuntimeError, and increasing N to fix this causes issues on other configurations. This way the test progressively builds a deeper data structure until it fails with RuntimeError. This is theoretically slower, but not noticeably so in reality. Signed-off-by: Angus Gratton <angus@redyak.com.au>
9438e5b
to
22deeeb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating.
Summary
stress/recurse_iternext.py
test, as this test fails on sanitizer builds with the increased stack. (Sanitizer build stack usage is only increased due to certain C function calls, but this test - I think - consumes stack in a way which isn't impacted by sanitizers so it can now handle many more iterations compared to a standard build). This took a while to find a good approach, but what's there seems more accurate than the previous heuristic and doesn't take noticeably more time to execute.Testing
stress/recurse_iternext.py
test on unix port with and without sanitizers, esp32 port with SPIRAM, and esp8266 port.Trade-offs and Alternatives
This work was funded through GitHub Sponsors