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