Open michael-schwarz opened 5 months ago
However, it seems unclear what that is supposed to do: Currently, the effect is that while paths are kept separate, they are then all propagated to callees. This seems unnecessary, it should be possible to remember (hashes) of the original paths and then only combine values from compatible paths.
The current behavior (https://github.com/goblint/analyzer/blob/60ecfe7eb23fcdd927eed52da45c9da755dc7fa3/src/framework/constraints.ml#L802-L810) should be that all paths are propagated from the caller to the callee separately and the result of each is combined with the corresponding caller state. That's why enter
returns a list of pairs (caller state, callee state) and combine is applied pairwise.
paths_as_set
(added during the longjmp
work) is also used to do this kind of splitting somewhere else.
In our constraint-based view, the two sensitivities have aspects that the other cannot replace:
Yes, I agree that there are subtle differences between both features and that we should have both, but I still think that the interaction between them is perhaps not particularly well thought-out yet.
Consider, e.g., the following program:
// PARAM: --set ana.ctx_insens[+] threadflag --set ana.ctx_insens[+] threadid --set ana.ctx_insens[+] base --set ana.path_sens[+] threadflag
// Fully context-insensitive, but thread is path-sensitive
#include <goblint.h>
#include <pthread.h>
int foo(int arg) {
return arg;
}
void *t_fun(void *arg) {
int r = foo(2);
__goblint_check(r == 2); // Currently fails in one path and succeeds in the other
}
int main() {
int r = foo(1);
__goblint_check(r == 1); // Currently fails in one path and succeeds in the other
pthread_t id;
pthread_create(&id, NULL, t_fun, NULL);
return 0;
}
foo
is kept separate all the time, but then both paths propagate to both callers. threadflag
context-sensitive. I think a more intuitive way for path-sensitivity to work across call-boundaries (that still should be relatively easy to implement and almost for free):
This would be how I would path-sensitivity in an interprocedural setting to work intuitively: If the different paths happen to be kept apart inside the procedure, we get some notion of context-sensitivity in the path information for free. Otherwise, we don't, but at least we only get propagated those paths into which our path was potentially joined instead of getting all of them.
I'm not sure if I am expressing myself clearly here, if not, please tell me and I might try to write up something more formal.
For #1508 I was playing around with various configurations to check that they still work, and it seems that Goblint allows to have an analysis that is path-sensitive, but not context-sensitive.
However, it seems unclear what that is supposed to do: Currently, the effect is that while paths are kept separate, they are then all propagated to callees. This seems unnecessary, it should be possible to remember (hashes) of the original paths and then only combine values from compatible paths.
At first glance, it might also make sense to only allow path-sensitivity for context-sensitive analyses: However, the information that is kept by the two different sensitivities is (potentially) different, which is in itself again dubious: If I have path-sensitivity active, would it not make sense to also consider this path-sensitive information part of the context.
I think this merits a principled re-design, and it should also be documented what these settings do.