Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Apr 2012 21:49:29 +0200
From:      =?ISO-8859-1?Q?Jean-S=E9bastien_P=E9dron?= <dumbbell@FreeBSD.org>
To:        freebsd-current@freebsd.org
Subject:   segfault in vfscanf(3): clang and __restrict usage
Message-ID:  <4F9703C9.8080503@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------090407000900020908050709
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit

-----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-----

--------------090407000900020908050709
Content-Type: text/plain; charset=UTF-8;
 name="ptr-comp.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="ptr-comp.c"

#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);
}

--------------090407000900020908050709
Content-Type: text/plain; charset=UTF-8;
 name="Makefile"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="Makefile"

PROG = ptr-comp

.include <bsd.prog.mk>

--------------090407000900020908050709--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4F9703C9.8080503>