segfault in vfscanf(3): clang and __restrict usage

From: Jean-Sébastien Pédron <dumbbell_at_FreeBSD.org>
Date: Tue, 24 Apr 2012 21:49:29 +0200
-----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-----

Received on Tue Apr 24 2012 - 17:49:32 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:26 UTC