platform: use flexible array members for "NMPlatformIPAddress.address_ptr"/"NMPlatformIPRoute.network_ptr"

Try to workaround a coverity warning:

 30. NetworkManager-1.39.3/src/core/vpn/nm-vpn-connection.c:2000:
     overrun-buffer-val: Overrunning array "address.ax.address_ptr" of 1
     bytes by passing it to a function which accesses it at byte offset 3.
This commit is contained in:
Thomas Haller 2022-05-09 15:05:12 +02:00
parent d6e6443b86
commit a34bad8b52
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
3 changed files with 24 additions and 13 deletions

View file

@ -37,6 +37,13 @@ const void *const _NM_PTRARRAY_EMPTY[1] = {NULL};
const NMIPAddr nm_ip_addr_zero = {};
/* We use _nm_alignas(NMIPAddr). Ensure that this struct has the same
* alignment as in_addr_t and struct in6_addr. */
G_STATIC_ASSERT(_nm_alignof(NMIPAddr) == 4);
G_STATIC_ASSERT(_nm_alignof(in_addr_t) == 4);
G_STATIC_ASSERT(_nm_alignof(struct in_addr) == 4);
G_STATIC_ASSERT(_nm_alignof(struct in6_addr) == 4);
/* this initializes a struct in_addr/in6_addr and allows for untrusted
* arguments (like unsuitable @addr_family or @src_len). It's almost safe
* in the sense that it verifies input arguments strictly. Also, it

View file

@ -216,7 +216,7 @@ nm_ether_addr_equal(const NMEtherAddr *a, const NMEtherAddr *b)
typedef struct {
union {
guint8 addr_ptr[1];
guint8 addr_ptr[sizeof(struct in6_addr)];
in_addr_t addr4;
struct in_addr addr4_struct;
struct in6_addr addr6;

View file

@ -333,6 +333,9 @@ typedef enum {
* should be configured. */ \
bool a_force_commit : 1; \
\
/* Don't have a bitfield as last field in __NMPlatformIPAddress_COMMON. It would then
* be unclear how the following fields get merged. We could also use a zero bitfield,
* but instead we just have there the uint8 field. */ \
guint8 plen; \
;
@ -343,10 +346,7 @@ typedef enum {
**/
typedef struct {
__NMPlatformIPAddress_COMMON;
union {
guint8 address_ptr[1];
guint32 __dummy_for_32bit_alignment;
};
_nm_alignas(NMIPAddr) guint8 address_ptr[];
} NMPlatformIPAddress;
/**
@ -358,11 +358,15 @@ struct _NMPlatformIP4Address {
/* Whether the address is ready to be configured. By default, an address is, but this
* flag may indicate that the address is just for tracking purpose only, but the ACD
* state is not yet ready for the address to be configured. */
* state is not yet ready for the address to be configured.
*
* This bit fits actually in an alignment gap between __NMPlatformIPAddress_COMMON and
* "address" field. Usually "address" must be the first field after __NMPlatformIPAddress_COMMON,
* but there is a gap. We have a static assertion that checks this, so all is good. */
bool a_acd_not_ready : 1;
/* The local address IFA_LOCAL. */
in_addr_t address;
_nm_alignas(NMIPAddr) in_addr_t address;
/* The IFA_ADDRESS PTP peer address. This field is rather important, because
* it constitutes the identifier for the IPv4 address (e.g. you can add two
@ -390,7 +394,7 @@ struct _NMPlatformIP4Address {
**/
struct _NMPlatformIP6Address {
__NMPlatformIPAddress_COMMON;
struct in6_addr address;
_nm_alignas(NMIPAddr) struct in6_addr address;
struct in6_addr peer_address;
};
@ -526,16 +530,16 @@ typedef union {
*
* This is not the original type, if type_coerced is 0 then
* it means RTN_UNSPEC otherwise the type value is preserved.
* */ \
*/ \
/* Don't have a bitfield as last field in __NMPlatformIPAddress_COMMON. It would then
* be unclear how the following fields get merged. We could also use a zero bitfield,
* but instead we just have there the uint8 field. */ \
guint8 type_coerced; \
;
typedef struct {
__NMPlatformIPRoute_COMMON;
union {
guint8 network_ptr[1];
guint32 __dummy_for_32bit_alignment;
};
_nm_alignas(NMIPAddr) guint8 network_ptr[];
} NMPlatformIPRoute;
#define NM_PLATFORM_IP_ROUTE_CAST(route) \