-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix UB in format_arg_store implementation. #3833
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR. format_arg_store
is not supposed to be copied so we should delete copy and assignment operators instead.
f767fb4
to
64595a0
Compare
Ok. |
Many reports from CI: https://github.com/fmtlib/fmt/actions/runs/7728340058/job/21068957883?pr=3833
https://github.com/fmtlib/fmt/actions/runs/7728340053/job/21068956966?pr=3833
https://github.com/fmtlib/fmt/actions/runs/7728340056/job/21068959707?pr=3833
etc. So, copy constructor must exist. Copy assignment operator might be deleted, I suggest. |
64595a0
to
ef7c57c
Compare
Yeah, let's go with that. |
include/fmt/base.h
Outdated
@@ -1636,7 +1636,9 @@ template <typename Context, size_t NUM_ARGS, size_t NUM_NAMED_ARGS, | |||
struct format_arg_store { | |||
// args_[0].named_args points to named_args to avoid bloating format_args. | |||
// +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. | |||
arg_t<Context, NUM_ARGS> args[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)]; | |||
static constexpr int ARGS_ARR_SIZE = 1 + (NUM_ARGS != 0 ? NUM_ARGS : +1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe size_t
(and i
in copy constructor)?
Like size_t NUM_ARGS, size_t NUM_NAMED_ARGS
template arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like loops optimization prevention for unsigned iterator due to allowed overflow is not a case here, because loop bounds are known at compile time.
Yep, size_t
is a good option here.
955f509
to
311ffbd
Compare
include/fmt/base.h
Outdated
format_arg_store(const format_arg_store& rhs) { | ||
args[0] = {named_args, NUM_NAMED_ARGS}; | ||
for (size_t i = 1; i < ARGS_ARR_SIZE; ++i) args[i] = rhs.args[i]; | ||
for (size_t i = 0; i < NUM_NAMED_ARGS; ++i) | ||
named_args[i] = rhs.named_args[i]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we only need move ctor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
311ffbd
to
b0945c2
Compare
Thank you! |
@@ -1649,6 +1651,17 @@ struct format_arg_store { | |||
0, | |||
(init_named_arg(named_args, arg_index, named_arg_index, values), 0)...}; | |||
} | |||
|
|||
format_arg_store(format_arg_store&& rhs) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This move constructor should be noexcept
format_arg_store struct contains pointers to its own members, so autogenerated copy constructor and copy assignment is not correct. Need to reassign pointers to |this| internals.
Compiler won't autogenerate incorrect move constructor and move assignment, because user-provided copy constructor and copy assignment member functions exist.