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