lib: cbprintf: fix ubsan errors in cbvprintf_package (take 2)

First approach had to be reverted because it did not pass tests.
Take 2 attempts to use uintptr_t instead of a pointer and cast it
to the expected pointer when necessary.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruściński 2024-10-11 15:48:59 +02:00 committed by Henrik Brix Andersen
parent adeeb10f4f
commit 0a54922ba7

View file

@ -242,10 +242,10 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags,
#define STR_POS_MASK BIT_MASK(7) #define STR_POS_MASK BIT_MASK(7)
/* Buffer offset abstraction for better code clarity. */ /* Buffer offset abstraction for better code clarity. */
#define BUF_OFFSET ((uintptr_t)buf - (uintptr_t)buf0) #define BUF_OFFSET (buf - (uintptr_t)buf0)
uint8_t *buf0 = packaged; /* buffer start (may be NULL) */ uint8_t *buf0 = packaged; /* buffer start (may be NULL) */
uint8_t *buf = buf0; /* current buffer position */ uintptr_t buf = (uintptr_t)buf0; /* current buffer position */
unsigned int size; /* current argument's size */ unsigned int size; /* current argument's size */
unsigned int align; /* current argument's required alignment */ unsigned int align; /* current argument's required alignment */
uint8_t str_ptr_pos[16]; /* string pointer positions */ uint8_t str_ptr_pos[16]; /* string pointer positions */
@ -355,7 +355,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags,
size = sizeof(int); size = sizeof(int);
/* align destination buffer location */ /* align destination buffer location */
buf = (void *)ROUND_UP(buf, align); buf = ROUND_UP(buf, align);
/* make sure the data fits */ /* make sure the data fits */
if (buf0 != NULL && BUF_OFFSET + size > len) { if (buf0 != NULL && BUF_OFFSET + size > len) {
@ -430,14 +430,14 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags,
} }
/* align destination buffer location */ /* align destination buffer location */
buf = (void *) ROUND_UP(buf, align); buf = ROUND_UP(buf, align);
if (buf0 != NULL) { if (buf0 != NULL) {
/* make sure it fits */ /* make sure it fits */
if ((BUF_OFFSET + size) > len) { if ((BUF_OFFSET + size) > len) {
return -ENOSPC; return -ENOSPC;
} }
if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) {
memcpy(buf, (uint8_t *)&v, size); memcpy((void *)buf, (uint8_t *)&v, size);
} else if (fmt[-1] == 'L') { } else if (fmt[-1] == 'L') {
*(long double *)buf = v.ld; *(long double *)buf = v.ld;
} else { } else {
@ -577,14 +577,14 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags,
size = sizeof(double); size = sizeof(double);
} }
/* align destination buffer location */ /* align destination buffer location */
buf = (void *) ROUND_UP(buf, align); buf = ROUND_UP(buf, align);
if (buf0 != NULL) { if (buf0 != NULL) {
/* make sure it fits */ /* make sure it fits */
if (BUF_OFFSET + size > len) { if (BUF_OFFSET + size > len) {
return -ENOSPC; return -ENOSPC;
} }
if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) {
memcpy(buf, (uint8_t *)&v, size); memcpy((void *)buf, (uint8_t *)&v, size);
} else if (fmt[-1] == 'L') { } else if (fmt[-1] == 'L') {
*(long double *)buf = v.ld; *(long double *)buf = v.ld;
} else { } else {
@ -603,7 +603,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags,
} }
/* align destination buffer location */ /* align destination buffer location */
buf = (void *) ROUND_UP(buf, align); buf = ROUND_UP(buf, align);
/* make sure the data fits */ /* make sure the data fits */
if ((buf0 != NULL) && (BUF_OFFSET + size) > len) { if ((buf0 != NULL) && (BUF_OFFSET + size) > len) {
@ -700,7 +700,7 @@ process_string:
if (buf0 != NULL) { if (buf0 != NULL) {
if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) {
memcpy(buf, (uint8_t *)&v, sizeof(long long)); memcpy((void *)buf, (uint8_t *)&v, sizeof(long long));
} else { } else {
*(long long *)buf = v; *(long long *)buf = v;
} }
@ -767,7 +767,7 @@ process_string:
return -ENOSPC; return -ENOSPC;
} }
/* store the pointer position prefix */ /* store the pointer position prefix */
*buf = pos; *(uint8_t *)buf = pos;
++buf; ++buf;
} }
} }
@ -781,7 +781,8 @@ process_string:
if (rws_pos_en) { if (rws_pos_en) {
size = 0; size = 0;
*buf++ = str_ptr_arg[i]; *(uint8_t *)buf = str_ptr_arg[i];
++buf;
} else { } else {
/* retrieve the string pointer */ /* retrieve the string pointer */
s = *(char **)(buf0 + str_ptr_pos[i] * sizeof(int)); s = *(char **)(buf0 + str_ptr_pos[i] * sizeof(int));
@ -796,10 +797,10 @@ process_string:
return -ENOSPC; return -ENOSPC;
} }
/* store the pointer position prefix */ /* store the pointer position prefix */
*buf = str_ptr_pos[i]; *(uint8_t *)buf = str_ptr_pos[i];
++buf; ++buf;
/* copy the string with its terminating '\0' */ /* copy the string with its terminating '\0' */
memcpy(buf, (uint8_t *)s, size); memcpy((void *)buf, (uint8_t *)s, size);
buf += size; buf += size;
} }