1*7c3d14c8STreehugger Robot // RUN: %clangxx_msan -O0 %s -o %t && %run %t %p 2>&1 | FileCheck %s
2*7c3d14c8STreehugger Robot // RUN: %clangxx_msan -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %run %t %p 2>&1 | FileCheck %s
3*7c3d14c8STreehugger Robot // RUN: %clangxx_msan -O3 %s -o %t && %run %t %p 2>&1 | FileCheck %s
4*7c3d14c8STreehugger Robot
5*7c3d14c8STreehugger Robot #include <assert.h>
6*7c3d14c8STreehugger Robot #include <glob.h>
7*7c3d14c8STreehugger Robot #include <stdio.h>
8*7c3d14c8STreehugger Robot #include <stdlib.h>
9*7c3d14c8STreehugger Robot #include <string.h>
10*7c3d14c8STreehugger Robot #include <errno.h>
11*7c3d14c8STreehugger Robot
12*7c3d14c8STreehugger Robot #include <sys/stat.h>
13*7c3d14c8STreehugger Robot #include <sys/types.h>
14*7c3d14c8STreehugger Robot #include <dirent.h>
15*7c3d14c8STreehugger Robot #include <unistd.h>
16*7c3d14c8STreehugger Robot
17*7c3d14c8STreehugger Robot #include <sanitizer/msan_interface.h>
18*7c3d14c8STreehugger Robot
my_gl_closedir(void * dir)19*7c3d14c8STreehugger Robot static void my_gl_closedir(void *dir) {
20*7c3d14c8STreehugger Robot if (!dir)
21*7c3d14c8STreehugger Robot exit(1);
22*7c3d14c8STreehugger Robot closedir((DIR *)dir);
23*7c3d14c8STreehugger Robot }
24*7c3d14c8STreehugger Robot
my_gl_readdir(void * dir)25*7c3d14c8STreehugger Robot static struct dirent *my_gl_readdir(void *dir) {
26*7c3d14c8STreehugger Robot if (!dir)
27*7c3d14c8STreehugger Robot exit(1);
28*7c3d14c8STreehugger Robot struct dirent *d = readdir((DIR *)dir);
29*7c3d14c8STreehugger Robot if (d) __msan_poison(d, d->d_reclen); // hehe
30*7c3d14c8STreehugger Robot return d;
31*7c3d14c8STreehugger Robot }
32*7c3d14c8STreehugger Robot
my_gl_opendir(const char * s)33*7c3d14c8STreehugger Robot static void *my_gl_opendir(const char *s) {
34*7c3d14c8STreehugger Robot assert(__msan_test_shadow(s, strlen(s) + 1) == (size_t)-1);
35*7c3d14c8STreehugger Robot return opendir(s);
36*7c3d14c8STreehugger Robot }
37*7c3d14c8STreehugger Robot
my_gl_lstat(const char * s,struct stat * st)38*7c3d14c8STreehugger Robot static int my_gl_lstat(const char *s, struct stat *st) {
39*7c3d14c8STreehugger Robot assert(__msan_test_shadow(s, strlen(s) + 1) == (size_t)-1);
40*7c3d14c8STreehugger Robot if (!st)
41*7c3d14c8STreehugger Robot exit(1);
42*7c3d14c8STreehugger Robot return lstat(s, st);
43*7c3d14c8STreehugger Robot }
44*7c3d14c8STreehugger Robot
my_gl_stat(const char * s,struct stat * st)45*7c3d14c8STreehugger Robot static int my_gl_stat(const char *s, struct stat *st) {
46*7c3d14c8STreehugger Robot assert(__msan_test_shadow(s, strlen(s) + 1) == (size_t)-1);
47*7c3d14c8STreehugger Robot if (!st)
48*7c3d14c8STreehugger Robot exit(1);
49*7c3d14c8STreehugger Robot return lstat(s, st);
50*7c3d14c8STreehugger Robot }
51*7c3d14c8STreehugger Robot
main(int argc,char * argv[])52*7c3d14c8STreehugger Robot int main(int argc, char *argv[]) {
53*7c3d14c8STreehugger Robot assert(argc == 2);
54*7c3d14c8STreehugger Robot char buf[1024];
55*7c3d14c8STreehugger Robot snprintf(buf, sizeof(buf), "%s/%s", argv[1], "glob_test_root/*a");
56*7c3d14c8STreehugger Robot
57*7c3d14c8STreehugger Robot glob_t globbuf;
58*7c3d14c8STreehugger Robot globbuf.gl_closedir = my_gl_closedir;
59*7c3d14c8STreehugger Robot globbuf.gl_readdir = my_gl_readdir;
60*7c3d14c8STreehugger Robot globbuf.gl_opendir = my_gl_opendir;
61*7c3d14c8STreehugger Robot globbuf.gl_lstat = my_gl_lstat;
62*7c3d14c8STreehugger Robot globbuf.gl_stat = my_gl_stat;
63*7c3d14c8STreehugger Robot for (int i = 0; i < 10000; ++i) {
64*7c3d14c8STreehugger Robot int res = glob(buf, GLOB_ALTDIRFUNC | GLOB_MARK, 0, &globbuf);
65*7c3d14c8STreehugger Robot assert(res == 0);
66*7c3d14c8STreehugger Robot printf("%d %s\n", errno, strerror(errno));
67*7c3d14c8STreehugger Robot assert(globbuf.gl_pathc == 2);
68*7c3d14c8STreehugger Robot printf("%zu\n", strlen(globbuf.gl_pathv[0]));
69*7c3d14c8STreehugger Robot printf("%zu\n", strlen(globbuf.gl_pathv[1]));
70*7c3d14c8STreehugger Robot __msan_poison(globbuf.gl_pathv[0], strlen(globbuf.gl_pathv[0]) + 1);
71*7c3d14c8STreehugger Robot __msan_poison(globbuf.gl_pathv[1], strlen(globbuf.gl_pathv[1]) + 1);
72*7c3d14c8STreehugger Robot globfree(&globbuf);
73*7c3d14c8STreehugger Robot }
74*7c3d14c8STreehugger Robot
75*7c3d14c8STreehugger Robot printf("PASS\n");
76*7c3d14c8STreehugger Robot // CHECK: PASS
77*7c3d14c8STreehugger Robot return 0;
78*7c3d14c8STreehugger Robot }
79