//===-- KTest.cpp ---------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "klee/ADT/KTest.h" #include #include #include #define KTEST_VERSION 3 #define KTEST_MAGIC_SIZE 5 #define KTEST_MAGIC "KTEST" // for compatibility reasons #define BOUT_MAGIC "BOUT\n" /***/ static int read_uint32(FILE *f, unsigned *value_out) { unsigned char data[4]; if (fread(data, 4, 1, f)!=1) return 0; *value_out = (((((data[0]<<8) + data[1])<<8) + data[2])<<8) + data[3]; return 1; } static int write_uint32(FILE *f, unsigned value) { unsigned char data[4]; data[0] = value>>24; data[1] = value>>16; data[2] = value>> 8; data[3] = value>> 0; return fwrite(data, 1, 4, f)==4; } static int read_string(FILE *f, char **value_out) { unsigned len; if (!read_uint32(f, &len)) return 0; *value_out = (char*) malloc(len+1); if (!*value_out) return 0; if (fread(*value_out, len, 1, f)!=1) return 0; (*value_out)[len] = 0; return 1; } static int write_string(FILE *f, const char *value) { unsigned len = strlen(value); if (!write_uint32(f, len)) return 0; if (fwrite(value, len, 1, f)!=1) return 0; return 1; } /***/ unsigned kTest_getCurrentVersion() { return KTEST_VERSION; } static int kTest_checkHeader(FILE *f) { char header[KTEST_MAGIC_SIZE]; if (fread(header, KTEST_MAGIC_SIZE, 1, f)!=1) return 0; if (memcmp(header, KTEST_MAGIC, KTEST_MAGIC_SIZE) && memcmp(header, BOUT_MAGIC, KTEST_MAGIC_SIZE)) return 0; return 1; } int kTest_isKTestFile(const char *path) { FILE *f = fopen(path, "rb"); int res; if (!f) return 0; res = kTest_checkHeader(f); fclose(f); return res; } KTest *kTest_fromFile(const char *path) { FILE *f = fopen(path, "rb"); KTest *res = 0; unsigned i, version; if (!f) goto error; if (!kTest_checkHeader(f)) goto error; res = (KTest*) calloc(1, sizeof(*res)); if (!res) goto error; if (!read_uint32(f, &version)) goto error; if (version > kTest_getCurrentVersion()) goto error; res->version = version; if (!read_uint32(f, &res->numArgs)) goto error; res->args = (char**) calloc(res->numArgs, sizeof(*res->args)); if (!res->args) goto error; for (i=0; inumArgs; i++) if (!read_string(f, &res->args[i])) goto error; if (version >= 2) { if (!read_uint32(f, &res->symArgvs)) goto error; if (!read_uint32(f, &res->symArgvLen)) goto error; } if (!read_uint32(f, &res->numObjects)) goto error; res->objects = (KTestObject*) calloc(res->numObjects, sizeof(*res->objects)); if (!res->objects) goto error; for (i=0; inumObjects; i++) { KTestObject *o = &res->objects[i]; if (!read_string(f, &o->name)) goto error; if (!read_uint32(f, &o->numBytes)) goto error; o->bytes = (unsigned char*) malloc(o->numBytes); if (fread(o->bytes, o->numBytes, 1, f)!=1) goto error; } fclose(f); return res; error: if (res) { if (res->args) { for (i=0; inumArgs; i++) if (res->args[i]) free(res->args[i]); free(res->args); } if (res->objects) { for (i=0; inumObjects; i++) { KTestObject *bo = &res->objects[i]; if (bo->name) free(bo->name); if (bo->bytes) free(bo->bytes); } free(res->objects); } free(res); } if (f) fclose(f); return 0; } int kTest_toFile(KTest *bo, const char *path) { FILE *f = fopen(path, "wb"); unsigned i; if (!f) goto error; if (fwrite(KTEST_MAGIC, strlen(KTEST_MAGIC), 1, f)!=1) goto error; if (!write_uint32(f, KTEST_VERSION)) goto error; if (!write_uint32(f, bo->numArgs)) goto error; for (i=0; inumArgs; i++) { if (!write_string(f, bo->args[i])) goto error; } if (!write_uint32(f, bo->symArgvs)) goto error; if (!write_uint32(f, bo->symArgvLen)) goto error; if (!write_uint32(f, bo->numObjects)) goto error; for (i=0; inumObjects; i++) { KTestObject *o = &bo->objects[i]; if (!write_string(f, o->name)) goto error; if (!write_uint32(f, o->numBytes)) goto error; if (fwrite(o->bytes, o->numBytes, 1, f)!=1) goto error; } fclose(f); return 1; error: if (f) fclose(f); return 0; } unsigned kTest_numBytes(KTest *bo) { unsigned i, res = 0; for (i=0; inumObjects; i++) res += bo->objects[i].numBytes; return res; } void kTest_free(KTest *bo) { unsigned i; for (i=0; inumArgs; i++) free(bo->args[i]); free(bo->args); for (i=0; inumObjects; i++) { free(bo->objects[i].name); free(bo->objects[i].bytes); } free(bo->objects); free(bo); }