Core: Avoid memcpy from NULL

Maxim Dounin mdounin at mdounin.ru
Sat Dec 16 04:15:57 UTC 2023


Hello!

On Fri, Dec 15, 2023 at 03:46:19PM +0100, Dipl. Ing. Sergey Brester via nginx-devel wrote:

> Enclosed few thoughts to the subject:
> 
> - since it is very rare situation that one needs only a memcpy without 
> to know whether previous alloc may fail
>    (e. g. some of pointers were NULL), me too thinks that the caller 
> should be responsible for the check.
>    So I would not extend ngx_memcpy or ngx_cpymem in that way.

That's not about failed allocations, it's about ability to work 
with empty strings which aren't explicitly set to something other 
than { 0, NULL }.  And you may refer to Vladimir's patch I've 
referenced to find out what it means in terms of the "caller 
should be responsible" approach even without trying to look into 
places not explicitly reported by the UB sanitizer.

https://mailman.nginx.org/pipermail/nginx-devel/2023-October/PX7VH5A273NLUGSYC7DR2AZRU75CIQ3Q.html
https://mailman.nginx.org/pipermail/nginx-devel/2023-December/DCGUEGEFS6TSVIWNEWUEZO3FZMR6ESYZ.html

> - rewrite of `ngx_memcpy` define like here:
>    ```
>    + #define ngx_memcpy(dst, src, n) (void) ((n) == 0 ? (dst) : 
> memcpy(dst, src, n))
>    ```
>    may introduce a regression or compat issues, e. g. fully functioning 
> codes like that may become broken hereafter:
>    ```
>    ngx_memcpy(dst, src, ++len); // because n would be incremented twice 
> in the macro now
>    ```
>    Sure, `ngx_cpymem` has also the same issue, but it had that already 
> before the "fix"...
>    Anyway, I'm always against of such macros (no matter with or without 
> check it would be better as an inline function instead).

In general macro definitions in nginx are used everywhere for 
efficiency reasons, and macro definitions usually aren't safe.  
While some might prefer other approaches, writing code like 
"ngx_memcpy(dst, src, ++len)" in nginx is just wrong, and 
shouldn't be trusted to work, much like it won't work with 
"ngx_cpymem(dst, src, ++len)".

I'm not exactly against using inline functions here, but the 
particular argument is at most very weak. 

> My conclusion:
>    a fix of affected places invoking `ngx_memcpy` and `ngx_cpymem`, and 
> possibly an assert in `ngx_memcpy`
>    and `ngx_cpymem` would be fully enough, in my opinion.

Well, thank you for your opinion, appreciated.  I don't think this 
approach is going to work though, see my review of Vladimir's 
patch.

Ideally, I would prefer this to be fixed in the C standard (and 
GCC).  But given this is not a likely option, and there is a 
constant stream of reports "hey, UB sanitizer reports about 
memcpy(dst, NULL, 0) in nginx" we might consider actually 
silencing this by introducing appropriate checks at the interface 
level.

-- 
Maxim Dounin
http://mdounin.ru/


More information about the nginx-devel mailing list