Repository navigation
verify: State the extents of pointer fields, and separate pairs with an extent over their extents - #72
Merged
Conversation
…ded integer quantifiers in the prelude.
…d or not reported.
…r does not represent.
…try value, separated like the others.
…nts in the release notes.
… to report, so no header's is mangled.
This was referenced Oct 24, 2026
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A record that describes a buffer by a pointer and a length (a string view, a span) could not state the buffer's extent. On the base (with #71):
Now
cv::valid(b.data, b.len)is the extent of the buffer the field addresses:Stacked on #71 (B3a-5, the last part of plan item B3a;
zero_prefixlends a localBuftozero, which is #71).Design
\at(s->data, Pre), so the field gets a synthetic parameter after the declared ones:s->data(VFunction::FieldParams, fields joined by->), displayed as written,b.datafor a reference. It is the field's value at entry by definition:enterassumess->data_0 == load(s + offset)in the entry heap, an entry fact without definedness (it says nothing where the field cannot be read) that no caller establishes, since a call binds the parameter inParamMapto the field at its arguments. The marker's argument converts to the parameter, soinstrumentUBCheckssees a bare pointer and records the extent, its validity clause, and the bounds checks exactly as for a parameter.pointerFieldOfParameter): a pointer to a complete object type, a field of the object a pointer or reference parameter addresses, nested fields included:s->f,r.f,(*s).f,s->inner.f. A field of an array element (s->items[k].f) keeps the marker error.AddressEntry, mutable unless the field points to const; the marker's parameter converts the argument to a pointer to const, so the field's own type decides): a mutable buffer is disjoint from the other address parameters' objects, its own record's included, sob.data[i] = 0leavesb.lenalone; two buffers through pointers to const may be one.validextent are disjoint "unless either pointer is null or either extent is empty". The extent separation said so, but the pair's one-object separation was required as well, so an empty extent into another object (touch(b, &b->len, 0)) failedaliasing, and so did a localBufholding a zero-length extent of a parameter.dropSingleObjectSeparationremoves a pair's one-object separation where one of them has an extent; a pointer with an empty extent reaches nothing, so the fact it carried was never used.Tests
suite/pointer_field_extents.cpp(Z3, BMC, VCR):v->data,b.data(a reference),p->out.dataandp.out.data(nested fields), each bounded by its extent (pastfailsbounds); a field without an extent is no object (unknownfailsbounds);Buf, and one element too long (boundsat the call);bounds);copyverifies,copy(b, b)failsaliasing), two const views may be one;empty_insideverifies,nonempty_insidefailsaliasing);extent_separation.cppnow expects onealiasingassert at a call between two extents, their separation, where it expected the first elements' separation as well.Mutants, each built and run on
pointer_field_extents.cpp,extent_separation.cpp,record_references.cpp, andlocal_record_arguments.cpp: 11 of 11 killed.pointer_field_extentspointer_field_extentspointer_field_extentspointer_field_extentspointer_field_extentspointer_field_extentspointer_field_extentspointer_field_extents,extent_separationpointer_field_extentspointer_field_extents(p.out.data, added for it)pointer_field_extents,local_record_arguments,record_referencesDocs
Checked
extent_separation.cppfailed only its Layer 2 check of the secondaliasingassert, which this PR removes (every verdict of it unchanged, the--no-check-ubrun, where extents fold away and the element separation remains, included); 1202 s with 40 workers.