diff options
Diffstat (limited to 'test/msan/Linux/xattr.cc')
-rw-r--r-- | test/msan/Linux/xattr.cc | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/test/msan/Linux/xattr.cc b/test/msan/Linux/xattr.cc new file mode 100644 index 000000000000..1beba117d574 --- /dev/null +++ b/test/msan/Linux/xattr.cc @@ -0,0 +1,145 @@ +// RUN: %clangxx_msan -m64 -O0 %s -o %t && %run %t %p 2>&1 +// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 +// RUN: %clangxx_msan -m64 -O3 %s -o %t && %run %t %p 2>&1 + +#include <argz.h> +#include <assert.h> +#include <sys/types.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sanitizer/msan_interface.h> + +// Do not depend on libattr headers. +#ifndef ENOATTR +#define ENOATTR ENODATA +#endif + +extern "C" { +ssize_t listxattr(const char *path, char *list, size_t size); +ssize_t llistxattr(const char *path, char *list, size_t size); +ssize_t flistxattr(int fd, char *list, size_t size); +ssize_t getxattr(const char *path, const char *name, void *value, size_t size); +ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size); +ssize_t fgetxattr(int fd, const char *name, void *value, size_t size); +} + +char g_path[1024]; +int g_fd; + +// Life before closures... +ssize_t listxattr_wrapper(char *buf, size_t size) { + return listxattr(g_path, buf, size); +} + +ssize_t llistxattr_wrapper(char *buf, size_t size) { + return llistxattr(g_path, buf, size); +} + +ssize_t flistxattr_wrapper(char *buf, size_t size) { + return flistxattr(g_fd, buf, size); +} + +ssize_t getxattr_wrapper(const char *name, char *buf, size_t size) { + return getxattr(g_path, name, buf, size); +} + +ssize_t lgetxattr_wrapper(const char *name, char *buf, size_t size) { + return lgetxattr(g_path, name, buf, size); +} + +ssize_t fgetxattr_wrapper(const char *name, char *buf, size_t size) { + return fgetxattr(g_fd, name, buf, size); +} + +size_t test_list(ssize_t fun(char*, size_t), char **buf) { + int buf_size = 1024; + while (true) { + *buf = (char *)malloc(buf_size); + assert(__msan_test_shadow(*buf, buf_size) != -1); + ssize_t res = fun(*buf, buf_size); + if (res >= 0) { + assert(__msan_test_shadow(*buf, buf_size) == res); + return res; + } + if (errno == ENOTSUP) { + printf("Extended attributes are disabled. *xattr test is a no-op.\n"); + exit(0); + } + assert(errno == ERANGE); + free(*buf); + buf_size *= 2; + } +} + +// True means success. False means result inconclusive because we don't have +// access to this attribute. +bool test_get_single_attr(ssize_t fun(const char *, char *, size_t), + const char *attr_name) { + char *buf; + int buf_size = 1024; + while (true) { + buf = (char *)malloc(buf_size); + assert(__msan_test_shadow(buf, buf_size) != -1); + ssize_t res = fun(attr_name, buf, buf_size); + if (res >= 0) { + assert(__msan_test_shadow(buf, buf_size) == res); + free(buf); + return true; + } + if (errno == ENOTSUP) { + printf("Extended attributes are disabled. *xattr test is a no-op.\n"); + exit(0); + } + if (errno == ENOATTR) + return false; + assert(errno == ERANGE); + free(buf); + buf_size *= 2; + } +} + +void test_get(ssize_t fun(const char *, char *, size_t), const char *attr_list, + size_t attr_list_size) { + // Try every attribute, until we see one we can access. Attribute names are + // null-separated strings in attr_list. + size_t attr_list_len = argz_count(attr_list, attr_list_size); + size_t argv_size = (attr_list_len + 1) * sizeof(char *); + char **attrs = (char **)malloc(argv_size); + argz_extract(attr_list, attr_list_size, attrs); + // TODO(smatveev): we need proper argz_* interceptors + __msan_unpoison(attrs, argv_size); + for (size_t i = 0; (i < attr_list_len) && attrs[i]; i++) { + if (test_get_single_attr(fun, attrs[i])) + return; + } + printf("*xattr test could not access any attributes.\n"); +} + +// TODO: set some attributes before trying to retrieve them with *getxattr. +// Currently the list is empty, so *getxattr is not tested. +int main(int argc, char *argv[]) { + assert(argc == 2); + snprintf(g_path, sizeof(g_path), "%s/%s", argv[1], "xattr_test_root/a"); + + g_fd = open(g_path, O_RDONLY); + assert(g_fd); + + char *attr_list; + size_t attr_list_size; + attr_list_size = test_list(listxattr_wrapper, &attr_list); + free(attr_list); + attr_list_size = test_list(llistxattr_wrapper, &attr_list); + free(attr_list); + attr_list_size = test_list(flistxattr_wrapper, &attr_list); + + test_get(getxattr_wrapper, attr_list, attr_list_size); + test_get(lgetxattr_wrapper, attr_list, attr_list_size); + test_get(fgetxattr_wrapper, attr_list, attr_list_size); + + free(attr_list); + return 0; +} |