-
Notifications
You must be signed in to change notification settings - Fork 184
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
Consider changing the treatment of null pointers. #137
Comments
Two things we need to think about, as brought up in the meeting today:
|
There was additional feedback from the meeting that it would be useful to understand where nullable pointers would be useful. The conjecture was that nullable pointers would be used a lot in data structures, but not used that much for local variables. A suggestion was that it would be useful to take some real-world code (such as OpenSSL) and mock up part of it with the proposed changes. I think one reason why nullable pointers might be used in data structures is that requiring that members have non-nullable pointers means that we need to check that members are initialized properly to non-null before they are used. This would mean expanding the treatment of initialization of data structures in the Checked C specification - zeroing allocated data would not be sufficient. For objects, we would have to make sure that an object with a non-null ponter does not escape before it is initialized. We would probably also need a flow-sensitive treatement of initialization of variables and data structures. |
After thinking about this, we decided that this would be a substantial language change that would require some effort to implement in the Checked C version of clang. We think it is more useful to get a working compiler with runtime checking first before making this language change, that is, implement the version 0.6 spec before making substantial changes to the language extension in this area. |
Overview
I am concerned that the treatment of null pointers in Checked C will lead to too many runtime checks. We have been implementing the runtime checks required by the current Checked C specification. At memory accesses using an array_ptr, there would be a null pointer check followed by a bounds checks. At pointer arithmetic involving array_ptr, there will also be a non-null check before the pointer arithmetic operation. There will be a lot of checking.
The problem is the semantics that we’ve chosen for bounds when null pointers are around: a pointer is either null or has valid bounds. The problem is that this means that a null pointer may not have valid bounds. From Section 3.1 of the Checked C v0.6 specification:
We chose this definition because C treats null pointers as interchangeable with other pointers. The definition results in less work and typing when converting programs. However, it has led to several issues in the semantics:
Proposal
We’re running into problems because we’re trying to combine bounds checking and the handling of null pointers. The fact that C pointers can either be null or point to valid objects is a source of complexity when reasoning about C programs.
I propose that we adapt the idea of nullable pointers to Checked C. We would use types to distinguish between the different ways in which null will be allowed or handled:
nullable
modifier that can be applied to ptr and array_ptr types.nullable ptr<T>
, a runtime null check is done before accessing memory.nullable array_ptr<T>
, a runtime null check is done before accessing memory. The runtime null check precedes the bounds check. The bounds for anullable array_ptr<T>
are only required to be valid when the value is non-null.Examples
It is a valid to assign a ptr variable a value that is guaranteed to be non-null. The following declarations and assignments are valid:
It is not valid to assign a ptr variable a value that is null. The following will be rejected at compile time:
It is valid to assign null to an array_ptr variable with bounds, if the bounds are empty:
The empty bounds are a subrange of any valid object.
It is invalid to assign to null to an array_ptr variable with non-empty bounds. This declaration is invalid:
bounds(NULL, NULL + 5) is not a subrange of a valid object.
It is valid to assign null to an nullable array_ptr variable with non-empty bounds. This declaration is valid:
Additional thoughts
ptr<T> x
is equivalent toarray_ptr<T> x : count(1)
. The bounds (NULL, NULL + 1) are invalid because no valid object includes NULL in it is bounds.Bounds-safe interfaces
My strawman proposal is to allow the keyword
nullable
to precede the in-line bounds declaration for an unchecked pointer type. For example:This implies in a checked context that calloc returns a
nullable array_ptr<void>
.For interface types, nullable can be applied as a type qualifier to _Ptr types. For example, the bounds-safe interface for the string-to-double function would be:
If endptr is non-null, strtod returns the location where the conversion stopped by modifying *endptr.
Conversions
Next steps
I modified the Checked C wrappers from the C standard library to add nullable type modifiers where necessary. I didn’t modify functions involving strings because we haven’t added support for null-terminated arrays. The results are on Github at https://github.com/dtarditi/checkedc/tree/nullable. There are two quick take-aways:
The text was updated successfully, but these errors were encountered: