146 lines · cpp
1// RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&12// RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&13// RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&14 5#include <argz.h>6#include <assert.h>7#include <sys/types.h>8#include <errno.h>9#include <fcntl.h>10#include <stdio.h>11#include <stdlib.h>12#include <string.h>13 14#include <sanitizer/msan_interface.h>15 16// Do not depend on libattr headers.17#ifndef ENOATTR18#define ENOATTR ENODATA19#endif20 21extern "C" {22ssize_t listxattr(const char *path, char *list, size_t size);23ssize_t llistxattr(const char *path, char *list, size_t size);24ssize_t flistxattr(int fd, char *list, size_t size);25ssize_t getxattr(const char *path, const char *name, void *value, size_t size);26ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size);27ssize_t fgetxattr(int fd, const char *name, void *value, size_t size);28}29 30char g_path[1024];31int g_fd;32 33// Life before closures...34ssize_t listxattr_wrapper(char *buf, size_t size) {35 return listxattr(g_path, buf, size);36}37 38ssize_t llistxattr_wrapper(char *buf, size_t size) {39 return llistxattr(g_path, buf, size);40}41 42ssize_t flistxattr_wrapper(char *buf, size_t size) {43 return flistxattr(g_fd, buf, size);44}45 46ssize_t getxattr_wrapper(const char *name, char *buf, size_t size) {47 return getxattr(g_path, name, buf, size);48}49 50ssize_t lgetxattr_wrapper(const char *name, char *buf, size_t size) {51 return lgetxattr(g_path, name, buf, size);52}53 54ssize_t fgetxattr_wrapper(const char *name, char *buf, size_t size) {55 return fgetxattr(g_fd, name, buf, size);56}57 58size_t test_list(ssize_t fun(char*, size_t), char **buf) {59 int buf_size = 1024;60 while (true) {61 *buf = (char *)malloc(buf_size);62 assert(__msan_test_shadow(*buf, buf_size) != -1);63 ssize_t res = fun(*buf, buf_size);64 if (res >= 0) {65 assert(__msan_test_shadow(*buf, buf_size) == res);66 return res;67 }68 if (errno == ENOTSUP) {69 printf("Extended attributes are disabled. *xattr test is a no-op.\n");70 exit(0);71 }72 assert(errno == ERANGE);73 free(*buf);74 buf_size *= 2;75 }76}77 78// True means success. False means result inconclusive because we don't have79// access to this attribute.80bool test_get_single_attr(ssize_t fun(const char *, char *, size_t),81 const char *attr_name) {82 char *buf;83 int buf_size = 1024;84 while (true) {85 buf = (char *)malloc(buf_size);86 assert(__msan_test_shadow(buf, buf_size) != -1);87 ssize_t res = fun(attr_name, buf, buf_size);88 if (res >= 0) {89 assert(__msan_test_shadow(buf, buf_size) == res);90 free(buf);91 return true;92 }93 if (errno == ENOTSUP) {94 printf("Extended attributes are disabled. *xattr test is a no-op.\n");95 exit(0);96 }97 if (errno == ENOATTR)98 return false;99 assert(errno == ERANGE);100 free(buf);101 buf_size *= 2;102 }103}104 105void test_get(ssize_t fun(const char *, char *, size_t), const char *attr_list,106 size_t attr_list_size) {107 // Try every attribute, until we see one we can access. Attribute names are108 // null-separated strings in attr_list.109 size_t attr_list_len = argz_count(attr_list, attr_list_size);110 size_t argv_size = (attr_list_len + 1) * sizeof(char *);111 char **attrs = (char **)malloc(argv_size);112 argz_extract(attr_list, attr_list_size, attrs);113 // TODO(smatveev): we need proper argz_* interceptors114 __msan_unpoison(attrs, argv_size);115 for (size_t i = 0; (i < attr_list_len) && attrs[i]; i++) {116 if (test_get_single_attr(fun, attrs[i]))117 return;118 }119 printf("*xattr test could not access any attributes.\n");120}121 122// TODO: set some attributes before trying to retrieve them with *getxattr.123// Currently the list is empty, so *getxattr is not tested.124int main(int argc, char *argv[]) {125 assert(argc == 2);126 snprintf(g_path, sizeof(g_path), "%s/%s", argv[1], "xattr_test_root/a");127 128 g_fd = open(g_path, O_RDONLY);129 assert(g_fd);130 131 char *attr_list;132 size_t attr_list_size;133 attr_list_size = test_list(listxattr_wrapper, &attr_list);134 free(attr_list);135 attr_list_size = test_list(llistxattr_wrapper, &attr_list);136 free(attr_list);137 attr_list_size = test_list(flistxattr_wrapper, &attr_list);138 139 test_get(getxattr_wrapper, attr_list, attr_list_size);140 test_get(lgetxattr_wrapper, attr_list, attr_list_size);141 test_get(fgetxattr_wrapper, attr_list, attr_list_size);142 143 free(attr_list);144 return 0;145}146