Repository navigation
Add autotest option to run unit tests under asan / run them in CI / fix bugs foud - #33976
Conversation
khancyr
left a comment
There was a problem hiding this comment.
looks like we don't have libclang-rt-18-dev on the container ...
do you prefer I update the container and we keep the same tag, or I create another tag and we change the tag version on the CI workflow ?
| examples, | ||
| sitl | ||
| ] | ||
| exclude: | ||
| # boards.py only adds the sanitizer link flag when building |
There was a problem hiding this comment.
should we add support for asan on gcc ? from the docs it should be supported
Maybe we should just take the test fixes for now? I mean, 4 errors in all of the tests over how many years - and the errors were only in the tests. So I think I should just archive the asan thing for later.... |
|
well, did you try to run on some SITL test ? our unittests are far from covering significant part of the codebase. |
09e810a to
3e4ac4a
Compare
Somewhere here I think I have more stuff. We do have this: |
I'm kind of tempted to just apt-install it. Thoughts? |
|
libclang-rt-18-dev is 3 772 ko, so should be ok. |
5165a2f to
16d2c10
Compare
|
16d2c10 to
632ace1
Compare
Global Size Summary (Total Flash delta in bytes)Built from b22e283 rebased onto 8ab6afd
|
Previous review (2026-09-22)Automated review note — AI-generated (Claude), cross-checked by a second independent Claude pass against the live diff. Please sanity-check before acting. Full report: https://uav.tridgell.net/DevCallReviews/2026_09_22_AIReview/devcall_pr_reviews.html#pr33976 Reviewed at head The good news first, since it is the load-bearing question for a sanitizer job: a real asan error does fail both new jobs, and both passes tested it independently on two toolchains. I injected a leaked Also worth saying: khancyr's "should we add support for asan on gcc?" is answered well. Dropping the forced clang is a real coverage win, and your comment about it is accurate — 1. BUG —
|
94d5d1d to
56921c0
Compare
Previous review (2026-09-24)Automated review note — AI-generated (Claude), validated against the live diff. Please sanity-check before acting. Re-reviewed at head Resolved by that push
A correction to my own previous advice on that last one. I suggested either Still open (all minor)
Checked and clean
CI at this head was still running when I snapshotted (35 passing, 72 pending, 0 failing) — in particular the four asan jobs that were red last round had not reported yet. |
56921c0 to
15b8eb4
Compare
Previous review (2026-10-15)Automated review note — AI-generated (Claude+Codex), validated against the live diff. Please sanity-check before acting. Reviewed at head Re-reviewed at Blocking
Non-blocking
Checked and cleanWith gcc CI for |
15b8eb4 to
8633e03
Compare
Previous review (2026-10-15)Automated review note — AI-generated (Claude+Codex), validated against the live diff. Please sanity-check before acting. Reviewed at head Re-reviewed at Fixed
Non-blocking
Not run: full vehicle SITL under ASAN (your Copter/Plane/etc. results weren't reproduced), a native macOS link, and the vehicle autotest CI jobs, which were still queued. |
8633e03 to
68baabd
Compare
Previous review (2026-10-16)Automated review note — AI-generated (Claude+Codex), validated against the live diff. Please sanity-check before acting. Reviewed at head Re-reviewed at Fixed
Non-blocking
Not run: full vehicle SITL under ASAN, a macOS link, and clang ASAN at this head. CI at this head was still pending. |
…ing test The test explicitly called the destructor and then read the freed buffer, and filled a 2048 byte array with 'a' with no terminator before passing it to printf. Both are found by address sanitizer.
…e test The string was replaced three times without being freed, and the last one was read back after its destructor had been called.
The index was advanced before the last two checks, so they tested the following result and read past the end of the table on the final call.
Two tests allocated an ekf_imu_buffer and never deleted it. Note that deleting one does not free the memory init() allocated inside it, as these classes have no destructor; that allocation is covered by the leak suppressions instead.
The link flag was only added for clang, so a GCC ASAN build got instrumented objects and an uninstrumented link line. That broke waf's own configure checks, each of which links a test program: they failed with undefined references to __asan_init and the features were recorded as unavailable. HAVE_BYTESWAP_H going missing that way made AP_Common/missing/byteswap.h define __bswap_16 itself, which then collided with the system header.
The framework treats a non-empty sanitizer log as a failure, so anything written to it which is not an error turns a good run into a bad one. Turn off the summary of suppressed allocations for the same reason verbosity is already zero here. Also stop llvm-symbolizer fetching debug info over the network, which it does by default on Ubuntu; it blocks for about ninety seconds a frame, so the report is never finished before the process goes away.
gcc and clang spell the sanitizer test differently and neither understands the other's form, so the __has_feature test has to be nested; on gcc a flat "defined(__has_feature) && __has_feature(...)" is a syntax error rather than a short circuit. LSAN_IGNORE_OBJECT marks a single allocation as deliberately kept. It is preferable to a suppression naming the function which allocated it, as a suppression is matched against every frame of the allocation stack and so also hides everything else allocated below that function.
These two are kept for the life of the process. Marking the objects themselves is exact, where a suppression naming _parse_command_line would cover the whole of that function - including constructing the simulated vehicle and running _sitl_setup().
Some allocations are made once and deliberately kept for the life of the vehicle: the EKF buffers, the sensor backends and the simulated serial devices. Listing them here means leak checking can be left on rather than turned off wholesale. The sanitizer finds this function by itself, so no environment variable or external suppressions file is needed. Each entry is matched against every frame of the allocation stack, so naming the allocating function keeps the rest of its file checked. The EKF buffers are named by file because the two classes which allocate them have no destructor, so every allocation in it is deliberate.
Stop llvm-symbolizer fetching debug info over the network, which it does by default on Ubuntu and which blocks for about ninety seconds a frame. Ignored by tests which were not built with --asan.
--asan searched for a clang to build with, which has a surprising side effect: AP_Networking_Config.h disables AP_NETWORKING_ENABLED for clang on linux, so every sanitized build had all of the networking code compiled out of it. That is why the networking tests fail under --asan rather than being run. The sanitizer works with gcc as well, so honour CXX/CC when the caller has set them and otherwise leave the choice to waf.
build_examples did not take the asan argument that autotest.py passes it, so --asan build.examples died with a TypeError which the broad exception handler reported as a build failure. --asan is only implemented for the sitl board, so it is not passed to the cross-compiled boards. The examples send their output to /dev/null and most are killed with a signal rather than exiting, so point the sanitizer at a log file and fail the step if any example leaves a report behind.
The sanitizer's redzones push loop() to 3040 bytes, past the 2000 byte limit this example sets for itself, so the example cannot be built with --asan.
The WMM tables are read with a bilinear interpolation which uses the next sample along in both latitude and longitude, so the table edges and out-of-range positions are what need checking. Sweeping them under the address sanitizer covers the indexing as well as the results.
The interpolation reads the next sample along in both latitude and longitude, but the index was not constrained, so at latitude 90 or longitude 180 the +1 ran off the end of dec_tbl. Found by running the examples under the address sanitizer. Take the corner position back from the constrained index so that the interpolation still lines up with the table; the index is only constrained at the very edges, and the position is unchanged everywhere else.
The examples are built with --asan and run with autotest's --asan, which is what makes run.examples collect the sanitizer reports.
--asan is implemented for the sitl board alone, so the linux half of the run was building and running the same tests a second time without any instrumentation. The unit-tests job already covers them.
68baabd to
b22e283
Compare
|
Automated review note — AI-generated (Claude+Codex), validated against the live diff. Please sanity-check before acting. Reviewed at head Re-reviewed at Fixed
FYI, unchanged: examples that are SIGKILLed still never reach LSan's exit check. This comes from the existing kill logic. Not run: full vehicle SITL under ASAN, a macOS link, and a full clang ASAN build. CI at this head was still pending. |
Summary
Fixes bugs found by running the unit tests under asan
Classification & Testing (check all that apply and add your own)
Description
Adds infrastructure to run unit tests under asan and fixes bugs found...