Skip to content

[TG-9294][UFC] Fix context-include/exclude jbmc options #5115

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 13 commits into from
Sep 20, 2019

Conversation

antlechner
Copy link
Contributor

The specification I was given by @peterschrammel about how --context-include/exclude should work is the following:

  • --context-include and --context-exclude both take a prefix of a Java package, class or method as an argument
  • Both can be specified several times on the same command line.
  • All methods matching a prefix in --context-include and not matching a prefix in --context-exclude are "included", all other methods are "excluded".
  • Included methods are treated just like regular (non-opaque) methods when --context-include/exclude aren't used. Equivalently, --context-include can be seen as including everything by default (i.e. if not specified on the command line), and --context-exclude can be seen as including nothing by default.
  • Excluded methods should have all their meta-information filled in when converting the bytecode, but their body (symbol value) should not be loaded and instead be replaced with a "return nondet null or instance of return type" body, just as we do for stubbed methods. Thus excluded methods are between opaque methods and "regular" methods.

The last specification was not implemented properly. We left out some meta-information (e.g. parameter identifiers) and left the body as nil rather than assigning a stub-like body. This PR fixes both parts of this specification.

  • Each commit message has a non-empty body, explaining why the change was made. (Except for documentation commit.)
  • Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • 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. (Two small closely related fixes.)
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

@antlechner antlechner changed the title [TG-9294] Fix context-include/exclude jbmc options [TG-9294][UFC] Fix context-include/exclude jbmc options Sep 18, 2019
Copy link
Contributor

@romainbrenguier romainbrenguier left a comment

Choose a reason for hiding this comment

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

Reviewed up to Remove "WARNING: no body for function" regexes

void operator()(
const symbolt &class_symbol,
const methodt &method,
const optionalt<prefix_filtert> method_context)
Copy link
Contributor

Choose a reason for hiding this comment

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

const &

INVARIANT(
symbol,
"Tried to generate a stub body for function that is not in the symbol "
"table: " +
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ the invariant message should rather be formulated to state what should normally be true.

Copy link
Contributor Author

@antlechner antlechner Sep 19, 2019

Choose a reason for hiding this comment

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

The commit that this was in has been removed as it wasn't compatible with symex-driven lazy loading. 🚗

typedef std::function<bool(
const irep_idt &function_name,
symbol_table_baset &symbol_table,
goto_functiont &function)>
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ using is preferred

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🚗

@@ -7,6 +7,5 @@ Main.class
.* line 11 assertion at file Main.java line 11 .*: SUCCESS
.* line 12 assertion at file Main.java line 12 .*: SUCCESS
--
WARNING: no body for function .*
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ is this one removed because it is useless, or does the warning now appear?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because it's (probably) useless. There is a test in a later commit that checks that the body of an excluded method is a stub-style "return nondet" body. Do you think it still makes sense to check for WARNING: ... as a negative regex everywhere?

Copy link
Contributor

Choose a reason for hiding this comment

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

If there is no way this warning could be produced for any input then it can be removed, otherwise it's probably safer to keep it in just in case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm keeping it as a negative regex here now, and also added it as a negative regex in all existing tests and the new tests for exclude package and exclude absent.

@antlechner antlechner force-pushed the antonia/context-include branch 3 times, most recently from ce883b8 to e54b2cc Compare September 18, 2019 13:18
--context-exclude org.cprover.other --function ExcludedProperties.runtimeReturnType
^EXIT=10$
^SIGNAL=0$
.* line 30 assertion at file ExcludedProperties.java line 30.*: FAILURE
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ there is no assertion line 30, as far as I can see, I mean 28?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed, this was a result of a late clang-format run (30 was correct before clang-format) and should be fixed now.

@@ -179,20 +179,37 @@ symbol_tablet load_java_class(
java_class_name, class_path, main, std::move(java_lang), command_line);
}

/// See \ref load_goto_model_from_java_class
/// With the command line configured to disable lazy loading and string
/// refinement and the language set to be the default java_bytecode language
goto_modelt load_goto_model_from_java_class(
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ should be documented

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is documented in the header file.

const auto public_instance_type =
type_try_dynamic_cast<java_method_typet>(public_instance_symbol.type);
REQUIRE(public_instance_type);
REQUIRE(id2string(public_instance_type->get(ID_access)) == "public");
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ compare to ID_public, and use get_access 💎

THEN(
"Meta-information of excluded methods is preserved. Symbol values are "
"nil as the lazy_goto_modelt for unit tests does not generate "
"stub/exclude bodies.")
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ it would be nice to have several THEN sections to structure the test and make it easier to identify what goes wrong when something does.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now grouped into several THEN sections where each is about one property of excluded method symbols.

const auto private_static_type =
type_try_dynamic_cast<java_method_typet>(private_static_symbol.type);
REQUIRE(private_static_type);
REQUIRE(id2string(private_static_type->get(ID_access)) == "private");
Copy link
Contributor

Choose a reason for hiding this comment

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

💎

default_final_static_symbol.type);
REQUIRE(default_final_static_type);
REQUIRE(
id2string(default_final_static_type->get(ID_access)) == "default");
Copy link
Contributor

Choose a reason for hiding this comment

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

💎

"stub/exclude bodies.")
{
const auto &public_instance_symbol = symbol_table.lookup_ref(
"java::ClassWithDifferentModifiers.testPublicInstance:()I");
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ would be better to use lookup and REQUIRE the result to be non-null 🦈

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. The REQUIREs had to go into the WHEN part, is that ok?

REQUIRE_FALSE(public_instance_type->get_is_final());

const auto &private_static_symbol = symbol_table.lookup_ref(
"java::ClassWithDifferentModifiers.testPrivateStatic:()I");
Copy link
Contributor

Choose a reason for hiding this comment

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

🦈

REQUIRE_FALSE(private_static_type->get_is_final());

const auto &protected_final_instance_symbol = symbol_table.lookup_ref(
"java::ClassWithDifferentModifiers.testProtectedFinalInstance:()I");
Copy link
Contributor

Choose a reason for hiding this comment

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

🦈

REQUIRE(protected_final_instance_type->get_is_final());

const auto &default_final_static_symbol = symbol_table.lookup_ref(
"java::ClassWithDifferentModifiers.testDefaultFinalStatic:()I");
Copy link
Contributor

Choose a reason for hiding this comment

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

🦈

@antlechner
Copy link
Contributor Author

It turns out my second fix (for assigning stub-like bodies to excluded methods) is too general and incompatible with symex-driven lazy loading. I will add an "in progress" label, and remove it once I've finished fixing that commit.

@antlechner antlechner force-pushed the antonia/context-include branch 2 times, most recently from b155932 to 67d8f97 Compare September 19, 2019 11:54
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: cbf5320).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/128352945

@antlechner antlechner force-pushed the antonia/context-include branch from cbf5320 to c5f02e4 Compare September 19, 2019 14:34
The new name makes it clearer that this field defines a context, not a
method.
The previous check was right at the beginning of convert_single_method,
meaning that for an "excluded" method, we would have never entered
java_bytecode_convert_method, which assigns more than just the symbol
value (body of a method), e.g. parameter identifiers.
The only information that we want to omit for excluded methods is their
bodies / symbol values. This is why the new check is just before the
assignment of symbol values, making sure that parameter identifiers and
other meta-information of the method are correctly assigned for excluded
methods.
There are three types of method symbols that we expect here:
1) symbols for regular methods, i.e. the bytecode of the method is
available and the method is in the supplied context
2) symbols for opaque methods, i.e. the bytecode of the method is not
available
3) symbols for excluded methods, i.e. the bytecode of the method is
available but the method is not in the supplied context
The previous check was correct for 1) and 2): we do not want to create
stub bodies ("return nondet") for regular methods but we do want to
create them for opaque methods.
The new check makes sure that stub bodies are also created for excluded
methods (3). Previously the value of those symbols was just left as nil,
meaning the (type of the) return value of the method was not constrained
in any way.
The previous version would have not called convert_single_method on
excluded methods, meaning they would have missed some meta-information,
e.g. parameter identifiers.
If we are not using CI lazy methods here (as could happen after the
change from the previous commit that makes sure convert_single_method is
run for all methods), needed_lazy_methods is an empty optional and we
cannot access it.
These lines appear in the output for methods whose body is empty/nil.
For excluded methods, we now have "return nondet" bodies as we do for
stubs, so the warnings are no longer printed.
The tests in this commit would have all passed without the previous
fixes already and are just added for completeness.
The tested prefixes are a prefix of a package and a prefix that does not
match anything on the classpath.
The tests from the previous commit show that the right methods are
excluded.
The tests from this commit show that an excluded method has the right
properties: meta-information such as parameter types and identifiers
should be preserved, while the real method should not be loaded and a
stub-like "return nondet" body should be used instead.
The tests from this commit would not have passed without the fixes from
this PR.
This is consistent with the location of the definition in the cpp file.
The new overload allows specifying the command-line options to run jbmc
with. For example, we will be able to specify that --context-include
should be used.
These unit tests complement the regression tests in
jbmc/regression/jbmc/context-include-exclude
that were added in a previous commit to check for properties of excluded
methods. Some properties, like information about accessibility and final
and static status, is easier to check in unit-style tests.
@antlechner
Copy link
Contributor Author

@romainbrenguier I addressed your comments. I also fixed the issue with symex-driven lazy loading. A previous commit has been replaced with three new commits for the fix:

Amend condition for when stub method body should be made
Remove unused variable assignment
Move convert call above body_provided check

Could you please review these new commits?

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: ceb297d).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/128380227

@codecov-io
Copy link

Codecov Report

Merging #5115 into develop will increase coverage by 2.79%.
The diff coverage is 100%.

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #5115      +/-   ##
===========================================
+ Coverage    66.94%   69.73%   +2.79%     
===========================================
  Files         1145     1323     +178     
  Lines        93627   109474   +15847     
===========================================
+ Hits         62674    76339   +13665     
- Misses       30953    33135    +2182
Flag Coverage Δ
#cproversmt2 ?
#regression ?
#unit ?
Impacted Files Coverage Δ
jbmc/src/java_bytecode/java_bytecode_language.h 76.92% <ø> (ø) ⬆️
jbmc/src/jbmc/jbmc_parse_options.h 100% <ø> (ø) ⬆️
...java_bytecode/java_bytecode_convert_method_class.h 100% <100%> (ø) ⬆️
jbmc/src/jbmc/jbmc_parse_options.cpp 71.56% <100%> (+0.21%) ⬆️
...tecode/java_bytecode_language/context_excluded.cpp 100% <100%> (ø)
...src/java_bytecode/java_bytecode_convert_method.cpp 97.54% <100%> (ø) ⬆️
jbmc/unit/java-testing-utils/load_java_class.cpp 100% <100%> (ø)
jbmc/src/java_bytecode/java_bytecode_language.cpp 93.06% <100%> (-0.02%) ⬇️
...ecode_parse_generics/parse_generic_array_class.cpp 100% <0%> (ø)
...t_builtin_function/length_for_format_specifier.cpp 100% <0%> (ø)
... and 177 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 da454ce...ceb297d. Read the comment docs.

@@ -605,8 +606,12 @@ void java_bytecode_convert_methodt::convert(
if((!m.is_abstract) && (!m.is_native))
{
code_blockt code(convert_parameter_annotations(m, method_type));
Copy link
Member

Choose a reason for hiding this comment

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

Why is this line outside the if?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, it should be inside. Antonia is away for three days, so I've made a follow-up PR to make this change: #5121

@@ -690,6 +690,8 @@ int jbmc_parse_optionst::get_goto_program(
std::unique_ptr<abstract_goto_modelt> &goto_model_ptr,
const optionst &options)
{
if(options.is_set("context-include") || options.is_set("context-exclude"))
Copy link
Member

Choose a reason for hiding this comment

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

It's ugly to repeat that here, but probably can't be fixed without cleaning up the language interface.

Copy link
Contributor

@romainbrenguier romainbrenguier left a comment

Choose a reason for hiding this comment

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

@antlechner

Could you please review these new commits?

Still looks fine

@owen-mc-diffblue owen-mc-diffblue merged commit 9c0e0d3 into diffblue:develop Sep 20, 2019
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.

6 participants