segfault in vfscanf(3): clang and __restrict usage
Jean-Sébastien Pédron
dumbbell at FreeBSD.org
Tue Apr 24 19:49:32 UTC 2012
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi everyone,
vfscanf(3) in HEAD (r234606) segfaults when compiled with clang. For
instance, here is a call made in cmake which crashes:
fscanf(f, "%*[^\n]\n");
The same libc, compiled with GCC, doesn't segfault.
When it encounters a character class, __svfscanf() calls convert_ccl():
static const int suppress;
#define SUPPRESS_PTR ((void *)&suppress)
static __inline int
convert_ccl(FILE *fp, char * __restrict p, [...])
{
[...]
if (p == SUPPRESS_PTR) {
[...]
} else {
[...]
}
[...]
}
In this case, there's no argument following the format string, and
convert_ccl is called with p = SUPPRESS_PTR. Therefore, we should
enter the if{} block. But when compiled with clang, we enter the
else{} block (causing the segfault).
I made a small program that shows the problem (attached): it seems to
be related to the __restrict qualifier.
Compiled with GCC:
./ptr-comp
p=0x600ac8 vs. SUPPRESS_PTR=0x600ac8
p == SUPPRESS_PTR
Compiled with clang:
./ptr-comp
p=0x4007dc vs. SUPPRESS_PTR=0x4007dc
p != SUPPRESS_PTR -> WRONG
- From what I understand about __restrict, it indicates that the pointer
is the only one pointing to a resource. In vfscanf.c, "suppress" may
be pointed by several pointers at a time, so I think __restrict here
is incorrect. But I'm really not sure I got it right. And I don't know
either if clang behavior is expected.
What do you think?
- --
Jean-Sébastien Pédron
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (FreeBSD)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk+XA8kACgkQa+xGJsFYOlOt9wCffUwQ344hfanDzU27wdgW5C+t
4fYAoKPh26OW/ge+VbLaOMTT/YtUYOwM
=OblW
-----END PGP SIGNATURE-----
-------------- next part --------------
#include <stdio.h>
static const int suppress;
#define SUPPRESS_PTR ((void *)&suppress)
void
func(char * __restrict p)
{
printf("p=%p vs. SUPPRESS_PTR=%p\n", p, SUPPRESS_PTR);
if (p == SUPPRESS_PTR)
printf("p == SUPPRESS_PTR\n");
else
printf("p != SUPPRESS_PTR -> WRONG\n");
}
int
main(int argc, char *argv [])
{
char *p;
p = SUPPRESS_PTR;
func(p);
return (0);
}
-------------- next part --------------
PROG = ptr-comp
.include <bsd.prog.mk>
More information about the freebsd-current
mailing list