Fix inttypes.h FAST16 macros to have a correct definition

The PRI and SCN are described by the C standard as being:
> suitable for use within the format argument of a formatted
> input/output function when converting the corresponding integer type
- C Standard, 7.8.1. Macros for format specifiers

However, cosmopolitan fails to do this properly for the FAST16 macros,
meaning that for example, the following program:

 #include <stdio.h>
 #include <stdint.h>
 #include <inttypes.h>
 #undef NDEBUG
 #include <assert.h>

int main()
{
    uint_fast16_t v = 0xFFFFFFFF;
    assert(sscanf("12345", "%" SCNdFAST16, &v) == 1);

    printf("%ju\n", (uintmax_t)v);
}

will print 4294914105 instead of the correct 12345 on
cosmopolitan. This is caused by the fact that the definitions of the
FAST16 macros have been made with the assumption that these are 16-bit
types, when they are in fact defined as 32-bit types.

This patch fixes this.
This commit is contained in:
Gabriel Ravier 2023-03-27 23:45:14 +02:00
parent 792b1c84c0
commit c6a7a6af25
2 changed files with 96 additions and 14 deletions

View file

@ -86,7 +86,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define PRIdLEAST128 __PRI128 "d"
#define PRIdFAST8 __PRI8 "d"
#define PRIdFAST16 __PRI16 "d"
#define PRIdFAST16 __PRI32 "d"
#define PRIdFAST32 __PRI32 "d"
#define PRIdFAST64 __PRI64 "d"
#define PRIdFAST128 __PRI128 "d"
@ -108,7 +108,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define PRIuLEAST128 __PRI128 "u"
#define PRIuFAST8 __PRI8 "u"
#define PRIuFAST16 __PRI16 "u"
#define PRIuFAST16 __PRI32 "u"
#define PRIuFAST32 __PRI32 "u"
#define PRIuFAST64 __PRI64 "u"
#define PRIuFAST128 __PRI128 "u"
@ -130,7 +130,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define PRIiLEAST128 __PRI128 "i"
#define PRIiFAST8 __PRI8 "i"
#define PRIiFAST16 __PRI16 "i"
#define PRIiFAST16 __PRI32 "i"
#define PRIiFAST32 __PRI32 "i"
#define PRIiFAST64 __PRI64 "i"
#define PRIiFAST128 __PRI128 "i"
@ -152,7 +152,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define PRIoLEAST128 __PRI128 "o"
#define PRIoFAST8 __PRI8 "o"
#define PRIoFAST16 __PRI16 "o"
#define PRIoFAST16 __PRI32 "o"
#define PRIoFAST32 __PRI32 "o"
#define PRIoFAST64 __PRI64 "o"
#define PRIoFAST128 __PRI128 "o"
@ -174,7 +174,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define PRIxLEAST128 __PRI128 "x"
#define PRIxFAST8 __PRI8 "x"
#define PRIxFAST16 __PRI16 "x"
#define PRIxFAST16 __PRI32 "x"
#define PRIxFAST32 __PRI32 "x"
#define PRIxFAST64 __PRI64 "x"
#define PRIxFAST128 __PRI128 "x"
@ -192,7 +192,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define PRIXLEAST128 __PRI128 "X"
#define PRIXFAST8 __PRI8 "X"
#define PRIXFAST16 __PRI16 "X"
#define PRIXFAST16 __PRI32 "X"
#define PRIXFAST32 __PRI32 "X"
#define PRIXFAST64 __PRI64 "X"
#define PRIXFAST128 __PRI128 "X"
@ -214,7 +214,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define PRIbLEAST128 __PRI128 "b"
#define PRIbFAST8 __PRI8 "b"
#define PRIbFAST16 __PRI16 "b"
#define PRIbFAST16 __PRI32 "b"
#define PRIbFAST32 __PRI32 "b"
#define PRIbFAST64 __PRI64 "b"
#define PRIbFAST128 __PRI128 "b"
@ -232,7 +232,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define PRIBLEAST128 __PRI128 "B"
#define PRIBFAST8 __PRI8 "B"
#define PRIBFAST16 __PRI16 "B"
#define PRIBFAST16 __PRI32 "B"
#define PRIBFAST32 __PRI32 "B"
#define PRIBFAST64 __PRI64 "B"
#define PRIBFAST128 __PRI128 "B"
@ -272,7 +272,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define SCNdLEAST128 __PRI128 "d"
#define SCNdFAST8 __PRI8 "d"
#define SCNdFAST16 __PRI16 "d"
#define SCNdFAST16 __PRI32 "d"
#define SCNdFAST32 __PRI32 "d"
#define SCNdFAST64 __PRI64 "d"
#define SCNdFAST128 __PRI128 "d"
@ -294,7 +294,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define SCNiLEAST128 __PRI128 "i"
#define SCNiFAST8 __PRI8 "i"
#define SCNiFAST16 __PRI16 "i"
#define SCNiFAST16 __PRI32 "i"
#define SCNiFAST32 __PRI32 "i"
#define SCNiFAST64 __PRI64 "i"
#define SCNiFAST128 __PRI128 "i"
@ -316,7 +316,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define SCNuLEAST128 __PRI128 "u"
#define SCNuFAST8 __PRI8 "u"
#define SCNuFAST16 __PRI16 "u"
#define SCNuFAST16 __PRI32 "u"
#define SCNuFAST32 __PRI32 "u"
#define SCNuFAST64 __PRI64 "u"
#define SCNuFAST128 __PRI128 "u"
@ -338,7 +338,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define SCNoLEAST128 __PRI128 "o"
#define SCNoFAST8 __PRI8 "o"
#define SCNoFAST16 __PRI16 "o"
#define SCNoFAST16 __PRI32 "o"
#define SCNoFAST32 __PRI32 "o"
#define SCNoFAST64 __PRI64 "o"
#define SCNoFAST128 __PRI128 "o"
@ -360,7 +360,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define SCNxLEAST128 __PRI128 "x"
#define SCNxFAST8 __PRI8 "x"
#define SCNxFAST16 __PRI16 "x"
#define SCNxFAST16 __PRI32 "x"
#define SCNxFAST32 __PRI32 "x"
#define SCNxFAST64 __PRI64 "x"
#define SCNxFAST128 __PRI128 "x"
@ -382,7 +382,7 @@ typedef __UINT_FAST64_TYPE__ uint_fast64_t;
#define SCNbLEAST128 __PRI128 "b"
#define SCNbFAST8 __PRI8 "b"
#define SCNbFAST16 __PRI16 "b"
#define SCNbFAST16 __PRI32 "b"
#define SCNbFAST32 __PRI32 "b"
#define SCNbFAST64 __PRI64 "b"
#define SCNbFAST128 __PRI128 "b"

View file

@ -19,6 +19,7 @@
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/bits.h"
#include "libc/inttypes.h"
#include "libc/limits.h"
#include "libc/mem/mem.h"
#include "libc/testlib/testlib.h"
@ -149,3 +150,84 @@ TEST(sscanf, testFixedWidthFormat_Integer) {
ASSERT_EQ(2, g);
ASSERT_EQ(30, b);
}
TEST(sscanf, testInttypes_macros) {
int8_t i8 = (int8_t)0xFFFFFFFFFFFFFFFF;
uint8_t u8 = (uint8_t)0xFFFFFFFFFFFFFFFF;
int16_t i16 = (int16_t)0xFFFFFFFFFFFFFFFF;
uint16_t u16 = (uint16_t)0xFFFFFFFFFFFFFFFF;
int32_t i32 = (int32_t)0xFFFFFFFFFFFFFFFF;
uint32_t u32 = (uint32_t)0xFFFFFFFFFFFFFFFF;
int64_t i64 = (int64_t)0xFFFFFFFFFFFFFFFF;
uint64_t u64 = (uint64_t)0xFFFFFFFFFFFFFFFF;
intmax_t imax = (intmax_t)0xFFFFFFFFFFFFFFFF;
uintmax_t umax = (uintmax_t)0xFFFFFFFFFFFFFFFF;
int_least8_t il8 = (int_least8_t)0xFFFFFFFFFFFFFFFF;
uint_least8_t ul8 = (uint_least8_t)0xFFFFFFFFFFFFFFFF;
int_least16_t il16 = (int_least16_t)0xFFFFFFFFFFFFFFFF;
uint_least16_t ul16 = (uint_least16_t)0xFFFFFFFFFFFFFFFF;
int_least32_t il32 = (int_least32_t)0xFFFFFFFFFFFFFFFF;
uint_least32_t ul32 = (uint_least32_t)0xFFFFFFFFFFFFFFFF;
int_least64_t il64 = (int_least64_t)0xFFFFFFFFFFFFFFFF;
uint_least64_t ul64 = (uint_least64_t)0xFFFFFFFFFFFFFFFF;
int_fast8_t if8 = (int_fast8_t)0xFFFFFFFFFFFFFFFF;
uint_fast8_t uf8 = (uint_fast8_t)0xFFFFFFFFFFFFFFFF;
int_fast16_t if16 = (int_fast16_t)0xFFFFFFFFFFFFFFFF;
uint_fast16_t uf16 = (uint_fast16_t)0xFFFFFFFFFFFFFFFF;
int_fast32_t if32 = (int_fast32_t)0xFFFFFFFFFFFFFFFF;
uint_fast32_t uf32 = (uint_fast32_t)0xFFFFFFFFFFFFFFFF;
int_fast64_t if64 = (int_fast64_t)0xFFFFFFFFFFFFFFFF;
uint_fast64_t uf64 = (uint_fast64_t)0xFFFFFFFFFFFFFFFF;
ASSERT_EQ(sscanf("1", "%" SCNd8, &i8), 1);
ASSERT_EQ(sscanf("1", "%" SCNu8, &u8), 1);
ASSERT_EQ(sscanf("1", "%" SCNd16, &i16), 1);
ASSERT_EQ(sscanf("1", "%" SCNu16, &u16), 1);
ASSERT_EQ(sscanf("1", "%" SCNd32, &i32), 1);
ASSERT_EQ(sscanf("1", "%" SCNu32, &u32), 1);
ASSERT_EQ(sscanf("1", "%" SCNd64, &i64), 1);
ASSERT_EQ(sscanf("1", "%" SCNu64, &u64), 1);
ASSERT_EQ(sscanf("1", "%" SCNdMAX, &imax), 1);
ASSERT_EQ(sscanf("1", "%" SCNuMAX, &umax), 1);
ASSERT_EQ(sscanf("1", "%" SCNdLEAST8, &il8), 1);
ASSERT_EQ(sscanf("1", "%" SCNuLEAST8, &ul8), 1);
ASSERT_EQ(sscanf("1", "%" SCNdLEAST16, &il16), 1);
ASSERT_EQ(sscanf("1", "%" SCNuLEAST16, &ul16), 1);
ASSERT_EQ(sscanf("1", "%" SCNdLEAST32, &il32), 1);
ASSERT_EQ(sscanf("1", "%" SCNuLEAST32, &ul32), 1);
ASSERT_EQ(sscanf("1", "%" SCNdLEAST64, &il64), 1);
ASSERT_EQ(sscanf("1", "%" SCNuLEAST64, &ul64), 1);
ASSERT_EQ(sscanf("1", "%" SCNdFAST8, &if8), 1);
ASSERT_EQ(sscanf("1", "%" SCNuFAST8, &uf8), 1);
ASSERT_EQ(sscanf("1", "%" SCNdFAST16, &if16), 1);
ASSERT_EQ(sscanf("1", "%" SCNuFAST16, &uf16), 1);
ASSERT_EQ(sscanf("1", "%" SCNdFAST32, &if32), 1);
ASSERT_EQ(sscanf("1", "%" SCNuFAST32, &uf32), 1);
ASSERT_EQ(sscanf("1", "%" SCNdFAST64, &if64), 1);
ASSERT_EQ(sscanf("1", "%" SCNuFAST64, &uf64), 1);
ASSERT_EQ(i8, 1);
ASSERT_EQ(u8, 1);
ASSERT_EQ(i16, 1);
ASSERT_EQ(u16, 1);
ASSERT_EQ(i32, 1);
ASSERT_EQ(u32, 1);
ASSERT_EQ(i64, 1);
ASSERT_EQ(u64, 1);
ASSERT_EQ(imax, 1);
ASSERT_EQ(umax, 1);
ASSERT_EQ(il8, 1);
ASSERT_EQ(ul8, 1);
ASSERT_EQ(il16, 1);
ASSERT_EQ(ul16, 1);
ASSERT_EQ(il32, 1);
ASSERT_EQ(ul32, 1);
ASSERT_EQ(il64, 1);
ASSERT_EQ(ul64, 1);
ASSERT_EQ(if16, 1);
ASSERT_EQ(uf16, 1);
ASSERT_EQ(if32, 1);
ASSERT_EQ(uf32, 1);
ASSERT_EQ(if64, 1);
ASSERT_EQ(uf64, 1);
}