You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement restrictions on taking addresses of members and variables. (checkedc#490)
Checked C restricts taking the addresses of:
1. Members with member bounds declarations.
2. Members used in member bounds declarations.
3. Variables with bounds declarations.
4. Variables/variable members used in bounds declarations.
This change implements restrictions 1 through 3. This addresses issue checkedc#213 and part of issue checkedc#212.
- Taking the address of non-array members with or used in bounds declarations is now an error.
- Taking the address of non-array members with or used in bounds-safe interfaces is allowed in unchecked scopes. It is an error in checked scopes. In unchecked scopes, we don't warn about this, even though it could go wrong. We don't want to add warnings for existing code. We could add an optional warning if we wanted to.
- Taking the address of non-array variables with bounds declaration is now an error.
It is OK to take the address of an array variable or member because you can't use the resulting pointer to modify the pointer that the array converts to.
We recognize variations on these restrictions, such as taking the address of a parenthesized lvalue expression or taking the address of an expression where a bounds-safe interface cast has been inserted.
This was more complex to implement than the specification describes because of the possible use of nested members. See the long comment describing the algorithm in CheckedCAlias.cpp. We handle a few different cases:
- The simple case where a member bounds expression only uses members declared in the current structure.
- A member bounds expression uses members from a nested structure of the current structure. In this case, we do not allow the address of the nested structure to be taken. Given
```
struct NestedLen {
int len;
};
struct S {
struct NestedLen n;
_Array_ptr<int> p : count(n.len);
}
```
we don't allow the address of n to be taken.
- A structure with bounds is embedded in another structure, and then an address of member used in member bounds is taken.
We handle these cases by recognizing "paths" of member accesses and using that to recognize paths that may result in aliases to members used in bounds, and paths that won't result in aliases to members used in bounds.
All of the benchmarks that we converted to Checked C compile with these restrictions in place. This is a step toward removing one of the caveats in the SecDev paper. We still need to restrict taking the address of variables and variable members used in bounds declarations to complete the aliasing restrictions.
It'll be interesting to see what happens on real-world code. We could loosen some of the restrictions, for example, and allow taking the addresses involving constant-sized bounds (bounds that only involve the variable or member).
I found and fixed a bug in the lexicographic comparison of declarations. We were supposed to be comparing pointers to names in declarations, and compared pointers to the declarations instead. We then tried dereferencing the pointers to names.
Testing:
- I've added a new file containing tests of address-of expressions in the Checked C repo. This will be subject to a separate pull request.
- Passed clang tests on Linux x64.
- Passed LNT tests on Linux x64.
- Passed automated testing on Windows.
0 commit comments