[SUBMIT] tlv_eeprom: fix bug when decoding TLV string of decimal numbers
authorHugo Villeneuve <hvilleneuve@dimonoff.com>
Fri, 14 Nov 2025 16:32:02 +0000 (11:32 -0500)
committerHugo Villeneuve <hvilleneuve@dimonoff.com>
Mon, 17 Nov 2025 15:50:01 +0000 (10:50 -0500)
This bug is not present in U-Boot, but happens if you compile the TLV code base
with glibc.

For default or TLV_CODE_VENDOR_EXT types, the decoded value as a string is
incorrect and display only the last byte.

For example, if TLV contains type TLV_CODE_VENDOR_EXT with a length of 6,
and bytes "0x66 0x6F 0x6F 0x62 0x61 0x72", here is the decoded output:

    TLV Name             Code Len Value
    -------------------- ---- --- -----
    Vendor Extension     0xFD   6  0x72

The reason (also identified by GCC warning message below) is that the behavior
of glibc sprintf is undefined if copying takes place between objects that
overlap - for example, if s is also given as an argument to be printed under
control of the ‘%s’ conversion.

Fix by using strcat and sprintf with an intermediate variable.

This also has the nice benefit of fixing this warning:

    In function ‘sprintf’,
    inlined from ‘decode_tlv_value’ at tlv_eeprom.c:343:4:
    ...stdio2.h:30:10: warning: ‘__builtin___sprintf_chk’ argument 5 overlaps destination object ‘value’ [-Wrestrict]
    30 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
       |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ...

Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
src/tlv_eeprom.c

index 78cb150..a6564e9 100644 (file)
@@ -337,7 +337,10 @@ static void decode_tlv_value(struct tlvinfo_tlv *tlv, char *value, int value_len
                value[0] = 0;
                for (i = 0; (i < (DECODE_VALUE_MAX / 5)) && (i < tlv->length);
                                i++) {
-                       sprintf(value, "%s 0x%02X", value, tlv->value[i]);
+                       char dec_val[DECODE_VALUE_MAX];
+
+                       sprintf(dec_val, " 0x%02X", tlv->value[i]);
+                       strcat(value, dec_val);
                }
                break;
        }