On Fri, 16 Jan 2009, Garrett Cooper wrote:

On Fri, Jan 16, 2009 at 2:52 AM, Thierry Herbelot
<thierry.herbe...@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
neldre...@math.ucsd.edu
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to