klee / klee

KLEE Symbolic Execution Engine

Home Page:https://klee-se.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

KLEE missing an error on symbolic array access

salvadorer opened this issue · comments

Hi,
I detected the following issue in KLEE:
I compiled the code below with clang -I ~/klee/include -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone test.c:

#include "klee/klee.h"
#include <assert.h>

int main (int argc, char* argv[]) {
  int d1;
  int d2;
  int *d3;
  int arr[1] = {0};
  int var = klee_int("var");
  klee_assume(0x32DAE895 < var);
  int i = klee_int("i");
  klee_assume(var < arr[i]);
  assert(0);
}

If I now invoke klee --silent-klee-assume --emit-all-errors --solver-backend=stp test.bc, I see a non-deterministic behavior: In some cases (roughly 20%) I see:

$ klee --silent-klee-assume --emit-all-errors --solver-backend=stp test.bc 
KLEE: output directory is "klee-out-1"
KLEE: Using STP solver backend
KLEE: SAT solver: MiniSat
KLEE: Deterministic allocator: Using quarantine queue size 8
KLEE: Deterministic allocator: globals (start-address=0x7f0fbf1cd000 size=10 GiB)
KLEE: Deterministic allocator: constants (start-address=0x7f0d3f1cd000 size=10 GiB)
KLEE: Deterministic allocator: heap (start-address=0x7e0d3f1cd000 size=1024 GiB)
KLEE: Deterministic allocator: stack (start-address=0x7ded3f1cd000 size=128 GiB)
KLEE: ERROR: test.c:12: memory error: out of bound pointer
KLEE: ERROR: test.c:13: ASSERTION FAIL: 0

KLEE: done: total instructions = 162
KLEE: done: completed paths = 0
KLEE: done: partially completed paths = 10
KLEE: done: generated tests = 2

In the other case, the warning about the assertion is missed. I'd expect a warning about the assertion in each case as for i=0 the assertion does not hold.
I'm working on an Ubuntu platform and klee --version gives:
KLEE 3.1-pre (https://klee.github.io)
Build mode: RelWithDebInfo (Asserts: ON)
Build revision: unknown

Ubuntu LLVM version 14.0.0

Optimized build.
Default target: x86_64-pc-linux-gnu
Host CPU: znver3

I'd expect a warning about the assertion in each case as for i=0

arr[i] can point anywhere in memory and sometimes resolves to a valid object (e.g. d1).

I see a non-deterministic behavior

You can fix the start addresses for the deterministic allocator (e.g. --kdalloc-constants-start-address) and than it should be deterministic.

I understand that the assertion might fail non-deterministically depending on whether the previous assumption evaluates to true or false (in turn depending on what arr[i] points to). However, doesn't KLEE branch on the bounds check, ensuring that i will also have value 0, and therefore, make the assertion fail?

ensuring that i will also have value 0

But then

klee_assume(var < arr[i]);

would boil down (roughly) to

klee_assume(0x32DAE895 < 0);

This check fails and cannot reach the assert or what do you mean?

True, this makes sense.
Thanks for your help!