Skip to content

Commit 84057ea

Browse files
committed
Fix out-of-bounds read in libxc interface
1 parent 0ecb932 commit 84057ea

1 file changed

Lines changed: 32 additions & 24 deletions

File tree

source/source_hamilt/module_xc/libxc_setup.cpp

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -290,33 +290,41 @@ XC_Functional_Libxc::init_func(const std::vector<int> &func_id,
290290
funcs.push_back({}); // create placeholder
291291
xc_func_init(&funcs.back(), id, xc_polarized); // instantiate the XC term
292292

293-
// search for external parameters
294-
const std::vector<double> in_built_ext_params = in_built_xc_func_ext_params(id, hybrid_alpha, hse_omega);
295-
const std::vector<double> external_ext_params = external_xc_func_ext_params(id);
296-
// for temporary use, I name their size as n1 and n2
297-
const int n1 = in_built_ext_params.size();
298-
const int n2 = external_ext_params.size();
293+
// Search for external parameters. User-supplied parameters take precedence
294+
// over ABACUS built-in overrides.
295+
const std::vector<double> in_built_ext_params
296+
= in_built_xc_func_ext_params(id, hybrid_alpha, hse_omega);
297+
const std::vector<double> external_ext_params
298+
= external_xc_func_ext_params(id);
299+
const std::vector<double>& requested_ext_params
300+
= external_ext_params.empty() ? in_built_ext_params : external_ext_params;
299301

300-
// #ifdef __DEBUG // will the following assertion cause performance issue?
301-
// assert the number of parameters should be either zero or the value from
302-
// libxc function xc_func_info_get_n_ext_params, this is to avoid the undefined
303-
// behavior of illegal memory access
304-
const xc_func_info_type* info = xc_func_get_info(&funcs.back());
305-
const int nref = xc_func_info_get_n_ext_params(info);
306-
assert ((n1 == 0) || (n1 == nref) || (n2 == 0) || (n2 == nref));
307-
// #endif
302+
if (!requested_ext_params.empty())
303+
{
304+
const xc_func_info_type* info = xc_func_get_info(&funcs.back());
305+
const int nref = xc_func_info_get_n_ext_params(info);
308306

309-
// external overwrites in-built if the same functional id is found in both maps
310-
const double* xc_func_ext_params =
311-
(n2 > 0) ? external_ext_params.data() :
312-
(n1 > 0) ? in_built_ext_params.data() :
313-
nullptr; // nullptr if no external parameters are found
307+
// xc_func_set_ext_params() reads exactly nref entries. Never pass a
308+
// shorter buffer: Libxc may append new parameters in a newer release
309+
// (GGA_C_PBE gained _tscale in Libxc 7.1).
310+
if (requested_ext_params.size() > static_cast<std::size_t>(nref))
311+
{
312+
ModuleBase::WARNING_QUIT(
313+
"XC_Functional_Libxc::init_func",
314+
"Too many external parameters for Libxc functional id "
315+
+ std::to_string(id) + ": got "
316+
+ std::to_string(requested_ext_params.size())
317+
+ ", expected at most " + std::to_string(nref) + ".");
318+
}
314319

315-
// if there are no external parameters, do nothing, otherwise we set
316-
if(xc_func_ext_params != nullptr)
317-
{
318-
// set the external parameters
319-
xc_func_set_ext_params(&funcs.back(), const_cast<double*>(xc_func_ext_params));
320+
// Missing trailing parameters retain Libxc's own defaults. This is
321+
// backward- and forward-compatible when Libxc appends parameters.
322+
std::vector<double> complete_ext_params(
323+
nref, static_cast<double>(XC_EXT_PARAMS_DEFAULT));
324+
std::copy(requested_ext_params.begin(),
325+
requested_ext_params.end(),
326+
complete_ext_params.begin());
327+
xc_func_set_ext_params(&funcs.back(), complete_ext_params.data());
320328
}
321329
}
322330
return funcs;

0 commit comments

Comments
 (0)