<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - common glob interceptor doesn't handle GLOB_DOFFS correctly"
href="https://bugs.llvm.org/show_bug.cgi?id=40822">40822</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>common glob interceptor doesn't handle GLOB_DOFFS correctly
</td>
</tr>
<tr>
<th>Product</th>
<td>compiler-rt
</td>
</tr>
<tr>
<th>Version</th>
<td>6.0
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>asan
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>adembo@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>It looks like unpoison_glob_t doesn't properly account for GLOB_DOOFFS when
iterating over the glob results. By not adding pglob->gl_offs to the iteration
index, it ends up calling strlen on a null pointer.
Here's what the manpage for glob has to say about GLOB_DOOFFS:
GLOB_DOOFFS
Reserve pglob->gl_offs slots at the beginning of the list of
strings in pglob->pathv. The reserved slots contain null pointers.
I found this while trying to reproduce an old memory leak in libgssapi-krb5
(<a href="http://krbdev.mit.edu/rt/Ticket/Display.html?id=7981">http://krbdev.mit.edu/rt/Ticket/Display.html?id=7981</a>). At one time, the
library called glob with GLOB_DOOFFS (it doesn't any more).
$ cat test.c
#include <fcntl.h>
#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
int fd = creat("foo", S_IRWXU | S_IRWXG | S_IRWXO);
if (fd == -1) {
perror("creat");
return 1;
}
int rc = close(fd);
if (rc) {
perror("close");
return rc;
}
glob_t globbuf;
memset(&globbuf, 0, sizeof(globbuf));
int flags = 0;
#ifdef TEST_DOOFFS
globbuf.gl_offs = 1;
flags |= GLOB_DOOFFS;
#endif
rc = glob("foo", flags, NULL, &globbuf);
if (rc) {
perror("glob");
globfree(&globbuf);
return rc;
}
for (int i = 0; i < globbuf.gl_pathc; i++) {
int index = i;
#ifdef TEST_DOOFFS
index += globbuf.gl_offs;
#endif
printf("%s\n", globbuf.gl_pathv[index]);
}
globfree(&globbuf);
return 0;
}
$ clang -g -o test test.c && ./test
foo
$ clang -g -o test -DTEST_DOOFFS=1 test.c && ./test
foo
$ clang -fsanitize=address -g -o test test.c && ./test
foo
$ clang -fsanitize=address -g -o test -DTEST_DOOFFS=1 test.c && ./test
AddressSanitizer:DEADLYSIGNAL
=================================================================
==28548==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc
0x7f39228a85a1 bp 0x7ffc5b5f9110 sp 0x7ffc5b5f8888 T0)
==28548==The signal is caused by a READ memory access.
==28548==Hint: address points to the zero page.
#0 0x7f39228a85a0
/build/glibc-OTsEL5/glibc-2.27/string/../sysdeps/x86_64/multiarch/strlen-avx2.S:59
#1 0x45d83b in unpoison_glob_t(void*, __sanitizer::__sanitizer_glob_t*)
(/tmp/test+0x45d83b)
#2 0x45e3d2 in glob (/tmp/test+0x45e3d2)
#3 0x512422 in main /tmp/test.c:28:8
#4 0x7f392273bb96 in __libc_start_main
/build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#5 0x419e29 in _start (/tmp/test+0x419e29)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV
/build/glibc-OTsEL5/glibc-2.27/string/../sysdeps/x86_64/multiarch/strlen-avx2.S:59
==28548==ABORTING</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>