Description
Dear CBMC Team,
Thank you for your incredible work on CBMC, which has been invaluable for our verification tasks. I am writing to kindly inquire if there might be a limitation or bug in CBMC 6.4.1 on Mac OS that prevents it from correctly handling sscanf
and strcmp
with symbolic strings. I’ve encountered unexpected counterexamples in my tests, and I’d greatly appreciate your guidance or confirmation if this is a known issue.
Test Program
Below is a minimal test program I’ve created to investigate this behavior:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_BUFFER_SIZE 20
void harness_sscanf() {
char buffer[MAX_BUFFER_SIZE];
// Ensure the buffer is null-terminated within bounds
__CPROVER_assume(buffer[MAX_BUFFER_SIZE - 1] == '\0');
// Check if input starts with "Hello"
if (sscanf(buffer, "Hello") == 0) {
assert(0); // Force CBMC to find an input that starts with "Hello"
}
}
void harness_strcmp() {
char buffer[MAX_BUFFER_SIZE]; // Symbolic input buffer
// Ensure the buffer is null-terminated within bounds
__CPROVER_assume(buffer[MAX_BUFFER_SIZE - 1] == '\0');
// Constrain buffer to have at least length 2 (for "Hello") and be reasonable
__CPROVER_assume(strlen(buffer) >= 2 && strlen(buffer) < MAX_BUFFER_SIZE - 1);
// Check if input exactly matches "Hello" using strcmp
if (strcmp(buffer, "Hello") != 0) {
assert(0); // Force CBMC to find an input that exactly matches "Hello"
}
}
void harness_simple_check() {
char buffer[MAX_BUFFER_SIZE]; // Symbolic input buffer
// Ensure the buffer is null-terminated within bounds
__CPROVER_assume(buffer[MAX_BUFFER_SIZE - 1] == '\0');
// Optional: constrain length if needed (e.g., strlen(input) < 9)
if (buffer[0] == 'H' && buffer[1] == 'e' && buffer[2] == 'l' && buffer[3] == 'l' && buffer[4] == 'o') {
assert(0); // Fail if "HI......!" pattern matches
}
}
Commands and Counterexamples
I ran the following commands on macOS ARM64 using CBMC 6.4.1:
For harness_sscanf
cbmc test_ssncf.c --function harness_sscanf --no-standard-checks --no-built-in-assertions --unwind 6 --trace
Counterexample Produced:
buffer={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
For harness_strcmp
cbmc test_ssncf.c --function harness_strcmp --no-standard-checks --no-built-in-assertions --unwind 6 --trace
Counterexample Produced:
buffer={ 'I', 'd', 0, 2, '`', 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
For harness_simple_check
cbmc test_ssncf.c --function harness_simple_check --no-standard-checks --no-built-in-assertions --unwind 6 --trace
Counterexample Produced:
buffer={ 'H', 'e', 'l', 'l', 'o', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
Expected Behavior
For the first two harnesses, I expected CBMC to produce a counterexample where buffer = "Hello\0..."
(e.g., {'H', 'e', 'l', 'l', 'o', 0, 0, ..., 0}
). This would indicate that CBMC successfully found an input that:
- For
harness_sscanf
, starts with"Hello"
(sosscanf(buffer, "Hello") == 1
). - For
harness_strcmp
, exactly matches"Hello"
(sostrcmp(buffer, "Hello") == 0
).
Environment
- Operating System: macOS (ARM64, Apple Silicon M3)
- CBMC Version: 6.4.1
In sum, this issue looks like a limitation or bug in CBMC 6.4.1 on macOS ARM64 that affects its handling of sscanf and strcmp with symbolic strings. The correct behavior of harness_simple_check suggests CBMC handles direct character comparisons well, but sscanf and strcmp struggle with constraint propagation or symbolic string modeling.
Thank you very much for your time and support!