This is an archive of the discontinued LLVM Phabricator instance.

[MSan] Ensure argument shadow initialized on memcpy
ClosedPublic

Authored by nikic on Apr 12 2022, 6:19 AM.

Details

Summary

We need to explicitly query the shadow here, because it is lazily initialized for arguments. Without opaque pointers this used to mostly work out, because there would be a bitcast to i8* present, and that would query the argument shadow.

Diff Detail

Event Timeline

nikic created this revision.Apr 12 2022, 6:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 12 2022, 6:19 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
nikic requested review of this revision.Apr 12 2022, 6:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 12 2022, 6:19 AM

I am not sure how this can help, I will try later today.
As I see it it just calculates the shadow address and these instructions will be removed as unused?

nikic added a comment.Apr 12 2022, 9:06 AM

I am not sure how this can help, I will try later today.
As I see it it just calculates the shadow address and these instructions will be removed as unused?

Shadow memory for arguments is lazily initialized. If we never call getShadow() for an argument, then we'll leave it uninitialized. In most cases this happens naturally, but for memcpy/memmove we call a builtin that will access the shadow internally, so we never perform the getShadow() call and never initialize the shadow.

vitalybuka added a comment.EditedApr 12 2022, 9:47 AM

I am not sure how this can help, I will try later today.
As I see it it just calculates the shadow address and these instructions will be removed as unused?

Shadow memory for arguments is lazily initialized. If we never call getShadow() for an argument, then we'll leave it uninitialized. In most cases this happens naturally, but for memcpy/memmove we call a builtin that will access the shadow internally, so we never perform the getShadow() call and never initialize the shadow.

I see. I suspect it does not work if instead of llvm.memcpy we have "call void @foo(i8* %p)" and "call void @foo_noundef(i8* noundef %p)"?

Most likely it would, as visitCallBase has it on all code paths, but could you add this into the test?

vitalybuka accepted this revision.Apr 12 2022, 9:52 AM
This revision is now accepted and ready to land.Apr 12 2022, 9:52 AM
eugenis accepted this revision.Apr 12 2022, 11:31 AM

Could you clarify that the problem is specifically with byval argument in the patch description?

Also, I'm wondering if we should make this copy explicit, perhaps by checking if the argument has any uses in the function body. I'm not 100% convinced that this is the only place where we forget to copy the shadow.

This change LGTM as a quick fix.

This revision was landed with ongoing or failed builds.Apr 12 2022, 2:50 PM
This revision was automatically updated to reflect the committed changes.
vitalybuka added a comment.EditedApr 12 2022, 2:54 PM

Works locally, so I landed it to fix the bot.
I will address my and @eugenis suggestions separately.