Closed skaae closed 2 years ago
I think it is a problem with fmt library. Can you reproduce the same problem with just fmt without spdlog?
Thank you for your reply.
I'm not sure how to reproduce this using fmt alone? fmt::format works, but fmt::format stores the result in a string so I don't think that reproduces the problem?
spdlogs log_msg
uses a string view to store the payload in string_view_t payload;
. I guess the string view is the problem and I'm not sure how to store the result of an fmt expression in a string view?
If the format is the cause, the following code would reproduce it.
https://github.com/gabime/spdlog/blob/6c95f4c8168401badff89d0c16e3887ea91ea9ad/include/spdlog/common.h#L151-L154 https://github.com/gabime/spdlog/blob/6c95f4c8168401badff89d0c16e3887ea91ea9ad/include/spdlog/logger.h#L370-L379
using string_view_t = fmt::basic_string_view<char>;
string_view_t buf;
fmt::detail::vformat_to(buf,
"**************************************************" // 50
"**************************************************" // 50
"**************************************************" // 50
"**************************************************" // 50
"**************************************************{}" // 51
,
fmt::make_format_args("1");
BTW, the string formatted by spdlog should not contain \0
(null-terminated character) at the end.
So I ignore the detection of strlen
(code not provided, but I assume it is called from std::basic_ostream
called by FooBar
) that expects \0
at the end.
thanks. I can't get the example to compile. I looked at fmts tests for vformat_to and the closets i can get to compile is
std::string s;
fmt::vformat_to(std::back_inserter(s),
"**************************************************" // 50
"**************************************************" // 50
"**************************************************" // 50
"**************************************************" // 50
"**************************************************{}" // 51
,
fmt::make_format_args("1"));
Do you have inputs on compiling with string_view?
Oh, I must be missing some fmt trick.
Since fmt::vformat_to(std::back_inserter(s), ...)
seems to call fmt::details::vformat_to()
internally, please try with your example code.
Making sure we are talking about the same code :) The code below works
std::string s;
fmt::vformat_to(std::back_inserter(s),
"**************************************************" // 50
"**************************************************" // 50
"**************************************************" // 50
"**************************************************" // 50
"**************************************************{}" // 51
,
fmt::make_format_args("1"));
I am not familiar with how to read AddressSanitizer reports, but isn't the heap-buffer-overflow caused by your FooBar
passing log messages to std::basic_ostream
?
I re-read the report and the heap-buffer-overflow is reported when calling strlen
inside std::basic_ostream
.
As noted in a previous comment, spdlog log messages are not terminated with the NULL character.
If you are passing log messages to std::cout
, etc., then the cause is your code.
I think you are correct. I think it happens when I access payload.data().
If i do fmt::print("{}", msg.payload) then it works, but fmt::print("{}", msg.payload.data()) fails.
Yes. You must pass msg.payload.data()
with msg.payload.size()
to C/C++ API that expect characters pointer.
Please do not directly call API that do not accept sizes.
great. Thank you for the help! I will close the issue.
Thanks @tt4g !
When running the code below with sanitizer enabled i get a
==931743==ERROR: AddressSanitizer: heap-buffer-overflow
error.The error happens if the logged string is longer than 250 characters and has at least one fmt formatted argument. In the sanitize output there is some info about
0x16ceda1 in fmt::v8::basic_memory_buffer<char, 250ul, std::allocator<char> >::grow(unsigned long)
. Maybe the data that string_viewmsg.payload
is pointing to was moved when the buffer was grown?compiler: clang-13, ubuntu 20.04. spdlog 1.10.0
Minimal example
Sanitize output