-
Notifications
You must be signed in to change notification settings - Fork 273
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
Performance Cliff and Excessive Memory Usage at --unwind 6 #8600
Comments
Trying to Explain Why You Might See this BehaviourIt seems that increasing the unwinding by 1 triggers execution of a whole new set of program statements. Most likely you will have CBMC running on a very wide call tree, caused by excessive branching. This, in turn, is often caused by CBMC resolving function pointers to some over-approximate set of functions over the ones that can actually be called at any such point. A possible scenario is that you are iterating beyond the bounds of an array of function pointers such that the sixth element isn't initialised anymore and, therefore, CBMC's over-approximate function pointer resolution behaviour becomes apparent. Remark: The above is some speculation as I couldn't find version 1.7.99 of cJSON, and neither was I able to find the function A Simple RemediationTo tell whether you are likely facing this scenario or not you may wish to review the early stages of the log output with The Better RemediationInstead of trying to work around the limitations of bounded model checking you might instead opt for unbounded verification, using code contracts and/or loop invariants. See our documentation at https://diffblue.github.io/cbmc/contracts-user.html. For an practical example see coreJSON where we insert loop invariants described in this patch. |
Thank you! We'll look into these remediations. |
Also consider |
Daniel, thank you! I’ll definitely give that a try. CBMC is truly an awesome tool, and I’m excited about the prospect of using it for real-world projects. I’ve had some success by simplifying a loop-heavy function in CJSON, although I’m a bit worried that these simplified functions or using the --depth flag might affect CBMC’s soundness. Still, I’m exploring that direction. Also, could you possibly take a look at another question I posted? Here’s the link: #8602. It’s about CBMC’s modeling of library functions like sscanf and strcmp, and the related challenge of generating a counterexample for a char*. |
I reran CBMC on cJSON using a high-performance server. After running for over 55 hours, CBMC terminated with a segmentation fault. Here is the command I used: time cbmc -Ilib/cJSON app/main.c lib/cJSON/cJSON.c lib/cJSON/cJSON_Utils.c --function harness_2_commands --trace --no-standard-checks --no-built-in-assertions --unwind 6 The output was as follows:
This performance issue and the segmentation fault disappeared after I replaced two blocking functions (shown from |
If you have recursive functions and loops you may want to try using function contracts ? Here is a regression test example that checks a function that contains loops and also calls itself: When using loop contracts and contracts for recursive functions you need to provide invariants and pre/post conditions but then CBMC reasons using induction instead of unwinding. |
Thank you, Remi, for the great pointer! Did you mean that CBMC, when using unwind, is known to struggle with functions that call themselves within a If it helps, I can provide a minimal working example for you to debug—assuming the regression test doesn’t already expose the issue. I’ll try the approach of generating function contracts and loop invariants. However, since producing function contracts isn’t something that can be easily automated, I’d still like to explore the possibility of relying on unwind—if that’s feasible. |
Hi, I've looked at the JSON parser code and I can tell you there's very little hope to verify all of that in one go using just unwinding. I could not really figure out what function you are analyzing ( Some of the reasons::
Look at this regression test for an example of
However there's some prior art that shows that it is possible to verify such JSON parsers using CBMC A couple of years ago we verified the coreJSON parser of freeRTOS for memory safety using CBMC, with function and loop contracts. It seems really similar to what you're currently trying to do. https://github.com/feliperodri/coreJSON/tree/52918f1ab0df56932af929008a9f7af2c7dc4d49/test/cbmc You can see the function contracts we defined for the basic functions of the parser here:
With all of this we were able to prove the memory safety without using unwinding, for any byte buffer input size. Getting to that sort of result is however a non-trivial amount of work. |
CBMC Bug Report: Performance Cliff and Excessive Memory Usage at
--unwind 6
Performance Degradation and Memory Explosion in CBMC 6.4.1 on macOS ARM64 with
--unwind 6
When VerifyingcJSON.c
.Please advise if this is a known bug, and suggest patches or workarounds. I’m happy to provide more logs, test cases, or assist in debugging.
Description
I am experiencing a severe performance issue with CBMC 6.4.1 when increasing the
--unwind
value from 5 to 6 while verifying a C program that uses thecJSON
library (cJSON.c
). For--unwind ≤ 5
, CBMC completes execution within seconds with reasonable memory usage. However, at--unwind 6
, CBMC runs for over 10 hours without producing a result, and memory usage exceeds 100GB, which is unexpected and appears to indicate a state space explosion or bug.Steps to Reproduce
Environment:
Project Structure:
main.c
: Contains a harness function provided below.lib/cJSON/cJSON.c
: ThecJSON
JSON parsing library (version 1.7.99, linked from https://github.com/DaveGamble/cJSON/blob/master/cJSON.c). The file also contains manually inserted assertions.lib/cJSON/cJSON_Utils.c
: Utilities forcJSON
.lib/cJSON/cJSON.h
andlib/cJSON/cJSON_Utils.h
: Corresponding headers (assumed to be included).Harness and Command:
Harness Code (in
main.c
):Command for Low Unwind (Works Fine):
Command for High Unwind (Fails):
Verbose Output (With
--verbosity 9
):--unwind 6
and--verbosity 9
, the following lines seem to repeat indefinitely, suggesting a potentially infinite loop or excessive unrolling:process_command
call), the output is concise and fast:Expected Behavior
--unwind
(e.g., from 5 to 6), not exponentially. For--unwind 6
, CBMC should complete within minutes (or at most hours) with reasonable memory usage (e.g., <10GB), not >10 hours and >100GB.Actual Behavior
--unwind 6
, CBMC hangs for >10 hours, consumes >100GB of memory, and appears stuck in excessive unrolling ofcJSON_Delete
’s loop and recursion inlib/cJSON/cJSON.c
(line 260).Additional Context
Assertions in
cJSON.c
:cJSON.c
to test for vulnerabilities.Workarounds Tried:
buffer[i]
to specific commands (ADD
,MOD
,GET id
,EXIT
) using__CPROVER_assume
, but the issue persists.Impact
This performance cliff prevents effective verification of multi-command sequences.
Possible Cause
cJSON_Delete
function (line 260 incJSON.c
) contains awhile
loop and recursive calls (cJSON_Delete(item->child)
), which CBMC unrolls excessively at--unwind 6
. This likely causes a state space explosion.The text was updated successfully, but these errors were encountered: