> On 28 Feb 2024, at 05:21, Piotr Sikora via nginx-devel 
> <nginx-devel@nginx.org> wrote:
> 
> # HG changeset patch
> # User Piotr Sikora <pi...@aviatrix.com>
> # Date 1708977626 0
> #      Mon Feb 26 20:00:26 2024 +0000
> # Branch patch007
> # Node ID 5584232259d28489efba149f2f5ae730691ff0d4
> # Parent  03e5549976765912818120e11f6b08410a2af6a9
> Core: fix conversion of IPv4-mapped IPv6 addresses.
> 
> Found with UndefinedBehaviorSanitizer (shift).

Hello, thanks for the patch.

The "shift" remark doesn't describe a problem in details.

What actually happens is:
- loading from "u_char", with integer promotion
- left shift by 24 to most significant bit 31

The latter cannot be represented in (signed) integer in popular
data type models: bit 31 gets to the integer type sign bit,
and is caught by UndefinedBehaviorSanitizer, e.g.:
| runtime error: left shift of 255 by 24 places cannot be represented in type 
'int'

The lvalue typically has an unsigned integer type of the same
size (POSIX states in_addr_t is equivalent to uint32_t, which
is of the same type as "unsigned int" in ILP32 and LP64).
Known compilers, such as GCC and Clang, represent intermediate
result used as a source for left shift in a wide register such that
it doesn't get truncated when storing it in the left value.
This makes objects don't change after adding an explicit cast,
comparing md5sum over them matches.

Notably, this differs from left-shifting signed integer
into the sign bit fixed in ad736705a744, where, as described
in the change, the left value is of the larger type width.

Still, I won't object to apply something similar to ad736705a744
in order to suppress such UndefinedBehaviorSanitizer reports.
They look valid, although seemingly innocent.

> 
> Signed-off-by: Piotr Sikora <pi...@aviatrix.com>
> 
> diff -r 03e554997676 -r 5584232259d2 src/core/ngx_inet.c
> --- a/src/core/ngx_inet.c Mon Feb 26 20:00:23 2024 +0000
> +++ b/src/core/ngx_inet.c Mon Feb 26 20:00:26 2024 +0000
> @@ -507,10 +507,10 @@
> 
>            p = inaddr6->s6_addr;
> 
> -            inaddr = p[12] << 24;
> -            inaddr += p[13] << 16;
> -            inaddr += p[14] << 8;
> -            inaddr += p[15];
> +            inaddr = (in_addr_t) p[12] << 24;
> +            inaddr += (in_addr_t) p[13] << 16;
> +            inaddr += (in_addr_t) p[14] << 8;
> +            inaddr += (in_addr_t) p[15];
> 
>            inaddr = htonl(inaddr);
>        }
> diff -r 03e554997676 -r 5584232259d2 src/http/modules/ngx_http_access_module.c
> --- a/src/http/modules/ngx_http_access_module.c Mon Feb 26 20:00:23 2024 +0000
> +++ b/src/http/modules/ngx_http_access_module.c Mon Feb 26 20:00:26 2024 +0000
> @@ -148,10 +148,10 @@
>        p = sin6->sin6_addr.s6_addr;
> 
>        if (alcf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
> -            addr = p[12] << 24;
> -            addr += p[13] << 16;
> -            addr += p[14] << 8;
> -            addr += p[15];
> +            addr = (in_addr_t) p[12] << 24;
> +            addr += (in_addr_t) p[13] << 16;
> +            addr += (in_addr_t) p[14] << 8;
> +            addr += (in_addr_t) p[15];
>            return ngx_http_access_inet(r, alcf, htonl(addr));
>        }
> 
> diff -r 03e554997676 -r 5584232259d2 src/http/modules/ngx_http_geo_module.c
> --- a/src/http/modules/ngx_http_geo_module.c Mon Feb 26 20:00:23 2024 +0000
> +++ b/src/http/modules/ngx_http_geo_module.c Mon Feb 26 20:00:26 2024 +0000
> @@ -199,10 +199,10 @@
>        p = inaddr6->s6_addr;
> 
>        if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
> -            inaddr = p[12] << 24;
> -            inaddr += p[13] << 16;
> -            inaddr += p[14] << 8;
> -            inaddr += p[15];
> +            inaddr = (in_addr_t) p[12] << 24;
> +            inaddr += (in_addr_t) p[13] << 16;
> +            inaddr += (in_addr_t) p[14] << 8;
> +            inaddr += (in_addr_t) p[15];
> 
>            vv = (ngx_http_variable_value_t *)
>                      ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
> @@ -272,10 +272,10 @@
>            if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
>                p = inaddr6->s6_addr;
> 
> -                inaddr = p[12] << 24;
> -                inaddr += p[13] << 16;
> -                inaddr += p[14] << 8;
> -                inaddr += p[15];
> +                inaddr = (in_addr_t) p[12] << 24;
> +                inaddr += (in_addr_t) p[13] << 16;
> +                inaddr += (in_addr_t) p[14] << 8;
> +                inaddr += (in_addr_t) p[15];
> 
>            } else {
>                inaddr = INADDR_NONE;
> diff -r 03e554997676 -r 5584232259d2 src/http/modules/ngx_http_geoip_module.c
> --- a/src/http/modules/ngx_http_geoip_module.c Mon Feb 26 20:00:23 2024 +0000
> +++ b/src/http/modules/ngx_http_geoip_module.c Mon Feb 26 20:00:26 2024 +0000
> @@ -266,10 +266,10 @@
>        if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
>            p = inaddr6->s6_addr;
> 
> -            inaddr = p[12] << 24;
> -            inaddr += p[13] << 16;
> -            inaddr += p[14] << 8;
> -            inaddr += p[15];
> +            inaddr = (in_addr_t) p[12] << 24;
> +            inaddr += (in_addr_t) p[13] << 16;
> +            inaddr += (in_addr_t) p[14] << 8;
> +            inaddr += (in_addr_t) p[15];
> 
>            return inaddr;
>        }
> diff -r 03e554997676 -r 5584232259d2 src/stream/ngx_stream_access_module.c
> --- a/src/stream/ngx_stream_access_module.c Mon Feb 26 20:00:23 2024 +0000
> +++ b/src/stream/ngx_stream_access_module.c Mon Feb 26 20:00:26 2024 +0000
> @@ -144,10 +144,10 @@
>        p = sin6->sin6_addr.s6_addr;
> 
>        if (ascf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
> -            addr = p[12] << 24;
> -            addr += p[13] << 16;
> -            addr += p[14] << 8;
> -            addr += p[15];
> +            addr = (in_addr_t) p[12] << 24;
> +            addr += (in_addr_t) p[13] << 16;
> +            addr += (in_addr_t) p[14] << 8;
> +            addr += (in_addr_t) p[15];
>            return ngx_stream_access_inet(s, ascf, htonl(addr));
>        }
> 
> diff -r 03e554997676 -r 5584232259d2 src/stream/ngx_stream_geo_module.c
> --- a/src/stream/ngx_stream_geo_module.c Mon Feb 26 20:00:23 2024 +0000
> +++ b/src/stream/ngx_stream_geo_module.c Mon Feb 26 20:00:26 2024 +0000
> @@ -190,10 +190,10 @@
>        p = inaddr6->s6_addr;
> 
>        if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
> -            inaddr = p[12] << 24;
> -            inaddr += p[13] << 16;
> -            inaddr += p[14] << 8;
> -            inaddr += p[15];
> +            inaddr = (in_addr_t) p[12] << 24;
> +            inaddr += (in_addr_t) p[13] << 16;
> +            inaddr += (in_addr_t) p[14] << 8;
> +            inaddr += (in_addr_t) p[15];
> 
>            vv = (ngx_stream_variable_value_t *)
>                      ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
> @@ -263,10 +263,10 @@
>            if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
>                p = inaddr6->s6_addr;
> 
> -                inaddr = p[12] << 24;
> -                inaddr += p[13] << 16;
> -                inaddr += p[14] << 8;
> -                inaddr += p[15];
> +                inaddr = (in_addr_t) p[12] << 24;
> +                inaddr += (in_addr_t) p[13] << 16;
> +                inaddr += (in_addr_t) p[14] << 8;
> +                inaddr += (in_addr_t) p[15];
> 
>            } else {
>                inaddr = INADDR_NONE;
> diff -r 03e554997676 -r 5584232259d2 src/stream/ngx_stream_geoip_module.c
> --- a/src/stream/ngx_stream_geoip_module.c Mon Feb 26 20:00:23 2024 +0000
> +++ b/src/stream/ngx_stream_geoip_module.c Mon Feb 26 20:00:26 2024 +0000
> @@ -236,10 +236,10 @@
>        if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
>            p = inaddr6->s6_addr;
> 
> -            inaddr = p[12] << 24;
> -            inaddr += p[13] << 16;
> -            inaddr += p[14] << 8;
> -            inaddr += p[15];
> +            inaddr = (in_addr_t) p[12] << 24;
> +            inaddr += (in_addr_t) p[13] << 16;
> +            inaddr += (in_addr_t) p[14] << 8;
> +            inaddr += (in_addr_t) p[15];
> 
>            return inaddr;
>        }
> _______________________________________________
> nginx-devel mailing list
> nginx-devel@nginx.org
> https://mailman.nginx.org/mailman/listinfo/nginx-devel

-- 
Sergey Kandaurov
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to