-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Make write_debug_image MSAN-safe #5691
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -108,16 +108,19 @@ WEAK bool ends_with(const char *filename, const char *suffix) { | |
} | ||
|
||
struct ScopedFile { | ||
void *f; | ||
ALWAYS_INLINE ScopedFile(const char *filename, const char *mode) { | ||
f = fopen(filename, mode); | ||
void *const user_context; | ||
void *const f; | ||
ALWAYS_INLINE ScopedFile(void *user_context, const char *filename, const char *mode) | ||
: user_context(user_context), f(fopen(filename, mode)) { | ||
halide_msan_annotate_memory_is_initialized(user_context, &f, sizeof(f)); | ||
} | ||
ALWAYS_INLINE ~ScopedFile() { | ||
if (f) { | ||
fclose(f); | ||
} | ||
} | ||
ALWAYS_INLINE bool write(const void *ptr, size_t bytes) { | ||
halide_msan_annotate_memory_is_initialized(user_context, ptr, bytes); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this one necessary? We should annotate at the call site of this function when needed, not here. Writing uninitialized memory to a file does seem like it should in fact be an msan failure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem is that the memory isn't uninitialized, but msan's interceptor for fwrite() thinks it is:
That said... this is a gigantic hack and I probably should rethink this; it assumes/relies on the fact that everything we pass to fwrite() goes through a stack allocation of some sort (which is true) but doesn't actually enforce it (so code changes could easily break this). Alternate approaches that might make sense:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe a simple solution would be to use |
||
return f ? fwrite(ptr, bytes, 1, f) > 0 : false; | ||
} | ||
ALWAYS_INLINE bool open() const { | ||
|
@@ -144,7 +147,7 @@ WEAK extern "C" int32_t halide_debug_to_file(void *user_context, const char *fil | |
|
||
halide_copy_to_host(user_context, buf); | ||
|
||
ScopedFile f(filename, "wb"); | ||
ScopedFile f(user_context, filename, "wb"); | ||
if (!f.open()) { | ||
return -2; | ||
} | ||
|
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.
Please add a comment explaining that args to a syscall that live on the stack must be annotated when msan is on. I guess the filename and mode always come from .rodata? Otherwise this code is baffling.
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 don't think that's the problem. The filename and mode come from code with msan enabled, so they are annotated correctly. The problem here is that fopen wasn't built with msan, so the returned value looks uninitialized to msan.