Skip to content

Stricter formal semantics for free - #592

Open
xavierleroy wants to merge 2 commits into
masterfrom
free-inject
Open

Stricter formal semantics for free#592
xavierleroy wants to merge 2 commits into
masterfrom
free-inject

Conversation

@xavierleroy

Copy link
Copy Markdown
Contributor

As currently modeled in the CompCert semantics, the free function accepts as arguments some pointers that were not returned by malloc, including pointers in the middle of a block. The reason for this tolerance is to make the semantics of free compatible with memory injections, which can transform a pointer returned by malloc into a pointer in the middle of a block. (At least conceptually; this is never necessary in CompCert's correctness proofs.)

This PR tightens the formal semantics of free so that it fails when given a pointer that does not point to the beginning of a block allocated by malloc. Compatibility with memory injections is ensured by an extra condition on memory injections.

Conceptually, we could associate a kind (global, stack, heap) with every memory block and require that blocks tagged "heap" are injected with offset 0. Instead, I chose to express the extra requirement on memory injections in terms of permissions and of metadata associated with heap blocks. The formal model of malloc and free uses negative offsets to store metadata (the size of the block), so that user code cannot read or write this metadata. In this PR, we require that valid negative offsets are injected with offset 0 and therefore cannot end up at nonnegative offsets. In other words, metadata should remain inaccessible to user code after memory injection.

The modeling of `malloc` and `free` uses a negative block offset to store
the size of the allocated block.  This ensures that user code cannot modify
the size using an ordinary store.  More generally, metadata can be stored
at negative block offsets to hide it from user code.

However, a memory injection could map this negative offset to a
nonnegative offset, manipulable by the user code.  In turn, this makes
`free` more lenient than it should be, e.g. it is possible to free a
pointer that was not returned by `malloc`.

This commit adds one condition to memory injections: if a block has
negative lower bound (i.e. valid negative offsets), its injection must
have delta = 0.

This condition is trivially satisfied by CompCert's uses of memory injections:
the only blocks that are injected with delta <> 0 are stack blocks, which
have lower bound 0.
Require that the argument `p` of `free(p)` points to the beginning of a block
(offset is 0).

Before, for compatibility with memory injections, `p` pointing in the
middle of a block was accepted, provided that the word before `p`
contains a valid length.  This is not ISO C, of course.

With the new definition of memory injections (previous commit), `free`
can fail on pointers in the middle of a block while remaining compatible
with memory injections.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant