From c657a1973e274b16db0631dc3862e276ab354564 Mon Sep 17 00:00:00 2001 From: Ruoyu Zhong <zhongruoyu@outlook.com> Date: Sat, 19 Aug 2023 22:48:16 +0800 Subject: [PATCH 1/2] MDEV-31963 cmake: fix libfmt usage `fmt::detail::make_arg` does not accept temporaries, so the code snippet checking system libfmt needs to be adjusted. Signed-off-by: Ruoyu Zhong <zhongruoyu@outlook.com> --- cmake/libfmt.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- a/cmake/libfmt.cmake +++ b/cmake/libfmt.cmake @@ -33,8 +33,9 @@ MACRO (CHECK_LIBFMT) #include <fmt/format-inl.h> #include <iostream> int main() { + int answer= 42; fmt::format_args::format_arg arg= - fmt::detail::make_arg<fmt::format_context>(42); + fmt::detail::make_arg<fmt::format_context>(answer); std::cout << fmt::vformat(\"The answer is {}.\", fmt::format_args(&arg, 1)); }" HAVE_SYSTEM_LIBFMT) --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1382,11 +1382,24 @@ namespace fmt { */ String *Item_func_sformat::val_str(String *res) { + /* + A union that stores a numeric format arg value. + fmt::detail::make_arg does not accept temporaries, so all of its numeric + args are temporarily stored in the fmt_args array. + See: https://github.com/fmtlib/fmt/issues/3596 + */ + union Format_arg_store { + longlong val_int; + float val_float; + double val_double; + }; + DBUG_ASSERT(fixed()); - using ctx= fmt::format_context; - String *fmt_arg= NULL; - String *parg= NULL; - fmt::format_args::format_arg *vargs= NULL; + using ctx= fmt::format_context; + String *fmt_arg= NULL; + String *parg= NULL; + fmt::format_args::format_arg *vargs= NULL; + Format_arg_store *fmt_args= NULL; null_value= true; if (!(fmt_arg= args[0]->val_str(res))) @@ -1395,25 +1408,39 @@ String *Item_func_sformat::val_str(Strin if (!(vargs= new fmt::format_args::format_arg[arg_count - 1])) return NULL; + if (!(fmt_args= new Format_arg_store[arg_count - 1])) + { + delete [] vargs; + return NULL; + } + /* Creates the array of arguments for vformat */ for (uint carg= 1; carg < arg_count; carg++) { switch (args[carg]->result_type()) { case INT_RESULT: - vargs[carg-1]= fmt::detail::make_arg<ctx>(args[carg]->val_int()); + fmt_args[carg-1].val_int= args[carg]->val_int(); + vargs[carg-1]= fmt::detail::make_arg<ctx>(fmt_args[carg-1].val_int); break; case DECIMAL_RESULT: // TODO case REAL_RESULT: if (args[carg]->field_type() == MYSQL_TYPE_FLOAT) - vargs[carg-1]= fmt::detail::make_arg<ctx>((float)args[carg]->val_real()); + { + fmt_args[carg-1].val_float= (float)args[carg]->val_real(); + vargs[carg-1]= fmt::detail::make_arg<ctx>(fmt_args[carg-1].val_float); + } else - vargs[carg-1]= fmt::detail::make_arg<ctx>(args[carg]->val_real()); + { + fmt_args[carg-1].val_double= args[carg]->val_real(); + vargs[carg-1]= fmt::detail::make_arg<ctx>(fmt_args[carg-1].val_double); + } break; case STRING_RESULT: if (!(parg= args[carg]->val_str(&val_arg[carg-1]))) { delete [] vargs; + delete [] fmt_args; return NULL; } vargs[carg-1]= fmt::detail::make_arg<ctx>(*parg); @@ -1423,6 +1450,7 @@ String *Item_func_sformat::val_str(Strin default: DBUG_ASSERT(0); delete [] vargs; + delete [] fmt_args; return NULL; } } @@ -1446,6 +1474,7 @@ String *Item_func_sformat::val_str(Strin null_value= true; } delete [] vargs; + delete [] fmt_args; return null_value ? NULL : res; }