This is somewhat ports related, but I decided to ask here before going
further with diff.

Well, we have Asterisk 1.6.2.14-rc1 going segfault:

#0  generic_http_callback (format=FORMAT_XML, remote_address=0x4001,
    uri=0x4001 <Address 0x4001 out of bounds>, method=205216842,
    params=0x20eb5bc00, status=0x2057b2c74, title=0x2057b2c78,
    contentlength=0x2057b2c84) at manager.c:4005
4005

#0  generic_http_callback (format=FORMAT_XML, remote_address=0x4001,
    uri=0x4001 <Address 0x4001 out of bounds>, method=205216842,
    params=0x20eb5bc00, status=0x2057b2c74, title=0x2057b2c78,
    contentlength=0x2057b2c84) at manager.c:4005
        buf = 0x208dd5000 <Address 0x208dd5000 out of bounds>
        l = 16384
        s = {session = 0x203382800, f = 0x2036d3440, fd = 245}
        session = (struct mansession_session *) 0x203382800
        ident = 390437576
        blastaway = 0
        v = (struct ast_variable *) 0x4000
        template = "/tmp/ast-http-U9afaz"
        out = (struct ast_str *) 0x207fd7800
        m = {hdrcount = 2, headers = {0x2057b2470 "Action: CoreShowChannels",
    0x2057b2450 "mansession_id: 17459ac8", 0x0 <repeats 126 times>}}
        x = 16385
        hdrlen = 0

Relevant lines are:

        if (s.f != NULL) {      /* have temporary output */
                char *buf;
                size_t l;

                if ((l = ftell(s.f))) {
                        if (MAP_FAILED == (buf = mmap(NULL, l + 1,
PROT_READ | PROT_WRITE, MAP_PRIVATE, s.fd, 0))) {
                                ast_log(LOG_WARNING, "mmap failed.
Manager output was not processed\n");
                        } else {
=>4005:                    buf[l] = '\0';
                                if (format == FORMAT_XML || format ==
FORMAT_HTML) {
                                        xml_translate(&out, buf,
params, format);
                                } else {
                                        ast_str_append(&out, 0, "%s", buf);
                                }
                                munmap(buf, l + 1);
                        }
                } else if (format == FORMAT_XML || format == FORMAT_HTML) {
                        xml_translate(&out, "", params, format);
                }
                fclose(s.f);
                s.f = NULL;
                s.fd = -1;
        }

So if ftell() returns value of l exactly at the end of file, accessing
l + 1 leads to segfault while mmaping l + 1 is ok, right?

On Wed, Nov 3, 2010 at 14:23, Otto Moerbeek <[email protected]> wrote:
> On Wed, Nov 03, 2010 at 01:12:20PM +0100, Otto Moerbeek wrote:
>
>> On Wed, Nov 03, 2010 at 01:18:51PM +0200, Alexey Suslikov wrote:
>>
>> > Hello t...@.
>> >
>> > On OpenBSD/amd64, doing something like
>> >     char *buf = mmap(NULL, len + 1, PROT_READ | PROT_WRITE,
>> > MAP_PRIVATE, some.fd, 0);
>> >     buf[len] = '\0';
>> > causes segfault on buf[len] = '\0' assignment if len = 16384.
>> >
>> > However doing
>> >     char *buf = mmap(NULL, len + 1, PROT_READ | PROT_WRITE,
>> > MAP_PRIVATE, some.fd, 0);
>> >     char *nbuf = malloc(len + 1);
>> >     memcpy(nbuf, buf, len);
>> >     nbuf[len] = '\0';
>> > does not lead to a crash.
>> >
>> > Is it expected behavior of mmap (alignment?) or usage of mmap is wrong?
>> >
>> > Thanks.
>> >
>> > Alexey
>>
>> This (complete!) program does not show the behahaviour. Please post a
>> complete testcase. Did you include sys/mman.h?
>
> BTW, accesses beyond the file do cause a segfault, and that is correct.
>
> Note that your firts case accesses buf[16384], while your memcpy does
> not access that address.
>
>        -Otto
>
>>
>> #include <sys/types.h>
>> #include <sys/mman.h>
>>
>> #include <err.h>
>> #include <fcntl.h>
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>>
>> int
>> main()
>> {
>>       int fd;
>>       char *buf;
>>       size_t len;
>>
>>       fd = open("file", O_RDWR, 0);
>>       if (fd == -1)
>>               err(1, NULL);
>>
>>       len = 16384;
>>       buf = mmap(NULL, len + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE,
>>           fd, (off_t)0);
>>       if (buf == MAP_FAILED)
>>               err(1, NULL);
>>       buf[len] = '\0';
>> }

Reply via email to