diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 8da164695f..da337cb4e1 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -314,6 +314,7 @@ tests := \
tst-popen2 \
tst-printf-binary \
tst-printf-intn \
+ tst-printf-macro \
tst-printf-oct \
tst-printf-round \
tst-printfsz \
diff --git a/stdio-common/tst-printf-macro.c b/stdio-common/tst-printf-macro.c
new file mode 100644
index 0000000000..100c6a4b0a
--- /dev/null
+++ b/stdio-common/tst-printf-macro.c
@@ -0,0 +1,93 @@
+/* Test printf PRI* macro narrowing arguments.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ . */
+
+#include
+#include
+#include
+
+#include
+#include
+
+#define CHECK_PRINTF(EXPECTED, FMT, ...) \
+ do \
+ { \
+ int ret = snprintf (buf, sizeof buf, FMT, \
+ __VA_ARGS__); \
+ TEST_COMPARE_STRING (buf, EXPECTED); \
+ TEST_COMPARE (ret, strlen (EXPECTED)); \
+ } \
+ while (0)
+
+_Static_assert (INT_FAST8_WIDTH == 8, "width of int_fast8_t");
+_Static_assert (UINT_FAST8_WIDTH == 8, "width of uint_fast8_t");
+
+static int
+do_test (void)
+{
+ char buf[1024];
+ CHECK_PRINTF ("-121", "%" PRId8, 1234567);
+ CHECK_PRINTF ("-121", "%" PRIdLEAST8, 1234567);
+ CHECK_PRINTF ("-121", "%" PRIdFAST8, 1234567);
+ CHECK_PRINTF ("-10617", "%" PRId16, 1234567);
+ CHECK_PRINTF ("-10617", "%" PRIdLEAST16, 1234567);
+ CHECK_PRINTF ("-121", "%" PRIi8, 1234567);
+ CHECK_PRINTF ("-121", "%" PRIiLEAST8, 1234567);
+ CHECK_PRINTF ("-121", "%" PRIiFAST8, 1234567);
+ CHECK_PRINTF ("-10617", "%" PRIi16, 1234567);
+ CHECK_PRINTF ("-10617", "%" PRIiLEAST16, 1234567);
+ CHECK_PRINTF ("207", "%" PRIo8, 1234567);
+ CHECK_PRINTF ("207", "%" PRIoLEAST8, 1234567);
+ CHECK_PRINTF ("207", "%" PRIoFAST8, 1234567);
+ CHECK_PRINTF ("153207", "%" PRIo16, 1234567);
+ CHECK_PRINTF ("153207", "%" PRIoLEAST16, 1234567);
+ CHECK_PRINTF ("135", "%" PRIu8, 1234567);
+ CHECK_PRINTF ("135", "%" PRIuLEAST8, 1234567);
+ CHECK_PRINTF ("135", "%" PRIuFAST8, 1234567);
+ CHECK_PRINTF ("54919", "%" PRIu16, 1234567);
+ CHECK_PRINTF ("54919", "%" PRIuLEAST16, 1234567);
+ CHECK_PRINTF ("87", "%" PRIx8, 1234567);
+ CHECK_PRINTF ("87", "%" PRIxLEAST8, 1234567);
+ CHECK_PRINTF ("87", "%" PRIxFAST8, 1234567);
+ CHECK_PRINTF ("d687", "%" PRIx16, 1234567);
+ CHECK_PRINTF ("d687", "%" PRIxLEAST16, 1234567);
+ CHECK_PRINTF ("87", "%" PRIX8, 1234567);
+ CHECK_PRINTF ("87", "%" PRIXLEAST8, 1234567);
+ CHECK_PRINTF ("87", "%" PRIXFAST8, 1234567);
+ CHECK_PRINTF ("D687", "%" PRIX16, 1234567);
+ CHECK_PRINTF ("D687", "%" PRIXLEAST16, 1234567);
+ /* GCC does not know the %b or %B formats before GCC 12. */
+ DIAG_PUSH_NEEDS_COMMENT;
+#if !__GNUC_PREREQ (12, 0)
+ DIAG_IGNORE_NEEDS_COMMENT (11, "-Wformat");
+ DIAG_IGNORE_NEEDS_COMMENT (11, "-Wformat-extra-args");
+#endif
+ CHECK_PRINTF ("10000111", "%" PRIb8, 1234567);
+ CHECK_PRINTF ("10000111", "%" PRIbLEAST8, 1234567);
+ CHECK_PRINTF ("10000111", "%" PRIbFAST8, 1234567);
+ CHECK_PRINTF ("1101011010000111", "%" PRIb16, 1234567);
+ CHECK_PRINTF ("1101011010000111", "%" PRIbLEAST16, 1234567);
+ CHECK_PRINTF ("10000111", "%" PRIB8, 1234567);
+ CHECK_PRINTF ("10000111", "%" PRIBLEAST8, 1234567);
+ CHECK_PRINTF ("10000111", "%" PRIBFAST8, 1234567);
+ CHECK_PRINTF ("1101011010000111", "%" PRIB16, 1234567);
+ CHECK_PRINTF ("1101011010000111", "%" PRIBLEAST16, 1234567);
+ DIAG_POP_NEEDS_COMMENT;
+ return 0;
+}
+
+#include
diff --git a/stdlib/inttypes.h b/stdlib/inttypes.h
index 9726abf5b1..a244db0da8 100644
--- a/stdlib/inttypes.h
+++ b/stdlib/inttypes.h
@@ -51,97 +51,97 @@ typedef wchar_t __gwchar_t;
/* Macros for printing format specifiers. */
/* Decimal notation. */
-# define PRId8 "d"
-# define PRId16 "d"
+# define PRId8 "hhd"
+# define PRId16 "hd"
# define PRId32 "d"
# define PRId64 __PRI64_PREFIX "d"
-# define PRIdLEAST8 "d"
-# define PRIdLEAST16 "d"
+# define PRIdLEAST8 "hhd"
+# define PRIdLEAST16 "hd"
# define PRIdLEAST32 "d"
# define PRIdLEAST64 __PRI64_PREFIX "d"
-# define PRIdFAST8 "d"
+# define PRIdFAST8 "hhd"
# define PRIdFAST16 __PRIPTR_PREFIX "d"
# define PRIdFAST32 __PRIPTR_PREFIX "d"
# define PRIdFAST64 __PRI64_PREFIX "d"
-# define PRIi8 "i"
-# define PRIi16 "i"
+# define PRIi8 "hhi"
+# define PRIi16 "hi"
# define PRIi32 "i"
# define PRIi64 __PRI64_PREFIX "i"
-# define PRIiLEAST8 "i"
-# define PRIiLEAST16 "i"
+# define PRIiLEAST8 "hhi"
+# define PRIiLEAST16 "hi"
# define PRIiLEAST32 "i"
# define PRIiLEAST64 __PRI64_PREFIX "i"
-# define PRIiFAST8 "i"
+# define PRIiFAST8 "hhi"
# define PRIiFAST16 __PRIPTR_PREFIX "i"
# define PRIiFAST32 __PRIPTR_PREFIX "i"
# define PRIiFAST64 __PRI64_PREFIX "i"
/* Octal notation. */
-# define PRIo8 "o"
-# define PRIo16 "o"
+# define PRIo8 "hho"
+# define PRIo16 "ho"
# define PRIo32 "o"
# define PRIo64 __PRI64_PREFIX "o"
-# define PRIoLEAST8 "o"
-# define PRIoLEAST16 "o"
+# define PRIoLEAST8 "hho"
+# define PRIoLEAST16 "ho"
# define PRIoLEAST32 "o"
# define PRIoLEAST64 __PRI64_PREFIX "o"
-# define PRIoFAST8 "o"
+# define PRIoFAST8 "hho"
# define PRIoFAST16 __PRIPTR_PREFIX "o"
# define PRIoFAST32 __PRIPTR_PREFIX "o"
# define PRIoFAST64 __PRI64_PREFIX "o"
/* Unsigned integers. */
-# define PRIu8 "u"
-# define PRIu16 "u"
+# define PRIu8 "hhu"
+# define PRIu16 "hu"
# define PRIu32 "u"
# define PRIu64 __PRI64_PREFIX "u"
-# define PRIuLEAST8 "u"
-# define PRIuLEAST16 "u"
+# define PRIuLEAST8 "hhu"
+# define PRIuLEAST16 "hu"
# define PRIuLEAST32 "u"
# define PRIuLEAST64 __PRI64_PREFIX "u"
-# define PRIuFAST8 "u"
+# define PRIuFAST8 "hhu"
# define PRIuFAST16 __PRIPTR_PREFIX "u"
# define PRIuFAST32 __PRIPTR_PREFIX "u"
# define PRIuFAST64 __PRI64_PREFIX "u"
/* lowercase hexadecimal notation. */
-# define PRIx8 "x"
-# define PRIx16 "x"
+# define PRIx8 "hhx"
+# define PRIx16 "hx"
# define PRIx32 "x"
# define PRIx64 __PRI64_PREFIX "x"
-# define PRIxLEAST8 "x"
-# define PRIxLEAST16 "x"
+# define PRIxLEAST8 "hhx"
+# define PRIxLEAST16 "hx"
# define PRIxLEAST32 "x"
# define PRIxLEAST64 __PRI64_PREFIX "x"
-# define PRIxFAST8 "x"
+# define PRIxFAST8 "hhx"
# define PRIxFAST16 __PRIPTR_PREFIX "x"
# define PRIxFAST32 __PRIPTR_PREFIX "x"
# define PRIxFAST64 __PRI64_PREFIX "x"
/* UPPERCASE hexadecimal notation. */
-# define PRIX8 "X"
-# define PRIX16 "X"
+# define PRIX8 "hhX"
+# define PRIX16 "hX"
# define PRIX32 "X"
# define PRIX64 __PRI64_PREFIX "X"
-# define PRIXLEAST8 "X"
-# define PRIXLEAST16 "X"
+# define PRIXLEAST8 "hhX"
+# define PRIXLEAST16 "hX"
# define PRIXLEAST32 "X"
# define PRIXLEAST64 __PRI64_PREFIX "X"
-# define PRIXFAST8 "X"
+# define PRIXFAST8 "hhX"
# define PRIXFAST16 __PRIPTR_PREFIX "X"
# define PRIXFAST32 __PRIPTR_PREFIX "X"
# define PRIXFAST64 __PRI64_PREFIX "X"
@@ -166,17 +166,17 @@ typedef wchar_t __gwchar_t;
/* Binary notation. */
# if __GLIBC_USE (ISOC23)
-# define PRIb8 "b"
-# define PRIb16 "b"
+# define PRIb8 "hhb"
+# define PRIb16 "hb"
# define PRIb32 "b"
# define PRIb64 __PRI64_PREFIX "b"
-# define PRIbLEAST8 "b"
-# define PRIbLEAST16 "b"
+# define PRIbLEAST8 "hhb"
+# define PRIbLEAST16 "hb"
# define PRIbLEAST32 "b"
# define PRIbLEAST64 __PRI64_PREFIX "b"
-# define PRIbFAST8 "b"
+# define PRIbFAST8 "hhb"
# define PRIbFAST16 __PRIPTR_PREFIX "b"
# define PRIbFAST32 __PRIPTR_PREFIX "b"
# define PRIbFAST64 __PRI64_PREFIX "b"
@@ -184,17 +184,17 @@ typedef wchar_t __gwchar_t;
# define PRIbMAX __PRI64_PREFIX "b"
# define PRIbPTR __PRIPTR_PREFIX "b"
-# define PRIB8 "B"
-# define PRIB16 "B"
+# define PRIB8 "hhB"
+# define PRIB16 "hB"
# define PRIB32 "B"
# define PRIB64 __PRI64_PREFIX "B"
-# define PRIBLEAST8 "B"
-# define PRIBLEAST16 "B"
+# define PRIBLEAST8 "hhB"
+# define PRIBLEAST16 "hB"
# define PRIBLEAST32 "B"
# define PRIBLEAST64 __PRI64_PREFIX "B"
-# define PRIBFAST8 "B"
+# define PRIBFAST8 "hhB"
# define PRIBFAST16 __PRIPTR_PREFIX "B"
# define PRIBFAST32 __PRIPTR_PREFIX "B"
# define PRIBFAST64 __PRI64_PREFIX "B"