From cf14e30aa204ed0814aeb2023bfd9f25309d68b3 Mon Sep 17 00:00:00 2001 From: Krishna Gadepalli <34969407+kkg4theweb@users.noreply.github.com> Date: Thu, 3 Jun 2021 12:37:07 -0700 Subject: [PATCH] Fix use-after-free issue with the global 'default_material' (issue 1483) (#1583) * Fix use-after-free issue with the global 'default_material' (issue 1483) Signed-off-by: Krishna Gadepalli * Make all copy_from methods take const ref. * use size_t instead of 'int' when computing size for memcpy (update existing update_weights too) --- src/material_data.hpp | 90 ++++++++++++++++++++++++++++++++++++++++++- src/meepgeom.cpp | 41 ++++++++++++++++++-- src/meepgeom.hpp | 1 + 3 files changed, 127 insertions(+), 5 deletions(-) diff --git a/src/material_data.hpp b/src/material_data.hpp index 2cc3690fe..b9200c5fc 100644 --- a/src/material_data.hpp +++ b/src/material_data.hpp @@ -54,6 +54,18 @@ struct transition { } bool operator!=(const transition &other) const { return !(*this == other); } + + // NOTE: We could add a copy constructor but that requires a lot more + // code cleanup! + void copy_from(const transition& from) { + from_level = from.from_level; + to_level = from.to_level; + transition_rate = from.transition_rate; + frequency = from.frequency; + sigma_diag = from.sigma_diag; + gamma = from.gamma; + pumping_rate = from.pumping_rate; + } }; typedef struct susceptibility_struct { @@ -69,6 +81,27 @@ typedef struct susceptibility_struct { bool is_file; std::vector transitions; std::vector initial_populations; + + void copy_from(const susceptibility_struct& from) { + sigma_offdiag = from.sigma_offdiag; + sigma_diag = from.sigma_diag; + bias = from.bias; + frequency = from.frequency; + gamma = from.gamma; + alpha = from.alpha; + noise_amp = from.noise_amp; + drude = from.drude; + saturated_gyrotropy = from.saturated_gyrotropy; + is_file = from.is_file; + + transitions.resize(from.transitions.size()); + for (int i = 0; i < transitions.size(); ++i) { + transitions[i].copy_from(from.transitions[i]); + } + initial_populations.assign(from.initial_populations.begin(), + from.initial_populations.end()); + } + } susceptibility; struct susceptibility_list { @@ -76,6 +109,14 @@ struct susceptibility_list { susceptibility *items; susceptibility_list() : num_items(0), items(NULL) {} + + void copy_from(const susceptibility_list& from) { + num_items = from.num_items; + items = new susceptibility[num_items]; + for (int i = 0; i < num_items; ++i) { + items[i].copy_from(from.items[i]); + } + } }; struct medium_struct { @@ -139,6 +180,23 @@ struct medium_struct { B_conductivity_diag.y = 0; B_conductivity_diag.z = 0; } + + void copy_from(const medium_struct& from) { + epsilon_diag = from.epsilon_diag; + epsilon_offdiag = from.epsilon_offdiag; + mu_diag = from.mu_diag; + mu_offdiag = from.mu_offdiag; + + E_susceptibilities.copy_from(from.E_susceptibilities); + H_susceptibilities.copy_from(from.H_susceptibilities); + + E_chi2_diag = from.E_chi2_diag; + E_chi3_diag = from.E_chi3_diag; + H_chi2_diag = from.H_chi2_diag; + H_chi3_diag = from.H_chi3_diag; + D_conductivity_diag = from.D_conductivity_diag; + B_conductivity_diag = from.B_conductivity_diag; + } }; // prototype for user-defined material function, @@ -217,7 +275,8 @@ struct material_data { enum { U_MIN = 0, U_PROD = 1, U_MEAN = 2, U_DEFAULT = 3 } material_grid_kinds; material_data() - : which_subclass(MEDIUM), medium(), user_func(NULL), user_data(NULL), epsilon_data(NULL), + : which_subclass(MEDIUM), medium(), user_func(NULL), user_data(NULL), + do_averaging(false), epsilon_data(NULL), weights(NULL), medium_1(), medium_2() { epsilon_dims[0] = 0; epsilon_dims[1] = 0; @@ -227,6 +286,35 @@ struct material_data { grid_size.z = 0; material_grid_kinds = U_DEFAULT; } + + void copy_from(const material_data& from) { + which_subclass = from.which_subclass; + medium.copy_from(from.medium); + + user_func = from.user_func; + // NOTE: the user_data field here opaque/void - so this is the best we can do. + user_data = from.user_data; + do_averaging = from.do_averaging; + + memcpy(epsilon_dims, from.epsilon_dims, 3 * sizeof(size_t)); + if (from.epsilon_data) { + size_t N = from.epsilon_dims[0] * from.epsilon_dims[1] * from.epsilon_dims[2]; + epsilon_data = new double[N]; + memcpy(epsilon_data, from.epsilon_data, N * sizeof(double)); + } + + grid_size = from.grid_size; + if (from.weights) { + size_t N = from.grid_size.x * from.grid_size.y * from.grid_size.z; + weights = new double[N]; + memcpy(weights, from.weights, N * sizeof(double)); + } + + medium_1.copy_from(medium_1); + medium_2.copy_from(medium_2); + beta = from.beta; + eta = from.eta; + } }; typedef material_data *material_type; diff --git a/src/meepgeom.cpp b/src/meepgeom.cpp index eaf9380af..cee02306b 100644 --- a/src/meepgeom.cpp +++ b/src/meepgeom.cpp @@ -28,6 +28,20 @@ namespace meep_geom { material_data vacuum_material_data; material_type vacuum = &vacuum_material_data; +static void set_default_material(material_type _default_material) { + if (default_material != NULL) { + material_free((material_type)default_material); + delete (material_type)default_material; + default_material = NULL; + } + + if (_default_material != NULL) { + material_type new_material = new material_data(); + new_material->copy_from(*_default_material); + default_material = (void *)new_material; + } +} + void check_offdiag(medium_struct *m) { if (m->epsilon_offdiag.x.im != 0 || m->epsilon_offdiag.y.im != 0 || m->epsilon_offdiag.z.im != 0 || m->mu_offdiag.x.im != 0 || m->mu_offdiag.y.im != 0 || @@ -105,6 +119,25 @@ void material_gc(material_type m) { susceptibility_list_gc(&(m->medium_2.H_susceptibilities)); } +void material_free(material_type m) { + if (!m) return; + + susceptibility_list_gc(&(m->medium.E_susceptibilities)); + susceptibility_list_gc(&(m->medium.H_susceptibilities)); + susceptibility_list_gc(&(m->medium_1.E_susceptibilities)); + susceptibility_list_gc(&(m->medium_1.H_susceptibilities)); + susceptibility_list_gc(&(m->medium_2.E_susceptibilities)); + susceptibility_list_gc(&(m->medium_2.H_susceptibilities)); + + // NOTE: We do not delete the user_data field here since it is an opaque/void + // object so will assume that the caller keeps track of its lifetime. + delete[] m->epsilon_data; + m->epsilon_data = NULL; + + delete[] m->weights; + m->weights = NULL; +} + bool material_type_equal(const material_type m1, const material_type m2) { if (m1 == m2) return true; if (m1->which_subclass != m2->which_subclass) return false; @@ -554,7 +587,7 @@ void epsilon_material_grid(material_data *md, double u) { // return material of the point p from the file (assumed already read) void epsilon_file_material(material_data *md, vector3 p) { - default_material = (void *)md; + set_default_material(md); if (md->which_subclass != material_data::MATERIAL_FILE) meep::abort("epsilon-input-file only works with a type=file default-material"); @@ -1806,7 +1839,7 @@ void set_materials_from_geometry(meep::structure *s, geometric_object_list g, ve _default_material->which_subclass != material_data::PERFECT_METAL) { check_offdiag(&_default_material->medium); } - default_material = _default_material; + set_default_material(_default_material); ensure_periodicity = _ensure_periodicity; meep::grid_volume gv = s->gv; double resolution = gv.a; @@ -1936,7 +1969,7 @@ material_type make_material_grid(bool do_averaging, double beta, double eta) { } void update_weights(material_type matgrid, double *weights) { - int N = matgrid->grid_size.x * matgrid->grid_size.y * matgrid->grid_size.z; + size_t N = matgrid->grid_size.x * matgrid->grid_size.y * matgrid->grid_size.z; memcpy(matgrid->weights, weights, N * sizeof(double)); } @@ -2061,7 +2094,7 @@ void init_libctl(material_type default_mat, bool ensure_per, meep::grid_volume * vector3 cell_size, vector3 cell_center, geometric_object_list *geom_) { geom_initialize(); - default_material = default_mat; + set_default_material(default_mat); ensure_periodicity = ensure_per; geometry_center = cell_center; dimensions = meep::number_of_directions(gv->dim); diff --git a/src/meepgeom.hpp b/src/meepgeom.hpp index 5805e39d7..ad9aa3662 100644 --- a/src/meepgeom.hpp +++ b/src/meepgeom.hpp @@ -178,6 +178,7 @@ bool susceptibility_equal(const susceptibility &s1, const susceptibility &s2); bool susceptibility_list_equal(const susceptibility_list &s1, const susceptibility_list &s2); bool medium_struct_equal(const medium_struct *m1, const medium_struct *m2); void material_gc(material_type m); +void material_free(material_type m); bool material_type_equal(const material_type m1, const material_type m2); bool is_material_grid(material_type mt); bool is_material_grid(void *md);