Skip to content

Initialise union of static lifetime with zeros #5705

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

Merged
merged 9 commits into from
Jan 23, 2021

Conversation

tautschnig
Copy link
Collaborator

The C standard does not specify the value of bytes that do not belong to
the object representation of a member referred to in an initializer
list, but compilers seem to ensure those bytes are zero (possibly by
using the .bss section).

  • Each commit message has a non-empty body, explaining why the change was made.
  • n/a Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • n/a The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • n/a My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

@codecov
Copy link

codecov bot commented Dec 29, 2020

Codecov Report

Merging #5705 (ac31213) into develop (60feede) will decrease coverage by 0.01%.
The diff coverage is 56.45%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #5705      +/-   ##
===========================================
- Coverage    69.66%   69.64%   -0.02%     
===========================================
  Files         1248     1248              
  Lines       100873   100922      +49     
===========================================
+ Hits         70278    70292      +14     
- Misses       30595    30630      +35     
Flag Coverage Δ
cproversmt2 43.36% <67.44%> (-0.02%) ⬇️
regression 66.62% <56.45%> (-0.03%) ⬇️
unit 32.18% <13.95%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/goto-instrument/dump_c.cpp 77.03% <5.26%> (-1.40%) ⬇️
src/ansi-c/expr2c.cpp 69.20% <30.76%> (-0.30%) ⬇️
src/ansi-c/c_typecheck_initializer.cpp 76.40% <100.00%> (+0.25%) ⬆️
src/ansi-c/parser.y 78.32% <100.00%> (-0.04%) ⬇️
src/solvers/flattening/bv_pointers.cpp 82.40% <100.00%> (ø)
src/util/simplify_expr.cpp 85.97% <100.00%> (-0.61%) ⬇️
src/util/simplify_utils.cpp 98.62% <100.00%> (+0.06%) ⬆️
src/solvers/flattening/boolbv_union.cpp 52.63% <0.00%> (-31.58%) ⬇️
src/util/endianness_map.cpp 77.35% <0.00%> (-1.89%) ⬇️
src/nonstd/optional.hpp 94.93% <0.00%> (-1.27%) ⬇️
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 60feede...ac31213. Read the comment docs.

@kroening
Copy link
Member

It would make sense to have a warning in the manual about this one as well.

@tautschnig
Copy link
Collaborator Author

Marking do-not-merge as this requires fixes in dump-c (or some approach not involving byte_update).

@kroening
Copy link
Member

Looking at this, I am wondering whether or not we might want to have a 'strict mode', which would not make compiler or architecture-specific assumptions.

@tautschnig
Copy link
Collaborator Author

Looking at this, I am wondering whether or not we might want to have a 'strict mode', which would not make compiler or architecture-specific assumptions.

Well, at least we should make sure we can configure all those architecture/compiler-specific assumptions. We have quite a lot of this in configt already, but handling of unions is not among that yet. I'll work on adding that union-configuration part, but I'd be happy to hear about more aspects that come to mind.

Even in upcoming changes there must not be a situation where such
initializers cannot be dumped in a compilable fashion.
The regression test demonstrated that decoding non-null pointer-typed
constants were not correctly decoded to their integer representation.
The parser unnecessarily introduced an ID_designated_initializer into
offsetof when no id was required, thereby creating an expression with
ID_designated_initializer that had a different shape from all other uses
of ID_designated_initializer. With this cleaned up, enable expr2c to
print designated-initializer expressions.
C does not have byte_update expressions.
The C standard does not specify the value of bytes that do not belong to
the object representation of a member referred to in an initializer
list, but compilers seem to ensure those bytes are zero (possibly by
using the .bss section).
Mirror what we already did for byte extract operations.
A union_exprt can refer to components of a type that is smaller than the
full bit width of the union. Consequently, bits2expr should accept bit
strings for such (smaller) members.
The order of constructor arguments was wrong, resulting in 48 copies
(the ASCII index of '0') instead of bit-width copies, being used.
We introduce byte updates to soundly prepare union initializers, but
such byte updates are not part of the C standard and thus aren't
expected by dump-c. Run simplify to clean them up, when possible.
@tautschnig
Copy link
Collaborator Author

Trying to make sure we can successfully dump union expressions after fixing zero initialisation via byte updates became quite the bug squashing party. I started out by creating a test for dump-c, which I then noticed CBMC would not produce the correct verification result for. Here is the history as it may help to understand the flood of commits:

  1. Added a test that dump-c ought to reproduce correctly (42b4740).
  2. Figured out that we could also check for "VERIFICATION SUCCESSFUL" as part of this test, but that required a bitvector flattening bugfix (completely unrelated to to dump-c, the original source would not yield the correct verification result) (7e02b53).
  3. Wanted to finally add support to dump-c (eventually done in db4f25c), but that required working ID_designated_initializer output. Thus fixed that first (a835405).
  4. Now it is possible to use byte_update in initialising unions without breaking dump-c's output thereof (a8592a7).
  5. Wanted to use simplify_expr to resolve this byte_update in common cases. This required extending the simplifier (9a51a92) and fixing bugs in bits2expr/expr2bits (e8ac4d6, ed75598).
  6. Finally the simplifier can be used successfully for the desired byte_update removal (ac31213).

@@ -410,7 +417,7 @@ expr2bits(const exprt &expr, bool little_endian, const namespacet &ns)
else if(type.id() == ID_pointer)
{
if(value == ID_NULL && config.ansi_c.NULL_is_zero)
return std::string('0', to_bitvector_type(type).get_width());
return std::string(to_bitvector_type(type).get_width(), '0');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

@tautschnig tautschnig merged commit 0f20b3c into diffblue:develop Jan 23, 2021
@tautschnig tautschnig deleted the union-zero branch January 23, 2021 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants