-
Notifications
You must be signed in to change notification settings - Fork 274
Optimisations in generated code with function pointers #434
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
Optimisations in generated code with function pointers #434
Conversation
Some tests that should be added:
|
{ | ||
const exprt &func_expr=array_expr.operands()[integer2size_t(value)]; | ||
exprt precise_match; | ||
if(try_get_precise_call(func_expr, precise_match)) |
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.
These no-body if statements aren't very clean. I shall have a think about a better way to structure this 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.
Perhaps something like:
bool matched=false;
matched=matched||try_get_precise_call(...)
matched=matched||try_get_from_address_of(...)
else | ||
{ | ||
// return false? | ||
// in this case there is an element |
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.
This happens if we can't convert one of the operands in the array - I suppose this could happen if most of the values are constant but one is not. In this case I suppose we have to fall back to the worst cast - should add a test for this.
{ | ||
out_array_index=array_index; | ||
} | ||
return !errors; |
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 to_integer
part of the code base, the general rule seems to be return false (i.e. 0 I guess) for errors, but this seems backward to me in general. Should I invert my functions to return false if everything went well?
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 overall the Boolean return value signals whether an error occurred, i.e., it's "true" whenever something bad happened. Whether this is good or bad is a different question.
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.
Confusingly, I managed to my comment exactly 50% wrong, it should have read:
return false (i.e. 0 I guess) for no errors, but this seems backward to me in general. Should I invert my functions to return false if everything went well.
To which I think your answer means return true for errors, else return true/false if the function clearly implies a truthy value.
I couldn't find a lot of try_
methods, but path_searcht::try_await
for example returns true for no errors, so I suppose try
suggests a truthy value of true meaning we tried and succeeded. So I will leave as it is.
|
||
return try_evaluate_index_value(index_symbol.value, out_array_index); | ||
} | ||
else if(index_value_expr.id()==ID_typecast) |
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 don't really know what ID_typecast is doing here, but it shows up when accessing the array by index - it is straightforward to resolve but feels a bit hard coded...
} | ||
else if(array_expr.id()==ID_symbol) | ||
{ | ||
// Is there some existing code to follow symbols to the real value? |
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.
@tautschnig This feels like something you might know?
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.
Perhaps simplify_expr
would be useful 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.
I may have answered this question in the other comments: in order to follow a symbol to its value, you'd need all the definitions, and thus a def-use 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.
Sorry I'm not sure I fully understand - am I not already following the symbols to their values? I'm currently (recursively) when I find a ID_symbol
, look at its ID_identifier
, look that up in the symbol_table
and look at the symbols value
.
I was hoping this logic for recursively resolving the symbols (and ideally dealing with other things like casting) would exist in the simplify_expr
but it doesn't seem to be working as I had hoped.
This falls apart as soon as the array is modified as it incorrectly assumes it is not. For example this code:
produces
i.e. would produce To resolve this we need to either detect the array being modified or only apply this optimisation on arrays that are declared constant at compile time. I imagine the second is easier (maybe just calling |
I'm not sure whether supporting non-const arrays is required. As far as I know there does not exist code yet to simply check whether an array is ever written to. I think looping through all assignments in the code and gathering all left-hand side symbols and afterwards checking if the array symbol is contained in there would be fine. Additionally we would need to check that the address of the array is never taken as otherwise it could be modified through a pointer. This can be done via |
@peterschrammel Do we have any code (possibly in 2LS?) that turns a goto program into SSA form? No loop unwinding or precise phi nodes. Otherwise we could resort to the existing def-use analysis to identify whether any arrays have been written to. |
|
||
bool try_get_array_from_index( | ||
const index_exprt &index_expr, array_exprt &out_array_expr); | ||
|
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.
Nit picking: newlines after each ","
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 think this changed as I thought it would require that but @peterschrammel has told me that if it fits on one line, then that's OK, see this:
put each argument on a separate line if they do not fit after one line break
https://github.com/diffblue/cbmc/blob/master/CODING_STANDARD#L12
{ | ||
if(expr.id()==ID_symbol && expr.type().id()==ID_code) | ||
{ | ||
out_function=to_symbol_expr(expr); |
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.
Missing return value?
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.
Fixed.
{ | ||
if(expr.id()==ID_address_of) | ||
{ | ||
address_of_exprt address_of_expr=to_address_of_expr(expr); |
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.
const address_of_exprt &
...
I had thought about the precision problems we have function pointer handling some time ago, and it wasn't entirely clear to me why we would not want to run a full data-flow analysis (via Thoughts? |
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 discussion on what I think needs to be done here.
@tautschnig, the def-use analysis for 2ls is https://github.com/diffblue/2ls/blob/master/src/ssa/ssa_domain.h |
@tautschnig Do you mean first running the existing The issue we're having is that The most precise way would probably be to integrate a function pointer analysis with the |
@thk123 Should also add some tests for the case when the array is represented as a pointer. I'm not sure exactly how goto handles this. |
46258a0
to
b578ebd
Compare
I've added checking the const-ness of the array which seems to work. I'll quickly address the other feedback requests. @danpoe I think for this simple version we don't need to check pointer reassignment as assigning a const array to a non-const pointer and then modifying that pointer is UB I think? And as such, I think @martin-cs said if there is UB we don't care. I don't know if I should be looking in to the more complex solutions suggested above, for the specific case we are trying to fix, providing they can mark the function pointer arrays as TODO:
|
{ | ||
return true; | ||
} | ||
else |
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.
The following lines could be replaced by a return false
on the last line of the function, do people think it is clearer like this or collapsed down.
Clearer like it is - can see all the ways the method can fail explicitly
Clearer other way - hard to keep track of which if the else corresponds to.
For a full solution it might indeed be necessary to have an analysis that runs a fixed point over both def-use (whether implemented via SSA or otherwise), and pointers (including function pointers). This may be way more elaborate than what's intended here, in which case the simple approach for const symbols/arrays would do. |
bd3c45f
to
8b11588
Compare
Add check for function pointer inside a struct. Sanity check the variable works iff const. Travis compile errors related to #467 Add a test to check that the UB of loosing const is in fact picked up by goto-cc and also check C standard to check it is in fact UB. |
Noting on here as well that #467 is fixed. Rebase to re-run the tests? |
8b11588
to
74aa2e4
Compare
Definitely UB to assign const to non-const, 6.7.3.6:
|
Like with const arrays, we need to apply the same const check to values, otherwise for example this code behaves incorrectly:
|
@tautschnig This looks to still be failing with these errors having rebased, are these still related to you or is something else going on? https://travis-ci.org/diffblue/cbmc/jobs/194806576#L2013
|
9214883
to
56c39e4
Compare
The only thing missing from this PR (I believe) is the implementation for handling structs containing function pointers and pointers to function pointers. I've added KNOWNBUG regressions demonstrating this limitation, I'll either implement it and replace the "temp checkin" with the implementation or I will replace the "temp implementation" with just the failing tests and create corresponding issues. |
Could we at least have a fall-back for all cases that the new code can't handle? I don't think we should end up in a situation where we gain precision on the one hand, but also fail in cases we previously wouldn't. |
This looks awesome but is it under the wrong issue?
Cheers,
- Martin
|
Could we at least have a fall-back for all cases that the new code can't handle?
Yes; we should definitely have 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.
Apologies for putting a surprising hard stop on this one: I just learned there is src/musketeer/propagate_const_function_pointers.cpp - could you please see to what extent we have overlap and/or can get rid of it?
As far as I remember the purpose of
|
Bit of a brain dump, feel free to ignore, just assesing what the propogate_const_function_pointers does and how it coule be combined with my changes in this PR. TL;DR:
So even if the parameter to The code in musketeer appears to start at the entry point and track each call site for each function and tracks the function pointers. It then replaces them when it can in the actual function call. I'm not sure, but I don't think this is a comprehensive super-set of my changes since I don't think it would deal with arrays of FPs. It also seems to me (though this could be completely wrong) that this won't scale to large applications as it basically walks through a complete CFG tracking all ways a function can be called? To combine them you would want to run this one first and this will introduce constant FPs that the second step can resolve. You could also extend this to apply the same logic to arrays of FPs in cases where they were passed in to a function. |
I think some of the failing tests have some incorrect code (discovered whilst looking at some logging for missed edge cases). This shouldn't be merged until I've pushed some improvements to these tests to make their failure more precise. |
Martin has also found some bugs and limitations with this which I will be addressing this week, so can probably hold off merging until those are complete and have been reviewed. |
May I suggest the following:
1. The function pointer removal code in:
goto-function/remove_function_pointers.cpp
should remain 'stateless', so that it only uses the expression and
definitions / types of any symbols used in it.
2. We should get the abstract interpreter to tolerate and eventually
track function pointers. This will allow stateful analysis. We need
this for other reasons.
3. Then --simplify --context-dependent --constant
--function-pointer-sensitivity=set (or whatever) should be able to
perform the simplification that is used in Musketeer.
|
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.
Apologies for the on/off on this one. As first step we should have the additional tests added to see more clearly where the problems are. I feel that we are somewhat back to my first comments on this PR, saying that it would actually need a full data-flow analysis.
@tautschnig Sorry if I've not understood, but isn't what Martin is saying is the remove-function-pointers will be a very simple first pass that remains stateless (i.e. without a data flow analysis). I am going to quickly get a messy branch sorted for Martin so he can verify it fixes all the problems and then I shall clean it up for this PR (it will have more tests covering different cases that it does and doesn't handle). A TODO list for my reference:
This should be done by Thursday. Then I will fix up this PR with these changes and clearer testing. |
Yes to all of the above. Give me / @tautschnig a shout if you want
back-up / to discuss the best way of handling some of these.
|
I think the key problem is that we need to figure out which ones can genuinely be handled in a stateless fashion: that's those where a const symbol holds all the possible values, and that symbol is genuinely never written to after initialisation. I think the existing code will be ok for the first part of that sentence (with some extensions as noted in your task list), but I think we are missing a check that the symbol (despite being declared const) is really never written to. I think I can put up a pull request for a helper analysis that will take care of that latter part. |
On Wed, 2017-02-01 at 06:43 -0800, Michael Tautschnig wrote:
I think we are missing a check that the symbol (despite being declared const) is really never written to.
This is part of a larger issue in abstract interpretation - you have to
assume that undefined behaviour doesn't occur / things are type safe
unless explictly noted otherwise because otherwise the first write to an
array in which you can't bound the parameters of the index will set
everything to top.
The exact rules / assumptions are not entirely clear to me but I think
they are worth working out and documenting as this does not seem to be
an issue that is widely discussed in the academic literature but has
huge inpact on things like the use of AI for security work. For
example, exploit location with AI is much harder than you'd think.
I think I can put up a pull request for a helper analysis that will take care of that latter part.
That would be awesome.
Cheers,
- Martin
|
As first step we'd want the basic check that 1) there is no write to a symbol deemed const and 2) that it's address is never taken. Surely undefined behaviour causes additional trouble, but then at least we've got a first "check" step in place that can possibly be extended. |
Ok, I was a bit confused - really what I was thinking of was @danpoe's work in 2df6785 that locates unused symbols. The other related work is #449. Both of which lay the grounds (in slightly different ways) for locating unused objects. #449 is probably closer in that it already uses read/write sets. |
Progress update on this: I have a reasonable version that deals with most cases correctly (not far advanced from what I sent you at the close of play on Thursday @martin-cs). This afternoon I fixed the structs containing const FP members but themselves are mutable. I have also started an audit on the very large number of regression tests to check I've covered all cases, there aren't any duplicates and to give them better names for a proper PR. In doing so, I have found a bug with pointers to function pointers, specifically, we don't require them to be const but should. I will complete this audit tomorrow and share it on here in case there are other cases I've not covered. Then I will fix the bug(s). Once that is done, the only missing feature should be array indices who are constant but a non-trivial expression (i.e.
Will confirm after discussion with @martin-cs tomorrow when this will get done. |
Finished the audit of the tests, can see a full list here: https://docs.google.com/spreadsheets/d/115b60q89eMAVAQAUPfyYLTwGEE80Pw5UX-nUjYdhH0E/edit?usp=sharing In doing this I found some problems and some missing cases which I will address next:
I also ran a line coverage on the relevant class. Most of the lines are hit. Most of the ones that are not hit are |
Based on @martin-cs failures, the cases left to do
|
It has also occurred to me that we don't deal with unions, this shouldn't be hard to add, though unlike structs we would require either every component to be const, or the union as a whole to be const. |
@martin-cs Update: found a big bug, I must have misunderstood what you meant by mutable structs with const function pointers, the following code can't be optimised since we can write over the whole struct. #include <stdio.h>
void f1 (void) { printf("%i", 1); }
void f2 (void) { printf("%i", 2); }
void f3 (void) { printf("%i", 3); }
void f4 (void) { printf("%i", 4); }
void f5 (void) { printf("%i", 5); }
void f6 (void) { printf("%i", 6); }
void f7 (void) { printf("%i", 7); }
void f8 (void) { printf("%i", 8); }
void f9 (void) { printf("%i", 9); }
typedef void(*void_fp)(void);
struct state
{
int x; // Mutable!
const void_fp go;
};
struct state thing = {0, &f2};
struct state other_thing = {0, &f4};
// There is a basic check that excludes all functions that aren't used anywhere
// This ensures that check can't work in this example
const void_fp fp_all[] = {f1, f2 ,f3, f4, f5 ,f6, f7, f8, f9};
void func(int i){
// overwrite the whole of thing including the FP!
thing = other_thing;
const void_fp fp = thing.go;
fp();
}
void main(){
for(int i=0;i<3;i++){
func(i);
}
} As such I've modified it to require the whole variable is const (and we don't care about the const-ness of individual components). Therefore I'm not sure if it is going to work with your mutable struct, but if it doesn't it shouldn't, as the structs value can be legally changed... See this commit for full details: thk123@c88c1af |
Tomorrow will move this into a clean branch to make a PR and close this one out. The only thing to investigate is the logging and behaviour of regression 11 looks a little odd (note for myself). |
As promised - clean version of this PR #519 so closing this now. I don't think there is anything outstanding from this PR thread that needs action in the new one. |
1e8b77c Merge pull request diffblue#514 from diffblue/romain/use-cprover-string b2b45ce Merge pull request diffblue#526 from diffblue/smowton/feature/special-methods-must-not-throw aeb92d7 Merge pull request diffblue#497 from diffblue/romain/string-join fc05549 Merge pull request diffblue#527 from diffblue/antonia/gauge-log-changes 65a0ecc Update categorise-specs for new Gauge version 1b31565 Mark special methods must-not-throw 9a18371 Refactor Integer.decode to use fewer strings f85fc32 Refactor Long.decode to use fewer string operations e339fbc Replace charAt with CProverString.charAt 0a09179 Replace substring with CProverString.substring bd2a579 Adapt String.join tests to disallow null arrays 331db5c Add String.join tests to spec file 599caec Adapt String.join tests 75ef335 Adding generated tests for String.join 03710d2 Empty model of interface java.lang.Iterable 3e0d412 Import Iterable interface from JDK d57e32e Model for StringBuilder(CharSequence) and append 3c9badf Model for String.join 19b284b Merge pull request diffblue#522 from diffblue/bugfix/model_test_gen 4a1955d Merge pull request diffblue#523 from diffblue/antonia/documentation 2fe8321 Merge pull request diffblue#524 from diffblue/antonia/categorise-on-mac e6f5781 Update documentation for Gauge plugins 511a19a Move all scripts documentation to new readme file e761c5b Rename setup.sh 44f7fcf Change path to download original JDK to 7202ddf Move .sh scripts into scripts folder 65b5de6 Merge pull request diffblue#520 from diffblue/allredj/update-emptier-to-fornotmodelled ff96cd7 Merge pull request diffblue#506 from diffblue/allredj/initialize-class-literals 8ecadaa Merge pull request diffblue#517 from diffblue/smowton/feature/mustnotthrow b9574a6 Emptier: add notModelled statements 6e5ac35 Remove useless error message 5554acd Address Mac TODOs in categorise-specs 0bca40e Merge pull request diffblue#518 from diffblue/antonia/generate-path-fix f72c373 Updates to the Emptier 55f3008 Adapt regexp and unit test for new test name c1bde8b Merge pull request diffblue#494 from diffblue/allredj/testrunner-add-option-step 56a40a6 Add MustNotThrow annotation 54cf9e2 Add documentation for new steps 87efcfd Activate test that requires --java-throw-runtime-exceptions 7217389 TestRunner: Add possibility to add a test-gen option b9a0ccf Force name to be non-null a483732 Fix path length bug in generate script 4b0c394 Add cproverInitializeClassLiteral to Class.java 0dc5dfe Merge pull request diffblue#513 from diffblue/bugfix/file-constructor 83435cf Replacing charAt/substring calls with CProverString d85ea5d Activate some long test for File constructor 17bfa18 Check we do not introduce "//" in filename b75615b Remove constraint on not containing "//" b6f2a36 Merge pull request diffblue#512 from diffblue/antonia/tg-3430-enable-tests 53d4685 Enable tests for TG-3430 5faeaf5 Merge pull request diffblue#511 from diffblue/antonia/disable-Object-test 658d9e5 Disable Object test for TG-3430 b62f0ef Merge pull request diffblue#510 from diffblue/bugfix/add_gpg_keys d7b126f Merge pull request diffblue#460 from diffblue/bugfix/nondet-for-not-modelled#TG-3175 f4e2d30 Use TRAVIS_BUILD_DIR to get path to keys 4c10d07 Remove reference to TG-3175 ecb6b99 Update README with info for nondet functions 737e0a4 Make nondetWithoutNull private a91312b Make nondetWithNull private d7423c6 notModelled for function with noSupport e3b673d nondetForNotModelledWithoutNull for CASE_INSENSITIVE_ORDER 938062b Use CProver.nondetForNotModelled(WithoutNull) 176ccad Use nondetWith(out)Null with an argument c1c1253 Introduce nondetForNotModelled functions 968a391 CProver function for initializing System streams d5dc7e3 Public version of nondetWithoutNull with argument 64e2685 New implementation of nondetWithNull with argument 2bb55d4 Make nondetWithoutNull assume non-null object b62c97b Document a problem with FileInputStream ac71051 Mark mocked void method not supported ce85efe Label method returning nonmodelled with noSupport 69f31e2 Merge pull request diffblue#509 from diffblue/antonia/annotate-Set 0ae3df3 Merge pull request diffblue#508 from diffblue/antonia/delete-temp-spec 6e65e90 Merge pull request diffblue#507 from diffblue/antonia/equals-ordering 9f7b53b Add regression test for TG-3546 051efe4 Annotate Set with preferred implementation 3dc3cdb Add GPG keys to improve Travis build stability 5aea66b Merge pull request diffblue#495 from diffblue/romain/pattern-compile 88d2f4b Merge pull request diffblue#505 from diffblue/allredj/remove-some-L0-tests 9ed9c83 Remove temp scenario in StringBuffer.spec a2083a6 Fix ordering of equals in simple HashSet.contains e31d258 Merge pull request diffblue#503 from diffblue/forejtv/X509EncodedKeySpec b9724d2 Adding 'untested' to (X509)EncodedKeySpec since we don't have level 1 tests c27237b added 'untested' tag 487e840 Marked support in models d91ae56 added model and tests for java.security.spec.X509EncodedKeySpec b988315 Merge pull request diffblue#465 from diffblue/jeannie/subsequencetest 4c368dc Merge pull request diffblue#483 from diffblue/jeannie/FileReaderDocsUpdate 6687faf Documents issue with mocking in InputStreamReader. 207298f Merge pull request diffblue#463 from diffblue/jeannie/Writers f4b7a89 Remove java.io.StringWriter from mocking in TestRunner.java b84a6d4 Tests java.io.StringWriter 62d732a Models java.io.StringWriter 7cee7d2 Models StringBuffer.append() with char[] and CharSequence 76af460 Merge pull request diffblue#499 from diffblue/antonia/simple-HashMap-tests 4c5ed85 Merge pull request diffblue#498 from diffblue/allredj/testrunner-cleanup-export-imports 6622177 Update documentation for simple HashMap fc793dd Update documentation for simple HashSet 5adfc6b Tag failing tests with appropriate ticket numbers 10f0cd3 Run categorise script on HashMap_simple.spec 07f9c04 Model replace(key, value) for simple HashMap ce91f40 Modify HashMap tests for simple model 0c80ce9 Remove all legacy tests for simple HashMap dab5fca Copy spec file and test folder for simple HashMap 31f981d Replace legacy test with similar level 1 test 5fcb621 Rewrite test so it doesn't need "lines" feature c816749 Add missing tests for HashMap 7ea5a49 Delete old class files 8a352de Delete unnecessary Level 2 tests 97173b8 Fix typos and formatting in HashMap.spec c5016af Remove L0 Properties tests 6d9363e Remove L0 HashMap tests 2542b0d Remove L0 HashSet tests ad866ca Remove L0 ArrayList tests e092a29 Run all tests with --export-imports option e30433e Merge pull request diffblue#496 from diffblue/allredj/activate-long-tests 65bb1f4 Merge pull request diffblue#492 from diffblue/romain/model-test-generation-v2 f9745ca Merge pull request diffblue#502 from diffblue/allredj/update-diffblue-test-utils bae50ba Add reference ticket for new bugs d0c9c9b Run long tests on models-library Travis d7b12cb Move some tests from long to knownbug ee38154 Add generated spec file and move old one aa169a3 Adapt Pattern tests to ensure they compile 2b26f3d Add test for Pattern.compile, .toString and .pattern 01fe53f Model for Pattern.compile .pattern and .toString b439573 Empty model for Pattern 875dc9f Import Pattern.java from JDK 667c4ca Merge pull request diffblue#488 from diffblue/justin/EnableTests_TG2717 3b90354 [TG-2717] [TG-3138] Enable regression tests d6b4563 Update diffbluetestutils to 1.2.0 f1409e0 Remove test that does not have a test file 15610f6 Merge pull request diffblue#501 from diffblue/allredj/reduce-signurl-duration c9e053b Merge pull request diffblue#500 from diffblue/antonia/categorise-script-lines f067bac Add (human written) unit tests for TestFactory f4a4cb2 Add deeptest utils to maven pom file 84a6dce Add unit tests generated by DeepTest 1347c88 Correct indentation in TestFactory a112b88 Correct pattern in TestInfo 9dcc952 Make Test.Argument class static e69380f Add an option to disable post-processing 3568640 Output list of untested methods 4904607 Special case of boolean retval in if 9acd301 Make filtered return deal with primitive types 90821cb Adapt script for new version of ModelTestGenerator b534526 Make ModelTestGenerator write formated java files c4ff80c Move TestFactory classes to TestFactory.java dac2e50 Make ModelTestGenerator take a function name 60224b2 Make ModelTestGenerator take test-generator output 22706c2 Java class running test-generator with default option 5cffd44 Reduce signed url duration to 7d aa9bd91 Add java script to list functions in a class 89858aa Merge pull request diffblue#491 from diffblue/allredj/export-imports a852716 Add support for "lines" steps to categorise script 1f2fc5a Add "Use exported imports" step 4e4a424 Refactor test creation 194d016 Merge pull request diffblue#493 from diffblue/antonia/simple-HashSet-tests 7a0cc29 Merge pull request diffblue#489 from diffblue/antonia/categorise-specs-script d6f3d9c Merge pull request diffblue#490 from diffblue/allredj/emptier-fixed c5149ae Include test header in debug output 5d1e1cd Remove auto-generated "passed" line ec7babd Tag test with ticket number TG-2332 cc6c691 Edit and sort tests for simple HashSet.clone d17aeaf Slightly modify and sort remaining generics tests 7fb122e Mark exception tests as future 5067254 Move test to future that depends on throw option fbebab6 Tag test as failing due to TG-3131 3aefc32 Tag TG-3430 test as future b91a5a6 Model for AbstractCollection.isEmpty 8d23268 Sort simple HashSet specs into pass and fail 5a0474b Modify tests for simple HashSet 11c2ccf Delete tests that don't exist from spec files 1c8e789 Edit Maven project in HashSet_simple.spec fcb6441 Delete legacy/level 2 tests for simple HashSet 0478736 Copy HashSet test folder to HashSet_simple d17cbb0 Copy HashSet.spec to HashSet_simple.spec 4bc4ded Replace most HashSet legacy tests with L1 tests 4a24d96 Delete duplicate Set class steps in HashSet.spec b4b4a35 Use new spec format for all L1* tests 9b2a89d Merge pull request diffblue#487 from diffblue/romain/model-test-generator 1768c7b Script for categorising specs into pass and fail 9cab0e8 fixup! Add package for model test generator ae29df1 Fix method pattern for underscores at the end 8a07718 Make TestInfo more resilient to missing statements de94631 Remove mock class arguments 882df2e Remove useless first argument b50ad06 Script to call test-gen and pipe to model-test-gen c1e3199 Add package for model test generator f226d64 Fix further bugs a070195 Some refactoring in unit tests 5adec2b Add support for simple models in generate script bea4bc5 Print help when no args given to generate-specs ae3e360 Remove restriction from generate-specs fbd3ae0 Fix commenting out of unexpected indents 185be7c Handle multi-line field definitions 76712bd Replace errors with assertions ca83981 Move generate-specs.sh to modelling-utils f9dd583 Merge pull request diffblue#485 from diffblue/allredj/testrunner-add-more-json-dumps 0c6830f Merge pull request diffblue#486 from diffblue/antonia/simple-ArrayList-tests b7f34ac Add documentation for Objects.requireNonNull 2e0ae85 Move common steps to the end as tear-down steps a9615fc Update documentation in simple ArrayList model 52758f9 Add tests for modified argument of toArray 617f8a4 Disable tests that may fail due to TG-3510 accf446 Remove non-existent test in ArrayList spec files 2e1147c Modify existing tests for simple model 5f5292c Fix ClassCastException of removeAll 241d441 Fix NPE in simple ArrayList.toArray(T[]) 08cdaf8 Fix exception case in simple ArrayList constructor 45f2437 Fix exception case in removeAll and retainAll 27ff11d Fix contains and indexOf in simple ArrayList 87d9c3d Remove and modify some tests in L1ClassNondet 0492f9e Fix rangeCheckForAdd in simple ArrayList model ac6cc48 Add missing exception in simple ArrayList model c2fe207 Add simple models step in spec file 37a36c6 Auto-generate categories of simple ArrayList specs 6aaad34 Correct typo in ArrayList spec file 5971f3a Move old ArrayList specs to new format bb4426b Copy ArrayList test folder into ArrayList_simple 59e2422 Use simple models on Travis 6b46fc8 Merge pull request diffblue#426 from diffblue/allredj/emptier 4ed871d Merge pull request diffblue#482 from diffblue/romain/replace-hashmap-renaming 581ce91 Merge pull request diffblue#484 from diffblue/feature/dashboard-webhooks c76af30 TestRunner: Add more JSON dumps 9086951 Add dashboard webhooks to travis c0baed2 Build utilities and run unit tests in CI c7a3c9d Utility to pre-process JDK files for modelling 8dd99aa Move utilities to subfolders 50f58df Add issue number for HashMap.replace issue faa8334 Rename test method names in spec file f1977d3 Use better names for HashMap.replace tests 88eabb3 Merge pull request diffblue#474 from diffblue/romain/hashmap-replace 9cd38bc Merge pull request diffblue#481 from diffblue/antonia/TestRunner-clear-reports 11ee4b4 Mark failing test as future fbbe7b1 Add HashMap.replace test to spec file aadd631 Make equality checks more appropriate 8713516 Improve replacement value in HashMap.replace 25c3efd Add specialized version of HashMap.replace tests 7d6b66d Remove useless side-effect tests for replace 0e389ee Add auto generated test for HashMap.replace 937bf42 Model for HashMap.replace fff013f Merge pull request diffblue#480 from diffblue/romain/update-specs-TG-2137 dbe0c15 Merge pull request diffblue#469 from diffblue/jeannie/UpdateFileDocs deac9c8 Merge pull request diffblue#479 from diffblue/antonia/mocking-exceptions-ticket 1b8d532 Clear reports as part of Setup step 087b635 Add additional references to TG-3273 85fffab Mark fullSupport methods working now correctly e4e6186 Activate tests fixed by TG-2137 TG-2138 781e965 Replace TG-1177 with TG-3273 cd8fd70 Merge pull request diffblue#475 from diffblue/antonia/Setup-Maven-project f047f34 Tests String.subsequence(char[],int,int) for integer wrapping. 60ea75d Ensure only one Setup step per spec file bb85868 Merge pull request diffblue#473 from diffblue/allredj/test-simple-models 1c6140a Merge pull request diffblue#467 from diffblue/antonia/object-self-ref 959491e Small improvements to the code 7cd70ae Add Gauge steps for adding simple models 7552215 Adapt setup.sh to also link simple models 982dca1 TestRunner: Make path to models final 8c64f58 Remove reference to deleted directory aec1834 Documents support for tested methods in java.io.File caf175f Documents limitations on java.io.File 56ce1bf Merge pull request diffblue#477 from diffblue/allredj/testrunner-dump-generated-test-on-fail 97429a3 Merge pull request diffblue#478 from diffblue/allredj/add-missing-step-in-File-spec 294e891 Merge pull request diffblue#466 from diffblue/justin/TG-2752_EnableTests c6597f7 [TG-2752] Enable disabled models-library tests dff3de1 Merge pull request diffblue#476 from diffblue/antonia/gauge-continue-on-fail a405dbc Merge pull request diffblue#472 from diffblue/antonia/tests-System 09b7fcc Add missing step in File.spec b2948b5 Dump generated tests on mvn test failure 144e4d2 Continue after failed Generate and Verify steps 4dcb147 Update documentation in System 98e29ed Add new tests for (get|set|clear)Property 481c160 Disable setProperty, setProperties, clearProperty 47f33a3 Rewrite tests for System fields in new format cefc156 Rewrite tests for System.getProperty in new format 3cf6a4c Enable test that used to fail due to TG-949 6618e32 Rewrite test for System.exit in new format c15c870 Add tests for most System methods 6a26462 Disable setIn(), setOut() and setErr() in System 52ce211 Merge pull request diffblue#470 from diffblue/feature/dump-stderr-on-error 0bbc49c Merge pull request diffblue#468 from diffblue/antonia/improve-generate-specs a9a32de Update readme for getopt installation on OS X 12c522d Update documentation fe9474e Merge pull request diffblue#471 from diffblue/allredj/fix-hashset-spec de5aee9 Add logging code for cbmc tests as well 3d7e5fb Also dump stderr on error f636bcb Fix syntax error in HashSet spec file 64d5a7d Merge pull request diffblue#462 from diffblue/justin/TG-3173_EnableTests e9e6022 Do not print whole spec file when -n is specified 3171bcf Provide more command-line options for gen-specs d39b1a6 [TG-3173] Enable disabled tests that should be fixed by this ticket 1141a4b Do not print useless "Set class file" steps 7b69dec Refactor generate-specs script 2cae6b2 Do not print specs that are already in spec file ce8a74e Rename sourcefile to classname dee7ca4 Merge pull request diffblue#459 from diffblue/antonia/delete-gen-test-folder bb17d6d Add regression tests for TG-3138 0cddd3e Merge pull request diffblue#457 from diffblue/jeannie/FileReaderAndOthers 6a72dbc Tests java.io.InputStreamReader 5b3aec5 Models java.io.InputStreamReader for mocking edfc70f Tests java.io.FileReader for mocking e993f0d Models java.io.FileReader for mocking. f433841 Tests java.io.FileInputStream for mocking 3ab02ed Models java.io.FileInputStream for mocking bb1c97a Updates tests in java.io.File for mocking f6e0d87 Merge pull request diffblue#452 from diffblue/jeannie/FilterReaderUnmock 8fa0c36 Documents support for java.io.PushbackReader 12efbe2 Tests java.io.PushbackReader fc80c36 Tests java.io.FilterReader 1125882 Initial commit for java.io.PushbackReader 5c4eda1 Removes java.io.FilterReader from mocking in TestRunner 7b0366a Models java.io.FilterReader 4dcc2fa Enables methods in java.io.Reader for inheritance. 604c7f2 Merge pull request diffblue#464 from diffblue/bugfix/subsequence 6b61a7b Forgotten check for exception in substring 0b54a1a Merge pull request diffblue#456 from diffblue/allredj/keyfactory 9fc72b6 Merge pull request diffblue#451 from diffblue/antonia/generate-specs-script 7be4f89 Mention generate-specs script in readme 62001ef Generalise generate-specs script 4d32caa Add script for generating Gauge specs 419b68f Merge pull request diffblue#454 from diffblue/allredj/fix-testrunner-message 9e2fba8 Merge pull request diffblue#449 from diffblue/romain/activate-TG-2098-tests-2 5e85389 Activate Hashtable tests fixed by TG-3173 6f99465 Activate HashSet tests fixed by TG-3173 38ce223 Delete unused generated_test folder d0d9a19 Merge pull request diffblue#374 from diffblue/jeannie/PropertiesUpdateTG1419 b89cf32 Merge pull request diffblue#455 from diffblue/jeannie/PropertiesRecursionFix a7f92dd Enables tests blocked by TG-2098 2867ebb Updates tests that had unreachable branches. 311b63e Merge pull request diffblue#445 from diffblue/romain/update-get-bytes-tests 4a74608 Merge pull request diffblue#450 from diffblue/antonia/tests-Random ab0587d Removes defaults field from java.io.Properties 8f1d266 Merge pull request diffblue#453 from diffblue/allredj/mocking-signature 6a6e12a Document java.security.KeyFactory model c01852f Add skipped tests for java.security.KeyFactory 7d0fa2c Document unwind restriction on getBytes 76cd7fa Tests java.util.Properties getProperty() with non-string value. abdeec5 Reformats Properties.spec to be in standard style. bc3d639 Enables tests in Properties due to TG-1419. 99646db Updates model for java.util.Properties to specialise to String. 1af1b0b Update documentation in Random.java 5f6cd61 Add L0 tests where necessary for Random e8e465b Add L1 tests for all modelled methods of Random 12ae250 Merge pull request diffblue#448 from diffblue/antonia/fix-File-getName 51275e6 Avoid IndexOutOfBoundsException in File 4e928d4 Add skipped tests for java.security.Signature e185fe1 Add tests for getBytes with long strings 058b221 Activate getBytes tests that can be activated 54604c3 Update TestRunner to flag discarded test case 7b9d95f Update documentation of java.security.Signature c5dde15 Basic model for java.security.SignatureSpi 8c07616 Import java.security.SignatureSpi from JDK 10965f1 Merge pull request diffblue#447 from diffblue/antonia/disable-Charset-test 0777f41 Add documentation for Charset.hashCode d5a72a6 Merge pull request diffblue#446 from diffblue/allredj/remove-support-v1-tags 077e997 Add class-level JDK documentation back to Charset 0cfa9bb Disable Charset.hashCode test that sometimes fails a52135f Merge pull request diffblue#436 from diffblue/allredj/remove-classpath-in-main-library 4e45c16 Merge pull request diffblue#417 from diffblue/allredj/gauge-dump-stdout-on-error 3e90539 Remove support-v1 tags from spec files a1415ed Merge pull request diffblue#433 from diffblue/romain/clean-up-hashset-base64 e40531f Merge pull request diffblue#442 from diffblue/jeannie/FileReaderMocking 49198f8 Copies methods from InputStreamReader to FileReader. 0f760fd Merge pull request diffblue#444 from diffblue/antonia/disable-BitSet-test 8fa4019 Merge pull request diffblue#443 from diffblue/jeannie/FilterReaderMocking f1fb492 Update title of TG-3043 in LinkedList.spec cb01593 Disable BitSet test affected by TG-3043 9a615fd Adds super call and field assignment in FilterReader. 183ca96 Merge pull request diffblue#437 from diffblue/forejtv/exceptions-no-toString 8c77b53 Retag HashSet bug to relevent issue 3717d70 Merge pull request diffblue#441 from diffblue/jeannie/MockingForTestRunner 00a0d17 Merge pull request diffblue#440 from diffblue/jeannie/WriterConstructors 64d3059 Double escapes dots in TestRunner --java-mock-class e1d68dc Models constructors in java.io.Writer d78363d Adds classes to TestRunner.java for mocking 9dbd27a Merge pull request diffblue#439 from diffblue/antonia/System-currentTimeMillis 6fcdb5e Enable mocking for java.lang.System in TestRunner 1d190fb Models Hashtable.remove(Object) 769aa61 Models Properties.getProperty(String,String) 1c216ff Further models System for mocking 7280385 Merge pull request diffblue#425 from diffblue/jeannie/File 8dc4121 Merge pull request diffblue#435 from diffblue/allredj/basic-models dca5a90 Merge pull request diffblue#434 from diffblue/antonia/Random-nextFloat 9c7288b Merge pull request diffblue#421 from diffblue/jeannie/SimpleModelHashtableProperties 3522d82 Copy newly modelled methods to SecureRandom model 45479cd Add tests for Random constructor and nextFloat b45eb4e Mock java.util.Random in TestRunner c0e9ac9 Comment out package-private methods in Random 71cc083 Model for java.util.Random 85f72b3 Update documentation in SecureRandom 195c4e4 Merge pull request diffblue#431 from diffblue/allredj/model-for-java-io-StringWriter 3f59dad Merge pull request diffblue#422 from diffblue/jeannie/SimpleModelArrays a0a5072 Merge pull request diffblue#429 from diffblue/jeannie/ReaderStackOverflowFix cd82ad2 Merge pull request diffblue#430 from diffblue/jeannie/BufferedReaderUpdateTestNumber d4669bf Tests java.io.File debb417 Mocks java.io.File in TestRunner.java 2b563f6 Models java.io.File for mocking. d14fafd Basic model for java.security.Signature b08d3bd Import java.security.Signature from JDK 183d408 Basic model for java.security.KeyFactory 44fc2d8 Import java.security.KeyFactory from JDK c365ccf Basic model for java.nio.file.Paths a8b8a43 Import java.nio.file.Paths from JDK 3099271 Basic model for java.nio.file.Files 651faf5 Import java.nio.file.Files from JDK b1dceb1 Basic model for java.lang.ProcessBuilder 5b4e8d6 Import java.lang.ProcessBuilder from JDK 4c6eb6b Basic model for java.lang.Process b2d6b3d Import java.lang.Process from JDK 3e34ef3 Basic model for java.io.StringWriter.java be0c11d Import java.io.StringWriter from JDK a59e43b Basic model for java.io.PrintWriter 7aa3271 Import java.util.PrintWriter from JDK 063e013 Basic model for java.io.FilterReader 1e982d1 Import java.io.FilterReader from JDK d3340a2 Basic model for java.io.InputStreamReader 5c0aaf6 Import java.io.InputStreamReader from JDK ea5ddc7 Updates incorrect ticket numbers in BufferedReader. a2602c6 Changes lock on Reader and Writer to dummy Object. f19ee1c Improves Properties tests. fa5182a Models Properties for simple model. dd3efa3 Models Hashtable for simple models. 91de9ff Empties Hashtable and Properties models. ea99011 Initial commit Hashtable, Properties simple models. 892e1de fixup! Addresses review comments 59e4605 Models Arrays.asList() for simple models. 9a58b96 Empties Arrays simple model. f119e1b Initial commit for Arrays simple model. f9ac9bc Use less "toString" calls in simple models. b1e9d65 Remove classpath in main library 95138d7 Basic model for java.io.FileReader 014d3ed Correct format of java.io.FileReader bc8fb8e Import java.io.FileReader from JDK 64db884 Basic model for java.io.FileInputStream 04e66c7 Import java.io.FileInputStream from JDK 335a2b7 Basic model for java.io.StringWriter 7b939e2 Import java.io.StringWriter from JDK 5e4252f Move exception up in cproverDecodeLength e605f5e Merge pull request diffblue#427 from diffblue/bugfix/base64-wrong-ending 40a4ef4 Merge pull request diffblue#428 from diffblue/Deeptest-utils1.1.0 dc57cfd Update Deeptest utils version number cca5c89 Merge pull request diffblue#424 from diffblue/antonia/simple-model-BitSet f93ddee Add tests for standard BitSet model 1eeb1ae Simple model for BitSet a283e67 Copy standard BitSet model to model-simple bb0e147 Add TODO about data structure used in BitSet model c2e6fd0 Mark methods in BitSet as untested b1b7bac Model BitSet.valueOf(byte[]) 5e32e23 Refactor decodeLastPosition 83a951a Assume encoded characters are valid 2c62411 Raise exception for illegal length ce7a8c7 Split BitSet spec files into Level 0 and 1 585bde6 Small optimisation in BitSet model 2a53838 Tidy up standard BitSet model 4d34638 Merge pull request diffblue#420 from diffblue/retag/TG-2892 a1ff717 Merge pull request diffblue#419 from diffblue/romain/base64-2 1e9e256 Merge pull request diffblue#423 from diffblue/justin/TG-992-Re-enable_tests 48861e7 [TG-992] Re-enable previously disabled tests db26be5 Remove trailing whitespaces 902bdde Remove untested flag from decode 7290189 Activate test for decode with padding 319608a Support for URL decoder afa48ce Activate more tests for Base64 bab6fff Remove unused decode0 argument b8a0702 Use a more imperative style in decode0 f2a2327 Make cproverDecodeLength aware of padding 3c1bb01 More tests for Base64.decode 39afd34 Prefix helper functions with cprover 8429ba2 Correct issue number for performance issues 063f0bd Merge pull request diffblue#406 from diffblue/romain/remove-ref-to-TG-2459-and-2338 8645435 Merge pull request diffblue#416 from diffblue/jeannie/BufferedReaderUpdate 5a8b1c4 Enables tests for BufferedReader 3db97c4 Tests BufferedReader further 1abaf0d Refactors BufferedReader to be more general 017d896 Merge pull request diffblue#418 from diffblue/allredj/disable-failing-test 48cf253 Disable failing LinkedList test 2adbfe4 Gauge: Dump test-generator stdout on failure 58a8317 Merge pull request diffblue#415 from diffblue/romain/base64-tests 2bcabd2 Improves existing tests for BufferedReader b73b527 Merge pull request diffblue#413 from diffblue/allredj/simple-arraylist 50f7134 Spec file for Base64 tests c70891d Add tests for Byte64 0d1880b Corrections to Base64 model 762f4a6 Merge pull request diffblue#414 from diffblue/antonia/simple-model-LinkedList 8aa0258 Merge pull request diffblue#412 from diffblue/romain/base64 c405539 Simple model for ArrayList 7d8efd8 Import model from models-library ff33657 Enable iterator methods in abstract classes 7d35366 Write simplified model for LinkedList 8edb2bd Merge pull request diffblue#410 from diffblue/antonia/simple-model-LinkedHashMap 38c6142 Add support for Base64 decode methods 4a72628 Empty Base64 model fed77be Copy Base64 from JDK 29b771e Merge pull request diffblue#409 from diffblue/jeannie/ReadersUpdate 6599bce Write simplified model for LinkedHashMap 7063f99 Copy standard LinkedList model to model-simple df43878 Re-align comments in standard LinkedList 51b2293 Merge pull request diffblue#407 from diffblue/bugfix/get-bytes-TG-2878 abe1fc3 Merge pull request diffblue#408 from diffblue/antonia/simple-model-HashSet 9c54e92 Enables tests for StringReader. TG-1450, TG-1290 f7278f8 Update Javadoc for simple model 9795fcb Correct initialCapacity value in Javadoc b84bb6b Write simplified model for HashSet d7afaaf Simplifies and documents java.io.StringReader 9b212e3 Simplifies and documents java.io.Reader model. e47fa38 Copy standard LinkedHashMap model to model-simple a1cc2a5 Remove unnecessary doc in standard LinkedHashMap 89058e8 Activate tests for GetBytesUtf16 5816659 Enforce non-supplementary characters in getBytes 743ab04 Remove ref to TG-2459 from StringBuilder 4f4990f Remove ref to TG-2338 from StringBuffer e3f3af2 Remove ref to TG-2338 from String model eb7ce68 Copy standard HashSet model to model-simple 64646d1 Small updates in standard HashSet model 6574386 Merge pull request diffblue#405 from diffblue/antonia/simple-models f3f423a Merge pull request diffblue#403 from diffblue/tests/TG-2459 dc1728e Compile simple models on Travis 245798d Remove standard model doc from simple model 5a8ac8f Write simplified model for HashMap 960a736 Copy standard HashMap model to model-simple f296fc2 Small updates in standard HashMap model e422127 Add Maven project for models-simple-overlay cb29c9b Activate tests in String.spec with label TG-2338 9424d87 Activate StringBuilder tests fixed by TG-2459 679a21c Activate StringBuffer tests fixed by TG-2459 dffcbd8 Merge pull request diffblue#404 from diffblue/jeannie/AddRegressionTesttg2763 37781fa Merge pull request diffblue#399 from diffblue/allredj/add-codeowner 1e4568e Merge pull request diffblue#402 from diffblue/allredj/update-doc-system-arraycopy e2ff539 Merge pull request diffblue#401 from diffblue/allredj/enable-code-point-before dda025a Enable tests for String.codePointBefore 8b3da3e Adds regression test for TG-2763 19b7efe Merge pull request diffblue#400 from diffblue/antonia/String-format-tests c137b46 Merge pull request diffblue#377 from diffblue/allredj/hashmap-remove-loadfactor 65c4e29 Add missing javadoc for System.arraycopy bb24960 Remove loadFactor field in HashMap e26d267 Add tests for String.format 7cc669d Merge pull request diffblue#369 from diffblue/allredj/testrunner-iterative-unwind 2c463ca Merge pull request diffblue#329 from diffblue/romain/script-generalize-v2 6aadb18 Incremental unwind for test generation 077f316 Parameterise unwind value 0e127d2 Refactor to separate check coverage from fail 5c16dcb Remove redundant check b9400cd Add Jeannie to models-library CODEOWNERS 4d44485 Add script class files to gitignore a03fb9e Example input for the GeneralizeJavaMethod script b912461 GeneralizeJavaMethod script corrections e613bc8 Reformat script 1a5eea8 Script specializing method to different types git-subtree-dir: benchmarks/LIBRARIES/models git-subtree-split: 1e8b77c839d0c54c83afc307b6bd76a51f613794
This is a proof of concept - there are still some structural improvements to be made (and function headers for all the functions) - so don't merge just yet.
Previously if a variable was a function pointer - we would branch in the goto program on all functions that had the right signature. This was causing problems in cases that uses dispatch tables as in reality it would be a very small number of functions that could actually be used.
The approach taken here is to handle these specific cases more intelligently. Basically, if we can work out either exactly what the function pointer is pointing to (because it is constant) or work out which array the function will come from (because it is pointing to an index inside an array), then we only generate code to handle these functions.
The main area of feedback I would appreciate is to do with resolving indirect access. For example, if the pointer is pointing to a
symbolt
then we need to look up the symbol in the symbol table and find what that is pointing to. Although I think below handles most cases (And should fail back to the old naive approach of all matching functions in the cases it can't), but I suspect there is some general code I should be using here to resolve this but I couldn't find any.