Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Set no_preserve_tags for copies of structs without capabilities
This allows inlining of structure assignments for structs that are at least capability size but do not contain any capabilities (e.g. `struct { long a; long b; }`). We can also set the attribute for all trivial auto var-init cases since those patterns never contain valid capabilities. Due to C's effective type rules, we have to be careful when setting the attribute and only perform the type-base tag-preservation analysis if we know the effective type. For example, marking a memcpy() to/from `long*` as not tag-preserving could result in tag stripping for code that uses type casts. Such code is correct even under strict aliasing rules since the first store to a memory location determines the type. Example from #506: ``` void *malloc(__SIZE_TYPE__); void *memcpy(void *, const void *, __SIZE_TYPE__); void foo(long **p, long **q) { *p = malloc(32); *q = malloc(32); (*p)[0] = 1; (*p)[1] = 2; *(void (**)(long **, long **))(*p + 2) = &foo; memcpy(*q, *p, 32); } ``` Despite the memcpy() argument being a long* (and therefore intuitively not tag preserving), we can't add the attribute since we don't actually know the type of the underlying object (malloc creates an allocated with no declared type). From C99: ``` The effective type of an object for an access to its stored value is the declared type of the object, if any (footnote 75: Allocated objects have no declared type). If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access. ``` There is another important caveat: we have to conservatively assume that the copy affects adjacent data (e.g. C++ subclass fields) that could hold capabilities if we don't know the copy size. If the copy size is <= sizeof(T), we can mark copies as non-tag-preserving since it cannot affect trailing fields (even if we are actually copying a subclass). We are also conservative if the structure contains an array of type ((un)signed) char or std::byte since those are often used to store arbitrary data (including capabilities). We could make this check more strict and require the array to be capability aligned, but that could be done as a follow-up change.
- Loading branch information
1 parent
8a3ebe2
commit 73fbe6d
Showing
18 changed files
with
783 additions
and
247 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.