Skip to content

sprintf reads past end of format string on trailing % #4741

Description

@Algunenano

Repro:

#include <fmt/printf.h>
#include <cstdlib>

int main()
{
    // Allocate exactly 1 byte so the byte after '%' is uninitialized.
    char * buf = static_cast<char *>(malloc(1));
    buf[0] = '%';
    fmt::sprintf(fmt::string_view(buf, 1));
    free(buf);
}

Running with msan:

/tmp $ clang++ -fsanitize=memory -g -O1 -DFMT_HEADER_ONLY -std=c++20 repro.cpp 
/tmp $ ./a.out 
==1358466==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x5559e25b1fad in int fmt::v12::detail::parse_header<char, void fmt::v12::detail::vprintf<char, fmt::v12::basic_printf_context<char>>(fmt::v12::detail::buffer<char>&, fmt::v12::basic_string_view<char>, fmt::v12::basic_format_args<fmt::v12::basic_printf_context<char>>)::'lambda'(int)>(char const*&, char const*, fmt::v12::format_specs&, fmt::v12::basic_printf_context<char>) /usr/include/fmt/printf.h:334:16
    #1 0x5559e25afdb2 in void fmt::v12::detail::vprintf<char, fmt::v12::basic_printf_context<char>>(fmt::v12::detail::buffer<char>&, fmt::v12::basic_string_view<char>, fmt::v12::basic_format_args<fmt::v12::basic_printf_context<char>>) /usr/include/fmt/printf.h:431:21
    #2 0x5559e25af7d8 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> fmt::v12::vsprintf<char>(fmt::v12::basic_string_view<char>, fmt::v12::vprintf_args<char>::type) /usr/include/fmt/printf.h:557:3
    #3 0x5559e25af586 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> fmt::v12::sprintf<>(fmt::v12::basic_string_view<char>) /usr/include/fmt/printf.h:571:10
    #4 0x5559e25af586 in main /tmp/repro.cpp:9:5
    #5 0x7f7e707186c0 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16
    #6 0x7f7e707187f8 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3
    #7 0x5559e250e244 in _start (/tmp/a.out+0x34244) (BuildId: cb51f5aab589e09aa6ff4156746050e58b960562)

SUMMARY: MemorySanitizer: use-of-uninitialized-value /usr/include/fmt/printf.h:334:16 in int fmt::v12::detail::parse_header<char, void fmt::v12::detail::vprintf<char, fmt::v12::basic_printf_context<char>>(fmt::v12::detail::buffer<char>&, fmt::v12::basic_string_view<char>, fmt::v12::basic_format_args<fmt::v12::basic_printf_context<char>>)::'lambda'(int)>(char const*&, char const*, fmt::v12::format_specs&, fmt::v12::basic_printf_context<char>)
Exiting

The same issue applies to any format string ending with a lone %, e.g. "hello%".

I would expect a format_error exception or similar.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions