libmicrohttpd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [libmicrohttpd] Issue on receiving very long URI


From: Christian Grothoff
Subject: Re: [libmicrohttpd] Issue on receiving very long URI
Date: Wed, 19 Aug 2020 09:51:57 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.11.0

Dear Shikha,

I'm not sure how this can happen, as the function specifically first
computes the available space in the pool before making the allocation
request.

Could you please check if the

if (pool->pos == ROUND_TO_ALIGN (old_offset + old_size))

condition in memorypool.c::MHD_pool_reallocate() was 'true' as one would
expect? Overall it would be good to know which path is taken through
MHD_pool_reallocate() and/or what the various variables ended up being
when 'NULL' was returned. I've looked at the code for a while now, but
could not find anything wrong :-(.

So please help; providing a failing test would also be great.

I have adjusted the code to 'assert' properly if the function
unexpectedly returns NULL. Alas, that'll just convert the
NULL-dereferencing into an abort().

Happy hacking!

Christian

On 8/19/20 9:25 AM, Shikha Sharma wrote:
> Hi
> 
> I have observed a crash in MHD after using very long URI. In function
> 
> int
> try_grow_read_buffer (struct MHD_Connection *connection)
> {
>     size_t new_size;
>   size_t avail_size;
> 
>   avail_size = MHD_pool_get_free (connection->pool);
>   if (0 == avail_size)
>     return false; /* No more space available */
>   if (0 == connection->read_buffer_size)
>     new_size = avail_size / 2; /* Use half of available buffer for
> reading */
>   else
>     {
>       size_t grow_size;
> 
>       grow_size = avail_size / 8;
>       if (MHD_BUF_INC_SIZE > grow_size)
>       { /* Shortage of space */
>           /* Shortage of space, but grow is mandatory */
>           static const size_t small_inc = MHD_BUF_INC_SIZE / 8;
>           if (small_inc < avail_size)
>               grow_size = small_inc;
>           else
>               grow_size = avail_size;
>       }
>       new_size = connection->read_buffer_size + grow_size;
>     }
>   /* we can actually grow the buffer, do it! */
>   connection->read_buffer = MHD_pool_reallocate (connection->pool,
> connection->read_buffer,
> connection->read_buffer_size,
>                                                  new_size);
>   mhd_assert (NULL != connection->read_buffer);
>   connection->read_buffer_size = new_size;
>   return MHD_YES;
> }
> 
> 
> In my scenario, MHD_pool_reallocate returns NULL as it can not
> reallocate the memory. Thus connection->read_buffer is set to NULL and
> the function returns MHD_YES as if it was able to grow the buffer.
> 
> The next access to connection->read_buffer leads to crash.
> 
> 
> Debug trace for MHD_pool_reallocate returning NULL :
> 
> Breakpoint 2, MHD_pool_reallocate (pool=0x7fffa0008d90,
> old=0x7fffa0000c70, old_size=23164, new_size=new_size@entry=24364) at
> memorypool.c:252
> 252    {
> (gdb) p *pool
> $88 = {memory = 0x7fffa0000c70 "GET
> /q/init-req/val1/callingParty/316543216/hostid/bfx1/SessionId/123/calledParty/1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066"...,
> size = 32768, pos = 23168, end = 32768, is_mmap = 0}
> (gdb) n
> 256      asize = ROUND_TO_ALIGN (new_size);
> (gdb)
> 257      if ( (0 == asize) &&
> (gdb)
> 260      if ( (pool->end < old_size) ||
> (gdb)
> 264      if ( (pool->pos >= old_size) &&
> (gdb)
> 265           (&pool->memory[pool->pos - old_size] == old) )
> (gdb)
> 264      if ( (pool->pos >= old_size) &&
> (gdb)
> 281      if (asize <= old_size)
> (gdb)
> 283      if ((pool->pos + asize >= pool->pos) &&
> (gdb)
> 297    }
> (gdb)
> 259        return NULL; /* new_size too close to SIZE_MAX */
> (gdb)
> 297    }
> 
> The functionality of try_grow_read_buffer was changed and the snippet
> above is latest. In the old functionality:
> 
> buf = MHD_pool_reallocate (connection->pool,
>                              connection->read_buffer,
>                              connection->read_buffer_size,
>                              new_size);
>   if (NULL == buf)
>     return MHD_NO;
>   /* we can actually grow the buffer, do it! */
>   connection->read_buffer = buf;
>   connection->read_buffer_size = new_size;
>   return MHD_YES;
> 
> 
> which returns MHD_NO in case reallocation fails.
> 
> Thanks & Regards,
> 
> Shikha
> 
> 
> 

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]