#define INIT_VIS
#endif
+#if SANITIZER_INTERCEPT_CDB
+INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open, const char *path, int flags) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open, path, flags);
+ if (path)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ struct __sanitizer_cdbr *cdbr = REAL(cdbr_open)(path, flags);
+ if (cdbr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
+ return cdbr;
+}
+
+INTERCEPTOR(struct __sanitizer_cdbr *, cdbr_open_mem, void *base, SIZE_T size,
+ int flags, void (*unmap)(void *, void *, SIZE_T), void *cookie) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_open_mem, base, size, flags, unmap,
+ cookie);
+ if (base && size)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, base, size);
+ struct __sanitizer_cdbr *cdbr =
+ REAL(cdbr_open_mem)(base, size, flags, unmap, cookie);
+ if (cdbr)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbr, sizeof(*cdbr));
+ return cdbr;
+}
+
+INTERCEPTOR(u32, cdbr_entries, struct __sanitizer_cdbr *cdbr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_entries, cdbr);
+ if (cdbr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
+ return REAL(cdbr_entries)(cdbr);
+}
+
+INTERCEPTOR(int, cdbr_get, struct __sanitizer_cdbr *cdbr, u32 index,
+ const void **data, SIZE_T *datalen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_get, cdbr, index, data, datalen);
+ if (cdbr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
+ int ret = REAL(cdbr_get)(cdbr, index, data, datalen);
+ if (!ret) {
+ if (data)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
+ if (datalen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
+ if (data && datalen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
+ }
+ return ret;
+}
+
+INTERCEPTOR(int, cdbr_find, struct __sanitizer_cdbr *cdbr, const void *key,
+ SIZE_T keylen, const void **data, SIZE_T *datalen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_find, cdbr, key, keylen, data, datalen);
+ if (cdbr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
+ if (key)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
+ int ret = REAL(cdbr_find)(cdbr, key, keylen, data, datalen);
+ if (!ret) {
+ if (data)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(*data));
+ if (datalen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datalen, sizeof(*datalen));
+ if (data && datalen)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *data, *datalen);
+ }
+ return ret;
+}
+
+INTERCEPTOR(void, cdbr_close, struct __sanitizer_cdbr *cdbr) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbr_close, cdbr);
+ if (cdbr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbr, sizeof(*cdbr));
+ REAL(cdbr_close)(cdbr);
+}
+
+INTERCEPTOR(struct __sanitizer_cdbw *, cdbw_open) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_open);
+ struct __sanitizer_cdbw *ret = REAL(cdbw_open)();
+ if (ret)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ret, sizeof(*ret));
+ return ret;
+}
+
+INTERCEPTOR(int, cdbw_put, struct __sanitizer_cdbw *cdbw, const void *key,
+ SIZE_T keylen, const void *data, SIZE_T datalen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put, cdbw, key, keylen, data, datalen);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (data && datalen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
+ if (key && keylen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
+ int ret = REAL(cdbw_put)(cdbw, key, keylen, data, datalen);
+ if (!ret && cdbw)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
+ return ret;
+}
+
+INTERCEPTOR(int, cdbw_put_data, struct __sanitizer_cdbw *cdbw, const void *data,
+ SIZE_T datalen, u32 *index) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_data, cdbw, data, datalen, index);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (data && datalen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, data, datalen);
+ int ret = REAL(cdbw_put_data)(cdbw, data, datalen, index);
+ if (!ret) {
+ if (index)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, index, sizeof(*index));
+ if (cdbw)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
+ }
+ return ret;
+}
+
+INTERCEPTOR(int, cdbw_put_key, struct __sanitizer_cdbw *cdbw, const void *key,
+ SIZE_T keylen, u32 index) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_put_key, cdbw, key, keylen, index);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (key && keylen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, key, keylen);
+ int ret = REAL(cdbw_put_key)(cdbw, key, keylen, index);
+ if (!ret && cdbw)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
+ return ret;
+}
+
+INTERCEPTOR(int, cdbw_output, struct __sanitizer_cdbw *cdbw, int output,
+ const char descr[16], u32 (*seedgen)(void)) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_output, cdbw, output, descr, seedgen);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, output);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (descr)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, descr, internal_strnlen(descr, 16));
+ if (seedgen)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, (void *)seedgen, sizeof(seedgen));
+ int ret = REAL(cdbw_output)(cdbw, output, descr, seedgen);
+ if (!ret) {
+ if (cdbw)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cdbw, sizeof(*cdbw));
+ if (output >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, output);
+ }
+ return ret;
+}
+
+INTERCEPTOR(void, cdbw_close, struct __sanitizer_cdbw *cdbw) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, cdbw_close, cdbw);
+ if (cdbw)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, cdbw, sizeof(*cdbw));
+ REAL(cdbw_close)(cdbw);
+}
+
+#define INIT_CDB \
+ COMMON_INTERCEPT_FUNCTION(cdbr_open); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_open_mem); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_entries); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_get); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_find); \
+ COMMON_INTERCEPT_FUNCTION(cdbr_close); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_open); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_put); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_put_data); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_put_key); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_output); \
+ COMMON_INTERCEPT_FUNCTION(cdbw_close)
+#else
+#define INIT_CDB
+#endif
+
static void InitializeCommonInterceptors() {
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map =
INIT_MD2;
INIT_SHA2;
INIT_VIS;
+ INIT_CDB;
INIT___PRINTF_CHK;
}
--- /dev/null
+// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s
+
+#include <sys/param.h>
+
+#include <sys/types.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <cdbr.h>
+#include <cdbw.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static char *name;
+
+const char data1[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+const char data2[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
+const char key1[] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27};
+const char key2[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37};
+
+void test_cdbw() {
+ uint32_t idx;
+
+ struct cdbw *cdbw = cdbw_open();
+ assert(cdbw);
+
+ int rv = cdbw_put_data(cdbw, data1, __arraycount(data1), &idx);
+ assert(!rv);
+
+ rv = cdbw_put_key(cdbw, key1, __arraycount(key1), idx);
+ assert(!rv);
+
+ rv = cdbw_put(cdbw, key2, __arraycount(key2), data2, __arraycount(data2));
+ assert(!rv);
+
+ name = strdup("/tmp/temp.XXXXXX");
+ assert(name);
+
+ name = mktemp(name);
+ assert(name);
+
+ int fd = open(name, O_RDWR | O_CREAT, 0644);
+ assert(fd != -1);
+
+ cdbw_output(cdbw, fd, "TEST1", cdbw_stable_seeder);
+
+ cdbw_close(cdbw);
+
+ rv = close(fd);
+ assert(rv != -1);
+}
+
+void test_cdbr1() {
+ struct cdbr *cdbr = cdbr_open(name, CDBR_DEFAULT);
+ assert(cdbr);
+
+ uint32_t idx = cdbr_entries(cdbr);
+ assert(idx > 0);
+ printf("entries: %" PRIu32 "\n", idx);
+
+ const void *data;
+ size_t data_len;
+ int rv = cdbr_get(cdbr, idx - 1, &data, &data_len);
+ assert(rv == 0);
+
+ printf("data: ");
+ for (size_t i = 0; i < data_len; i++)
+ printf("%02" PRIx8, ((uint8_t *)data)[i]);
+ printf("\n");
+
+ rv = cdbr_find(cdbr, key1, __arraycount(key1), &data, &data_len);
+
+ printf("data: ");
+ for (size_t i = 0; i < data_len; i++)
+ printf("%02" PRIx8, ((uint8_t *)data)[i]);
+ printf("\n");
+
+ cdbr_close(cdbr);
+}
+
+#define COOKIE ((void *)1)
+
+static void cdbr_unmap(void *cookie, void *base, size_t sz) {
+ assert(cookie == COOKIE);
+ int rv = munmap(base, sz);
+ assert(rv != -1);
+}
+
+void test_cdbr2() {
+ struct stat sb;
+
+ int fd = open(name, O_RDONLY);
+ assert(fd != -1);
+
+ int rv = fstat(fd, &sb);
+ assert(rv != -1);
+
+ size_t sz = sb.st_size;
+ assert(sz < SSIZE_MAX);
+
+ void *base = mmap(NULL, sz, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0);
+ assert(base != MAP_FAILED);
+
+ rv = close(fd);
+ assert(rv != -1);
+
+ struct cdbr *cdbr = cdbr_open_mem(base, sz, CDBR_DEFAULT, cdbr_unmap, COOKIE);
+ assert(cdbr);
+
+ printf("entries: %" PRIu32 "\n", cdbr_entries(cdbr));
+
+ cdbr_close(cdbr);
+}
+
+int main(void) {
+ printf("cdb\n");
+
+ test_cdbw();
+ test_cdbr1();
+ test_cdbr2();
+
+ // CHECK: cdb
+ // CHECK: entries: 2
+ // CHECK: data: 1011121314151617
+ // CHECK: data: 0001020304050607
+ // CHECK: entries: 2
+
+ return 0;
+}