From 6747f2130e90ccf85f374e9d97df0e5ca6497229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org> Date: Fri, 1 Sep 2023 14:50:38 +0200 Subject: [PATCH] Perfect foresight: fix illegal memory read with bytecode + endval_steady The exogenous steady state vector was passed as a row-vector to evaluate_steady_state, thus leading to an incorrectly-sized matrix passed to bytecode when checking the steady state on the dynamic model (when different from the static model). --- matlab/evaluate_steady_state.m | 11 ++++++++++- .../perfect_foresight_solver.m | 6 +++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/matlab/evaluate_steady_state.m b/matlab/evaluate_steady_state.m index c23f562adc..0f48675f35 100644 --- a/matlab/evaluate_steady_state.m +++ b/matlab/evaluate_steady_state.m @@ -56,6 +56,15 @@ if isoctave && options.solve_algo == 11 error(['STEADY: you can''t use solve_algo = %u under Octave'],options.solve_algo) end +% To ensure that the z and zx matrices constructed by repmat and passed to bytecode +% are of the right size. +if size(ys_init, 2) > 1 + error('ys_init must be a column-vector') +end +if size(exo_ss, 2) > 1 + error('exo_ss must be a column-vector') +end + info = 0; check = 0; @@ -458,7 +467,7 @@ if M.static_and_dynamic_models_differ % computed on the *static* one if options.bytecode z = repmat(ys,1,M.maximum_lead + M.maximum_lag + 1); - zx = repmat([exo_ss'], M.maximum_lead + M.maximum_lag + 1, 1); + zx = repmat(exo_ss', M.maximum_lead + M.maximum_lag + 1, 1); r = bytecode('dynamic','evaluate', z, zx, params, ys, 1); else r = feval([M.fname '.sparse.dynamic_resid'], repmat(ys, 3, 1), exo_ss, params, ys); diff --git a/matlab/perfect-foresight-models/perfect_foresight_solver.m b/matlab/perfect-foresight-models/perfect_foresight_solver.m index d412afb301..97f53848fd 100644 --- a/matlab/perfect-foresight-models/perfect_foresight_solver.m +++ b/matlab/perfect-foresight-models/perfect_foresight_solver.m @@ -108,7 +108,7 @@ end if ~options_.simul.endval_steady && ~isempty(ys0_) terminal_condition_is_a_steady_state = true; for j = lastperiods - endval_resid = evaluate_static_model(oo_.endo_simul(:,j), oo_.exo_simul(j,:), M_.params, M_, options_); + endval_resid = evaluate_static_model(oo_.endo_simul(:,j), oo_.exo_simul(j,:)', M_.params, M_, options_); if norm(endval_resid, 'Inf') > options_.simul.steady_tolf terminal_condition_is_a_steady_state = false; break @@ -160,7 +160,7 @@ function local_success = create_scenario(share) % Effectively compute the terminal steady state for j = lastperiods % First use the terminal steady of the previous homotopy iteration as guess value (or the contents of the endval block if this is the first iteration) - [oo_.endo_simul(:, j), ~, info] = evaluate_steady_state(oo_.endo_simul(:, j), oo_.exo_simul(j, :), M_, options_, true); + [oo_.endo_simul(:, j), ~, info] = evaluate_steady_state(oo_.endo_simul(:, j), oo_.exo_simul(j, :)', M_, options_, true); if info(1) % If this fails, then try again using the initial steady state as guess value if isempty(ys0_) @@ -168,7 +168,7 @@ function local_success = create_scenario(share) else guess_value = ys0_; end - [oo_.endo_simul(:, j), ~, info] = evaluate_steady_state(guess_value, oo_.exo_simul(j, :), M_, options_, true); + [oo_.endo_simul(:, j), ~, info] = evaluate_steady_state(guess_value, oo_.exo_simul(j, :)', M_, options_, true); if info(1) % If this fails again, give up and restore last periods in oo_.endo_simul oo_.endo_simul(:, lastperiods) = saved_ss; -- GitLab