1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
#include <stdbool.h>
typedef struct CTX
{
int data[16];
} CTX;
union low_level_t
{
CTX md5;
};
typedef struct HIGH_LEVEL_MD
{
unsigned long flags;
} HIGH_LEVEL_MD;
typedef struct HIGH_LEVEL_MD_CTX
{
HIGH_LEVEL_MD *digest;
unsigned long flags;
} HIGH_LEVEL_MD_CTX;
struct high_level_digest_t
{
HIGH_LEVEL_MD_CTX *ctx;
};
struct high_level_t
{
struct high_level_digest_t first;
struct high_level_digest_t second;
};
typedef struct state_t
{
union
{
union low_level_t low_level;
struct high_level_t high_level;
} digest;
} state_t;
bool nondet_bool();
bool is_high_level()
{
static bool latch = false;
static bool once = false;
if(!once)
{
latch = nondet_bool();
once = true;
}
return latch;
}
int update(state_t *state, bool also_second)
// clang-format off
__CPROVER_requires(__CPROVER_is_fresh(state, sizeof(*state)))
__CPROVER_requires(
is_high_level() ==>
__CPROVER_is_fresh(state->digest.high_level.first.ctx,
sizeof(*(state->digest.high_level.first.ctx))) &&
__CPROVER_is_fresh(state->digest.high_level.first.ctx->digest,
sizeof(*(state->digest.high_level.first.ctx->digest))))
__CPROVER_requires(
is_high_level() && also_second ==>
__CPROVER_is_fresh(state->digest.high_level.second.ctx,
sizeof(*(state->digest.high_level.second.ctx))) &&
__CPROVER_is_fresh(state->digest.high_level.second.ctx->digest,
sizeof(*(state->digest.high_level.second.ctx->digest))))
__CPROVER_assigns(
is_high_level():
__CPROVER_object_whole(state->digest.high_level.first.ctx->digest),
state->digest.high_level.first.ctx->flags;
is_high_level() && also_second:
__CPROVER_object_whole(state->digest.high_level.second.ctx->digest),
state->digest.high_level.second.ctx->flags;
)
// clang-format on
{
if(is_high_level())
{
// must pass
__CPROVER_havoc_object(state->digest.high_level.first.ctx->digest);
state->digest.high_level.first.ctx->flags = 0;
if(also_second)
{
// must pass
__CPROVER_havoc_object(state->digest.high_level.second.ctx->digest);
state->digest.high_level.second.ctx->flags = 0;
}
// must fail
__CPROVER_havoc_object(state->digest.high_level.second.ctx->digest);
state->digest.high_level.second.ctx->flags = 0;
}
// must fail
__CPROVER_havoc_object(state->digest.high_level.first.ctx->digest);
state->digest.high_level.first.ctx->flags = 0;
// must fail
__CPROVER_havoc_object(state->digest.high_level.second.ctx->digest);
state->digest.high_level.second.ctx->flags = 0;
return 0;
}
int main()
{
state_t *state;
bool also_second;
update(state, also_second);
return 0;
}
|