-
Notifications
You must be signed in to change notification settings - Fork 274
[DOCS] Add documentation on CBMC Shadow Memory intrinsics #7913
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
Conversation
Codecov ReportAll modified lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #7913 +/- ##
===========================================
+ Coverage 78.56% 78.99% +0.42%
===========================================
Files 1699 1701 +2
Lines 195804 195932 +128
===========================================
+ Hits 153833 154769 +936
+ Misses 41971 41163 -808 ☔ View full report in Codecov by Sentry. |
(The original artefact's implementation is outlined in the paper [CBMC-SSM: | ||
Bounded Model Checking of C Programs with Symbolic Shadow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
describes...
|
||
## Introduction | ||
|
||
CBMC contains a component that supports *Symbolic Shadow Memory*. Shadow memory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CBMC supports Symbolic Shadow Memory.
analysis program and that shadows the standard memory of the program. In that | ||
memory structure, a user can create fields, for which he can later set and | ||
retrieve values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the shadow memory a user can set or retrieve values.
memory structure, a user can create fields, for which he can later set and | ||
retrieve values. | ||
|
||
By doing so, one can organise his own tracking of metadata related to the code, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
his
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be gender neutral? Also the person who is the object of this sentence is expected to be a user of cbmc. Therefore - "By doing so, a user can organise their own tracking of metadata"...
By doing so, one can organise his own tracking of metadata related to the code, | ||
in a way that is then considered by the backend of CBMC during analysis. This | ||
can be used to implement novel analyses that the CBMC framework itself doesn't | ||
support - for example, the paper above presents as an example a taint analysis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
" - for example, " -> ". For example,"
|
||
A user can interact with the Symbolic Shadow Memory component (from now on | ||
onwards, SSM) through four CBMC primitives, which allow one to declare shadow | ||
memory fields, and retrieve/set their corresponding values: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set/retrieve order consistency
|
||
More precisely, their signatures (in pseudo-C, because of some constraints that | ||
we can't express using the type system), along with some small examples of their | ||
usage, look like this: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
look like this: -> are described below.
Type constraints: | ||
|
||
* `type1`: string literal, such as `"field"`, | ||
* `SSM_value_type`: value of maximum 8 bits, signed or unsigned or `_Bool`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SSM_value_type: any value up to 8 bits in size (signed or unsigned)
analysis program and that shadows the standard memory of the program. In that | ||
memory structure, a user can create fields, for which he can later set and | ||
retrieve values. | ||
CBMC contains a component that implements *Symbolic Shadow Memory*. Symbolic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"contains a component that" -> ""
5e3d405
to
a4c9364
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me
memory structure, a user can create fields, for which he can later set and | ||
retrieve values. | ||
|
||
By doing so, one can organise his own tracking of metadata related to the code, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be gender neutral? Also the person who is the object of this sentence is expected to be a user of cbmc. Therefore - "By doing so, a user can organise their own tracking of metadata"...
## Usage | ||
|
||
A user can interact with the Symbolic Shadow Memory component (from now on | ||
onwards, SSM) through four CBMC primitives, which allow one to declare shadow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion "allow one" -> "support" and splitting into two sentences.
"A user can interact with the Symbolic Shadow Memory component (from now onwards, SSM) through four CBMC primitives. These support the declaration of shadow memory fields, and setting/retrieving their corresponding values:"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed to "allow" without "one".
Split in 2 sentences.
|
||
## Usage | ||
|
||
A user can interact with the Symbolic Shadow Memory component (from now on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ Duplication when read across line breaks - "on onwards"
|
||
Type constraints: | ||
|
||
* `type1`: string literal, such as `"field"`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worth emphasising that by string literal we mean that the field name must be compile time constant and may not be the result of runtime string manipulation. That is, if my understanding of what you are trying to say here is correct...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant is that it has to be a string literal such as "this is a string literal"
.
In the exprt
world it has to be a constant_stringt
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. My understanding is correct. I think it is worth making the documentation spell out the exact details of what is and is not allowed as an argument here.
|
||
Type constraints: | ||
|
||
* `type1`: string literal, such as `"field"`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See previous comment of clarifying string literal.
identifier for the field and using the pointer in `p` as the address for the location | ||
of the value to be changed, to the given value, supplied by the third argument | ||
`set_value`. This value needs to be of the same type as the type of the value the | ||
field was originally initialised with. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that the shadow memory operates on the byte level. Therefore even if you declare the field as being 16 bits, if you pass in a value of say 300, than value would be truncated to fit in 8 bits. Is my understanding correct/incorrect and does that need to be explained here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, when declaring shadow memory we should use the exact type, so < 8 bits.
The truncation happens only on set_field
and it is explained there.
* `type1`: string literal, such as `"field"`, | ||
* `SSM_value_type`: value of maximum 8 bits, signed or unsigned or `_Bool`. | ||
|
||
Declares a local (working for variable declared in the current function scope) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a user wants to use shadow memory for a value which goes through a function return, should the shadow memory be declared as local or global? It could be local based on it being on the stack or global based on it exceeding the lifetime of the function, so as a user I would be unsure which to declare it as.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is based on the scope, so when you leave it everything is lost.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So does that mean the shadow memory would have to be declared as global in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, that is unfortunately a shortcoming of the actual implementation.
Global is for global variables and heap-allocated pointers.
Local is for the local function scope.
There may be in the future a way to propagate local shadow memory information to called functions and through return, but it is not implemented yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add the limitation to the documentation then? Do similar limitations apply to function arguments? Do they only apply to stack memory or can the limitations be dodged by heap allocating and passing pointers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is possible to heap-allocate arguments and return types so they will be tracked on the global SM.
About the documentation I'm not too keen at adding a "limitation" section as it draws attention to the limitation itself.
As the documentation says already local is for local only and is not passed to sub-call, I added that the same applies to returns, so the only way around is having the passed-around values on the global SM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree on the subject of documenting limitations. If we document them, then it allows users to work around them and allows us to point to the documentation if anyone runs across them. It also adds strength to the argument that removing such limitations is a feature request, rather than a bug fix. However I am happy to leave this to your discretion.
If using global shadow memory enables support for function arguments and returns then doesn't that answer my original question of whether local or global declarations are needed for that use case?
|
||
### Working with Compound Type Objects | ||
|
||
When using SSM on compound type pointers (e.g. `struct`) the value used for the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this description of shadow memory as it applies to struct types also apply to unions and arrays?
* `__CPROVER_field_decl_local` | ||
* `__CPROVER_field_decl_global` | ||
* `__CPROVER_get_field` | ||
* `__CPROVER_set_field` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth noting that these are only currently supported for the C front end? I am kind of assuming that these are unavailable for the JBMC at the moment.
cced7fd
to
36ba7df
Compare
36ba7df
to
e68aa9d
Compare
This PR adds documentation for the 4 CBMC intrinsics that allow a user to interact with the Symbolic Shadow Memory component to the CProver manual.
I would appreciate reviewers to have a closer look at the following two items: