lib: cbprintf: avoid referencing distinct union fields in a statement

An assignment from one multi-word union field to another was not safe
from corruption.  Copy the value out to a local value before storing it
to the preferred union field.

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
Peter Bigot 2021-01-27 10:15:13 -06:00 committed by Anas Nashif
commit 10180af38d

View file

@ -1323,6 +1323,7 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap)
{ {
char buf[CONVERTED_BUFLEN]; char buf[CONVERTED_BUFLEN];
size_t count = 0; size_t count = 0;
sint_value_type sint;
/* Output character, returning EOF if output failed, otherwise /* Output character, returning EOF if output failed, otherwise
* updating count. * updating count.
@ -1579,11 +1580,16 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap)
sign = ' '; sign = ' ';
} }
if (value->sint < 0) { /* sint/uint overlay in the union, and so
* can't appear in read and write operations
* in the same statement.
*/
sint = value->sint;
if (sint < 0) {
sign = '-'; sign = '-';
value->uint = (uint_value_type)-value->sint; value->uint = (uint_value_type)-sint;
} else { } else {
value->uint = (uint_value_type)value->sint; value->uint = (uint_value_type)sint;
} }
__fallthrough; __fallthrough;