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
  This message is in MIME format.  The first part should be readable text,
  while the remaining parts are likely unreadable without MIME-aware tools.

---559023410-570397931-1232130795=:18030
Content-Type: TEXT/PLAIN; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

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 =E9crit :
>>> 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) !=3D 0) {
>>>                 o_errno =3D 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=20
implicitly assumed to return `int'.  This "feature" was widely used in the=
=20
early days of C and so continues to be accepted by compilers, and gcc by=20
default doesn't warn about it.

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

Since running on amd64 I've seen a lot of bugs where people carelessly=20
assume (perhaps without noticing) that ints and pointers are practically=20
interchangeable, which works on x86 and the like but breaks on amd64.=20
Variadic functions are special offenders because the compiler can't do=20
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);

--=20

Nate Eldredge
neldredge@math.ucsd.edu
---559023410-570397931-1232130795=:18030--



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