Closed
Description
Example
Illustrated in #94700:
char buf[256] = "10000000000-100000000000 rw-p 00000000 00:00 0";
long rss = 0;
// This test exposes a bug in DFSan's sscanf, that leads to flakiness
// in release_shadow_space.c (see
// https://github.com/llvm/llvm-project/issues/91287)
if (sscanf(buf, "Garbage text before, %ld, Garbage text after", &rss) == 1) {
printf("Error: matched %ld\n", rss); // THIS ERROR HAPPENS WITH DFSAN
return 1;
}
Implications
- It caused a failure in the release_shadow_space.c test (DFSAN release_shadow_space.c is flaky #91287).
- DFSan's release_shadow_space.c test relies on sscanf to scrape the RSS from /proc/maps output and is therefore scraping numbers from irrelevant output (e.g., base addresses), leading to test flakiness.
- The test
can behas been fixed by filtering the sscanf matches e.g., by using strstr to check for 'Rss: ' ([dfsan] Fix release_shadow_space.c #94770).
- This will also change the semantics of instrumented programs that use sscanf, because text may erroneously match.
- This probably needs a real fix in DFSan's sscanf.
Relevant code in DFSan's scan_buffer:
static int scan_buffer(char *str, size_t size, const char *fmt,
dfsan_label *va_labels, dfsan_label *ret_label,
dfsan_origin *str_origin, dfsan_origin *ret_origin,
va_list ap) {
...
if (*formatter.fmt_cur != '%') {
// Ordinary character. Consume all the characters until a '%' or the end
// of the string.
for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
++formatter.fmt_cur) {
// EDITOR'S NOTE: SHOULD THIS CHECK AGAINST THE INPUT STRING?
}
retval = formatter.scan();
dfsan_set_label(0, formatter.str_cur(),
formatter.num_written_bytes(retval));