This is an archive of the discontinued LLVM Phabricator instance.

[Compiler-rt][MSan] fix param_tls_limit test
ClosedPublic

Authored by mohit.bhakkad on Feb 10 2016, 10:20 PM.

Details

Summary

Looking at __msan_test_shadow definition, we can see that it returns index of first poisioned (uninitialized) member of the argument.

For example consider :

int i[10];
printf("\nBefore init: %d",__msan_test_shadow(&i, sizeof(i)));
i[0] = 7;
printf("\nAfter    init: %d",__msan_test_shadow(&i, sizeof(i)));

will give output:

Before init: 0
After init: 4

So to check for tls limit, I am initializing 801 size buffer till 800th value, and we can see that part which does not fit is considered fully initialized, i.e. instead of 800, __msan_test_shadow will return -1.

Please correct my understanding if its wrong, as I can see test fails on every arch except x86.

Diff Detail

Repository
rL LLVM

Event Timeline

mohit.bhakkad retitled this revision from to [Compiler-rt][MSan] fix param_tls_limit test.
mohit.bhakkad updated this object.
mohit.bhakkad added reviewers: eugenis, kcc, samsonov.
mohit.bhakkad set the repository for this revision to rL LLVM.
mohit.bhakkad updated this object.
mohit.bhakkad added subscribers: slthakur, jaydeep.
eugenis edited edge metadata.Feb 11 2016, 1:06 PM

If an argument does not fit in param-tls, it becomes completely unpoisoned - not just the overflow part, but the entire argument.
I suspect that on non-x86 targets the large struct may be passed as several smaller arguments, and then the ones that fit (completely!) will be poisoned.

If an argument does not fit in param-tls, it becomes completely unpoisoned - not just the overflow part, but the entire argument.
I suspect that on non-x86 targets the large struct may be passed as several smaller arguments, and then the ones that fit (completely!) will be poisoned.

I can confirm that we slice large aggregates into a series of smaller arguments (i32 on o32, i64 on n32/n64) in clang.

test/msan/param_tls_limit.cc
37

Typo: poision

Thanks,

So can we have modified test as a separate test for archs other than x86?

Maybe you can define PARTIAL_OVERFLOW() for the arguments that start in param-tls and end outside of it. It would be defined the same as OVERFLOW() on x86, and the same as NO_POISON() on other platforms, resulting in a slightly weaker test.

Maybe you can define PARTIAL_OVERFLOW() for the arguments that start in param-tls and end outside of it. It would be defined the same as OVERFLOW() on x86, and the same as NO_POISON() on other platforms, resulting in a slightly weaker test.

Hi @eugenis, I didn't understood your suggestion clearly.
I understand OVERFLOW() and NO_POISON() will have same definition.

In this revision, I initiialized arguments that start in param-tls and end outside of it upto till param-tls size, so they will match condition of OVERFLOW().
Without initialing, they will match NO_OVERFLOW in archs other than x86.

What will be functionality of PARTIAL_OVERFLOW(), and if you want to keep same test for all archs, than should we initialize overflow arguments ?

Currently this test has OVERFLOW() and NO_OVERFLOW() checks.
Arguments that are entirely under the tls limit are poisoned on all platforms and can be checked with NO_OVERFLOW.
Arguments (at the source level) that are partially over limit are unpoisoned on X86, and partially poisoned on other platforms due to them being splitted into multiple IR arguments. We can check that with a PARTIAL_OVERFLOW() macro, defined differently based on the platform.

Please keep f_many and f_many2 tests, they are valuable.

PARTIALLY_INIT should not be necessary. If an argument partially overflows, at least the last byte of it will be unpoisoned in the callee - test for that.

mohit.bhakkad edited edge metadata.

defining PARTIAL_OVERFLOW to check shadow of arguments greater than tls limit on platforms where big arguments are sliced in smaller ones.

eugenis added inline comments.Feb 26 2016, 12:39 PM
test/msan/param_tls_limit.cc
33

800 in "&x + 800" would be 800 * sizeof(x).

something like this to test the last byte of x: (char *)(&(x) + 1) - 1

Changed as suggested.

Updating revision with full context patch

eugenis accepted this revision.Feb 29 2016, 1:01 PM
eugenis edited edge metadata.

LGTM

test/msan/param_tls_limit.cc
36–37

This one is also PARTIAL_OVERFLOW. Does not really matter since "int", naturally, does not get split.

This revision is now accepted and ready to land.Feb 29 2016, 1:01 PM
This revision was automatically updated to reflect the committed changes.