This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 0c009a8cbaf7bf645af37e283094585e2f1802fe Author: Marco Casaroli <[email protected]> AuthorDate: Thu Nov 5 06:51:54 2026 +0100 libs/libc/stream: Take the argument of %a and print a question mark. printf() has no %a. It went to the path of the unknown conversions, which takes an unsigned int. The argument is a double, and on arm64, RISC-V and x86_64 it is in a floating point register. The next %s used a wrong general register as a pointer, and printf() crashed. Take the double for %a and %A and print "?", padded to the width. With CONFIG_LIBC_FLOATINGPOINT off, do the same for %e, %f and %g, in place of the text "*float*". So a conversion that is not available has one behavior, and the rest of the line stays correct. Part of https://github.com/apache/nuttx/issues/21467 Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- libs/libc/stdio/Kconfig | 2 ++ libs/libc/stream/lib_libvsprintf.c | 27 ++++++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/libs/libc/stdio/Kconfig b/libs/libc/stdio/Kconfig index ff25cacb619..70b5bfe4ab8 100644 --- a/libs/libc/stdio/Kconfig +++ b/libs/libc/stdio/Kconfig @@ -59,6 +59,8 @@ config LIBC_FLOATINGPOINT ---help--- By default, floating point support in printf, sscanf, etc. is disabled. This option will enable floating point support. + Without it, printf() takes the argument of %e, %f and %g and + prints "?". config LIBC_NUMBERED_ARGS bool "Enable numbered arguments in printf" diff --git a/libs/libc/stream/lib_libvsprintf.c b/libs/libc/stream/lib_libvsprintf.c index 1bb3d1ebe63..80083855c1c 100644 --- a/libs/libc/stream/lib_libvsprintf.c +++ b/libs/libc/stream/lib_libvsprintf.c @@ -112,6 +112,11 @@ #define fmt_ungetc(fmt) ((fmt)--) +/* e, f, g and a in either case: 0x20 makes an ASCII letter lower case */ + +#define fmt_isfloat(c) ((((c) | 0x20) >= 'e' && ((c) | 0x20) <= 'g') || \ + ((c) | 0x20) == 'a') + /**************************************************************************** * Private Types ****************************************************************************/ @@ -596,8 +601,7 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream, { if (stream == NULL) { - if ((c >= 'E' && c <= 'G') - || (c >= 'e' && c <= 'g')) + if (fmt_isfloat(c)) { arglist->type[argnumber - 1] = TYPE_DOUBLE; } @@ -645,13 +649,13 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream, #endif #ifdef CONFIG_LIBC_FLOATINGPOINT - if (c >= 'E' && c <= 'G') + if ((c >= 'E' && c <= 'G') || c == 'A') { flags |= FL_FLTUPP; c += 'e' - 'E'; goto flt_oper; } - else if (c >= 'e' && c <= 'g') + else if ((c >= 'e' && c <= 'g') || c == 'a') { double value; int exp; /* Exponent of master decimal digit */ @@ -706,6 +710,15 @@ flt_oper: value = va_arg(ap, double); } + /* %a has no output yet */ + + if (c == 'a') + { + pnt = "?"; + size = 1; + goto str_lpad; + } + ndigs = __dtoa_engine(value, &_dtoa, ndigs, ndecimal); exp = _dtoa.exp; @@ -982,7 +995,7 @@ flt_oper: } #else /* !CONFIG_LIBC_FLOATINGPOINT */ - if ((c >= 'E' && c <= 'G') || (c >= 'e' && c <= 'g')) + if (fmt_isfloat(c)) { # ifdef CONFIG_LIBC_NUMBERED_ARGS if ((flags & FL_ARGNUMBER) == 0) @@ -991,8 +1004,8 @@ flt_oper: va_arg(ap, double); } - pnt = "*float*"; - size = sizeof("*float*") - 1; + pnt = "?"; + size = 1; goto str_lpad; } #endif
