On 02/14/2020 10:08 AM, Joe Orton wrote:
> I've been playing with UBSan[1] which catches undefined behaviour, found a 
> couple of interesting things so far.
> 
> One is with event, I messed with the line numbers but the error is:
> 
> event.c:3620:13: runtime error: null pointer passed as argument 2, which is 
> declared to never be null
> 
> from the memcpy() in this code: 
> https://github.com/apache/httpd/blob/trunk/server/mpm/event/event.c#L3619
> 
>         new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
>         memcpy(new_ptr, retained->idle_spawn_rate,
>                retained->mpm->num_buckets * sizeof(int));

I guess the above only does not crash because retained->mpm->num_buckets is 0 
at the same time.
But this is probably something we should not rely on with all memcpy 
implementations.

>         retained->idle_spawn_rate = new_ptr;
>         retained->mpm->max_buckets = new_max;
> 
> At startup it seems retained->idle_spawn_rate is NULL, and you can't 
> (shouldn't?!) memcpy() from NULL.  I am not sure what the right fix is 
> here, is that array supposed to be initialized to something other than 
> zero here, or somewhere else?  Not obvious if the loop below will 
> initialize it properly:

I think stuff is correctly initialized in the block starting at line 3624.

> 
> https://github.com/apache/httpd/blob/trunk/server/mpm/event/event.c#L3624
> 
> Is something like this correct?  (also this could use apr_pmemdup rather 
> than palloc+memcpy now I think about it)
> 
> --- a/server/mpm/event/event.c
> +++ b/server/mpm/event/event.c
> @@ -3615,9 +3615,15 @@ static int event_open_logs(apr_pool_t * p, apr_pool_t 
> * plog,
>          if (new_max < num_buckets) {
>              new_max = num_buckets;
>          }
> -        new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
> -        memcpy(new_ptr, retained->idle_spawn_rate,
> -               retained->mpm->num_buckets * sizeof(int));
> +        if (retained->idle_spawn_rate) {
> +            new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
> +            memcpy(new_ptr, retained->idle_spawn_rate,
> +                   retained->mpm->num_buckets * sizeof(int));
> +        }
> +        else {
> +            /* ### should initialize array to something other than 0?? */
> +            new_ptr = apr_pcalloc(ap_pglobal, new_max * sizeof(int));
> +        }

I guess there is no need for two cases here. We should only avoid the call to 
memcpy
if retained->idle_spawn_rate is NULL. The initialization happens then in the 
block starting
at line 3624.

Regards

RĂ¼diger

Reply via email to