1

While using the libmicrohttpd library, I came across an odd error when converting a string to const char * and calling MHD_create_response_from_buffer with it.

This causes the webpage response to come back badly malformed, occasionally displaying binary data and, a little more rarely, making the browser think it is a file and downloading it.

What makes this really odd is that the error does not show up if I send a regular const char, like const char *cstring = "this is a page"; only when I'm converting from a string to const char * like const char *cstring = page.c_str();

the Valgrind output:

==11105== Thread 2:
==11105== Syscall param socketcall.sendto(msg) points to unaddressable byte(s)
==11105==    at 0x617464B: send (send.c:31)
==11105==    by 0x565986F: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x565737D: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x565DA3C: MHD_run_from_select (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x565DC8A: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x565DDA1: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x876B0A3: start_thread (pthread_create.c:309)
==11105==    by 0x617362C: clone (clone.S:111)
==11105==  Address 0xe499448 is 24 bytes inside a block of size 56 free'd
==11105==    at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==11105==    by 0x401CA5: http_connect(void*, MHD_Connection*, char const*, char const*, char const*, char const*, unsigned long*, void**) (in /home/shpoople/projects/http/main)
==11105==    by 0x5656F70: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x5658427: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x565D988: MHD_run_from_select (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x565DC8A: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x565DDA1: ??? (in /usr/lib/x86_64-linux-gnu/libmicrohttpd.so.10.27.0)
==11105==    by 0x876B0A3: start_thread (pthread_create.c:309)
==11105==    by 0x617362C: clone (clone.S:111)
==11105==

And the function for sending the data (found at this page and only modified to use std::string):

static int send_page (struct MHD_Connection *connection, std::string page) {
    int ret;
    struct MHD_Response *response;
    const char* cstring = page.c_str();

    response = MHD_create_response_from_buffer (strlen (cstring), (void *) cstring, MHD_RESPMEM_PERSISTENT);

    if (!response) {
        return MHD_NO;
    }

    ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
    MHD_destroy_response (response);

    return ret;
}

2 Answers 2

3

Your parameter std::string page is a local variable. Its memory is freed when this function finishes.

On the other hand, the function MHD_run_from_select and related apparently run on a separate thread. When that thread tries to access a buffer, the memory of std::string page has already been freed.

You should make sure the buffer stays alive, either by allocating it differently or by blocking the major thread until you get the response.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the reply. The function has a flag for copying the buffer memory, MHD_RESPMEM_MUST_COPY
2

I seem to have solved it on my own. Sorry about asking an unnecessary question.

The problem was solved by changing the third argument on MHD_create_response_from_buffer from MHD_RESPMEM_PERSISTENT to MHD_RESPMEM_MUST_COPY

Again, sorry about that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.