Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Jan 2009 10:33:15 -0800 (PST)
From:      Nate Eldredge <neldredge@math.ucsd.edu>
To:        Garrett Cooper <yanefbsd@gmail.com>
Cc:        Thierry Herbelot <thierry.herbelot@free.fr>, freebsd-hackers@freebsd.org, Christoph Mallon <christoph.mallon@gmx.de>
Subject:   Re: Confused by segfault with legitimate call to strerror(3) on amd64 / sysctl (3) setting `odd' errno's
Message-ID:  <Pine.GSO.4.64.0901161023030.18030@zeno.ucsd.edu>
In-Reply-To: <7d6fde3d0901161006r79f0cac4yf80c9c5079152b87@mail.gmail.com>
References:  <7d6fde3d0901160041n55466290l55f737d274a40895@mail.gmail.com> <49705FA2.2020605@gmx.de> <7d6fde3d0901160235o6aa1f096q11c5096b70f3577@mail.gmail.com> <200901161152.53478.thierry.herbelot@free.fr> <7d6fde3d0901161006r79f0cac4yf80c9c5079152b87@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

On Fri, 16 Jan 2009, Garrett Cooper wrote:

> On Fri, Jan 16, 2009 at 2:52 AM, Thierry Herbelot
> <thierry.herbelot@free.fr> wrote:
>> Le Friday 16 January 2009, Garrett Cooper a écrit :
>>> On Fri, Jan 16, 2009 at 2:21 AM, Christoph Mallon
>>>
>>> #include <errno.h>
>>> #include <stdio.h>
>>> #include <sys/stat.h>
>>>
>>> int
>>> main()
>>> {
>>>
>>>         struct stat sb;
>>>
>>>         int o_errno;
>>>
>>>         if (stat("/some/file/that/doesn't/exist", &sb) != 0) {
>>>                 o_errno = errno;
>>>                 printf("Errno: %d\n", errno);
>>>                 printf("%s\n", strerror(o_errno));
>>>         }
>>>
>>>         return 0;
>>>
>>> }
>>>
>> with this, it's better on an amd64/ RELENG_7 machine :
>>
>> % diff -ub badfile.c.ori badfile.c
>> --- badfile.c.ori       2009-01-16 11:49:44.778991057 +0100
>> +++ badfile.c   2009-01-16 11:49:03.470465677 +0100
>> @@ -1,6 +1,7 @@
>>  #include <errno.h>
>>  #include <stdio.h>
>>  #include <sys/stat.h>
>> +#include <string.h>
>>
>>  int
>>  main()
>>
>>        Cheers
>>
>>        TfH
>
> That's hilarious -- why does it pass though without issue on x86 though?
> -Garrett

As pointed out, when you don't have a declaration for strerror, it's 
implicitly assumed to return `int'.  This "feature" was widely used in the 
early days of C and so continues to be accepted by compilers, and gcc by 
default doesn't warn about it.

On x86, int and char * are the same size.  So even though the compiler 
thinks strerror is returning an int which is being passed to printf, the 
code it generates is the same as for a char *.  On amd64, int is 32 bits 
but char * is 64.  When the compiler thinks it's using int, it only keeps 
track of the lower 32 bits, and the upper 32 bits get zeroed.  So the 
pointer that printf receives has had its upper 32 bits zeroed, and no 
longer points where it should.  Hence segfault.

Since running on amd64 I've seen a lot of bugs where people carelessly 
assume (perhaps without noticing) that ints and pointers are practically 
interchangeable, which works on x86 and the like but breaks on amd64. 
Variadic functions are special offenders because the compiler can't do 
much type checking.

Pop quiz: which of the following statements is correct?

#include <stdlib.h>
#include <unistd.h>

execl("/bin/sh", "/bin/sh", 0);
execl("/bin/sh", "/bin/sh", NULL);

-- 

Nate Eldredge
neldredge@math.ucsd.edu

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.GSO.4.64.0901161023030.18030>