1 // RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1
2 // RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1
3 // RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1
14 #include <sanitizer/msan_interface.h>
16 // Do not depend on libattr headers.
18 #define ENOATTR ENODATA
22 ssize_t
listxattr(const char *path
, char *list
, size_t size
);
23 ssize_t
llistxattr(const char *path
, char *list
, size_t size
);
24 ssize_t
flistxattr(int fd
, char *list
, size_t size
);
25 ssize_t
getxattr(const char *path
, const char *name
, void *value
, size_t size
);
26 ssize_t
lgetxattr(const char *path
, const char *name
, void *value
, size_t size
);
27 ssize_t
fgetxattr(int fd
, const char *name
, void *value
, size_t size
);
33 // Life before closures...
34 ssize_t
listxattr_wrapper(char *buf
, size_t size
) {
35 return listxattr(g_path
, buf
, size
);
38 ssize_t
llistxattr_wrapper(char *buf
, size_t size
) {
39 return llistxattr(g_path
, buf
, size
);
42 ssize_t
flistxattr_wrapper(char *buf
, size_t size
) {
43 return flistxattr(g_fd
, buf
, size
);
46 ssize_t
getxattr_wrapper(const char *name
, char *buf
, size_t size
) {
47 return getxattr(g_path
, name
, buf
, size
);
50 ssize_t
lgetxattr_wrapper(const char *name
, char *buf
, size_t size
) {
51 return lgetxattr(g_path
, name
, buf
, size
);
54 ssize_t
fgetxattr_wrapper(const char *name
, char *buf
, size_t size
) {
55 return fgetxattr(g_fd
, name
, buf
, size
);
58 size_t test_list(ssize_t
fun(char*, size_t), char **buf
) {
61 *buf
= (char *)malloc(buf_size
);
62 assert(__msan_test_shadow(*buf
, buf_size
) != -1);
63 ssize_t res
= fun(*buf
, buf_size
);
65 assert(__msan_test_shadow(*buf
, buf_size
) == res
);
68 if (errno
== ENOTSUP
) {
69 printf("Extended attributes are disabled. *xattr test is a no-op.\n");
72 assert(errno
== ERANGE
);
78 // True means success. False means result inconclusive because we don't have
79 // access to this attribute.
80 bool test_get_single_attr(ssize_t
fun(const char *, char *, size_t),
81 const char *attr_name
) {
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
);
89 assert(__msan_test_shadow(buf
, buf_size
) == res
);
93 if (errno
== ENOTSUP
) {
94 printf("Extended attributes are disabled. *xattr test is a no-op.\n");
99 assert(errno
== ERANGE
);
105 void 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 are
108 // 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_* interceptors
114 __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
]))
119 printf("*xattr test could not access any attributes.\n");
122 // TODO: set some attributes before trying to retrieve them with *getxattr.
123 // Currently the list is empty, so *getxattr is not tested.
124 int main(int argc
, char *argv
[]) {
126 snprintf(g_path
, sizeof(g_path
), "%s/%s", argv
[1], "xattr_test_root/a");
128 g_fd
= open(g_path
, O_RDONLY
);
132 size_t attr_list_size
;
133 attr_list_size
= test_list(listxattr_wrapper
, &attr_list
);
135 attr_list_size
= test_list(llistxattr_wrapper
, &attr_list
);
137 attr_list_size
= test_list(flistxattr_wrapper
, &attr_list
);
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
);