Skip to content
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

Sanitizer builds #5272

Merged
merged 7 commits into from
Feb 12, 2025
Merged

Sanitizer builds #5272

merged 7 commits into from
Feb 12, 2025

Conversation

wolfsage
Copy link
Contributor

@wolfsage wolfsage commented Feb 7, 2025

This is mostly intended to be used in tandem with https://github.com/cyrusimap/cyrus-docker/pull/29/files but can stand on its own.

If you compile cyrus with -fsanitize=address and then run LSAN_OPTIONS=suppressions=leaksanitizer.suppress make check all tests pass minus those few skipped.

If you compile cyrus with -fsanitize=undefined, make check will pass but throw some warnings. To get it to fail, compile with -fsanitize=undefined -fsanitize-undefined-trap-on-error or use halt_on_error=1 make check.

When running cassandane with such a build, LSAN_OPTIONS and UBSAN_OPTIONS will be configured to send log files somewhere cassandane can see them, and cass will detect/report any detected log entries as failures (similar to how testrunner --valgrind works).

There's lots of work to go to get asan/ubsan tests passing, but this gets the infrastructure in place.

With this, we can add asan/ubsan builds to all CI if we want. Draft here: #5273

Note that ubsan will complain until a lot of things are fixed... we could start with just asan builds and work our way up to getting everything passing with both.

Copy link
Contributor

@ksmurchison ksmurchison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert but LGTM. Ellie should definitely review

Copy link
Collaborator

@rjbs rjbs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Perl changes seem correct to me. I'm doing a practical test now and might have questions. The C changes should be reviewed by someone else. (I see Ken has approved.)

Of special interest is the change to build-with-cyruslibs, which adds some more CFLAGS. I believe that @elliefm recently said that we should move from using the environment to adding options to ./configure. It would be good to get her take here. But mostly: 👍🏽

Copy link
Contributor

@elliefm elliefm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, a few notes but nothing major

@elliefm
Copy link
Contributor

elliefm commented Feb 10, 2025

Of special interest is the change to build-with-cyruslibs, which adds some more CFLAGS. I believe that @elliefm recently said that we should move from using the environment to adding options to ./configure. It would be good to get her take here. But mostly: 👍🏽

For flags that we think should be the default for all builds, we want to put them in AM_CFLAGS et al. But we don't want these flags for all builds.

We could add a --with-whatever or --enable-whatever configure option to set these up. Have a look at AC_ARG_ENABLE(unit-tests, [...] through AM_CONDITIONAL([CUNIT], [...] in configure.ac for an example of how we do that for the cunit tests, and AC_ARG_ENABLE(coverage, [...] through AM_CONDITIONAL([HAVE_COVERAGE], [...] for coverage testing.

I think we'd usually add a detail like this later though, once we've driven it in anger a bit and have some sense of the ergonomics we want.

Copy link
Member

@rsto rsto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is very important work for this project, thanks for making it happen.

I haven't approved nor requested changes, because I would first like to understand if the couple commits that address specific ubsan/asan issues are required to be part of this PR or just a byproduct of getting the test infrastructure in place. E.g. I'm not sure I agree with adding the aligned (2) attributes, but I don't want to hold back shipping this PR with these nits.

@wolfsage
Copy link
Contributor Author

Of special interest is the change to build-with-cyruslibs, which adds some more CFLAGS. I believe that @elliefm recently said that we should move from using the environment to adding options to ./configure. It would be good to get her take here. But mostly: 👍🏽

For flags that we think should be the default for all builds, we want to put them in AM_CFLAGS et al. But we don't want these flags for all builds.

We could add a --with-whatever or --enable-whatever configure option to set these up. Have a look at AC_ARG_ENABLE(unit-tests, [...] through AM_CONDITIONAL([CUNIT], [...] in configure.ac for an example of how we do that for the cunit tests, and AC_ARG_ENABLE(coverage, [...] through AM_CONDITIONAL([HAVE_COVERAGE], [...] for coverage testing.

I think we'd usually add a detail like this later though, once we've driven it in anger a bit and have some sense of the ergonomics we want.

Thanks, this was my plan too. I'd like to get this info into the build using a configure opt or make opt, and have cyr_info reflect it so cassandane can inspect it and do the right thing, but I did not want to fight with automake at this point

@wolfsage wolfsage force-pushed the sanitizer-builds branch 2 times, most recently from bf41889 to e8003b7 Compare February 10, 2025 12:31
@wolfsage
Copy link
Contributor Author

@elliefm I'd like to merge this if you're okay with it, and we can fix up other things down the line

Copy link
Contributor

@elliefm elliefm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

I've included a patch in my comment that removes the valgrind suppression for the leak that your wrap_int_parser_nofree change fixes, since we won't need that suppression anymore with the leak fixed. Use it if you want, doesn't need re-review if you do.

If you don't use it, I'll eventually clean up the stale suppression myself anyway next time I think about it. But the history would be nicer if the suppression is removed in the same commit as the leak is fixed :)

CU_syslogMatchEnd stores .re in a pointer for the caller to use
in error messages. We can't free that string and then hand it back,
so instead switch slmatch to using a buffer and copy strings into
it as necessary.
Due to the way search_expr.c is linked in with cunit tests, this
variable causes an odr violation that's detected by asan.
You can use this by doing:

    export LSAN_OPTIONS="suppressions=leaksanitizer.suppress"

And then running make check.

For AddressSanitizer, you need to compile cyrus with:

    -fsanitize=address -static-libasan

in both LDFLAGS and CFLAGS
When testing fatal conditions, wrap_int_parser mallocs prot and b, but the
related free() calls never happen because we longjmp away.

Split wrap_int_parser into two methods, one which expects to complete fully
and can handle cleaning up memory itself, and one where the caller must
clean up memory. Then use the caller-version for fatal tests.

This keeps LeakSanitizer happy.
Unlike --valgrind, asan and ubsan are baked into the running programs. If
they happen to be compiled in, they'll write to the provided log
directories, and we can pull out any errors they generate automatically.

Note that unfortunately there are some buggy (still?) verisons of clang
and/or gcc where the UBSAN_OPTIONS log_path overrides the ASAN_OPTIONS
log_path. The effect of this is that tests run with ASan will misreport
errors as ubsan errors, but I think we can live with that.
Now that parse.testc doesn't leak on fatal errors we don't need to suppress
valgrind reports for it!
@wolfsage wolfsage merged commit c280de5 into cyrusimap:master Feb 12, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants