From 1683baee00b9d68db7d51fef71325093b68e1391 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Fri, 21 Jan 2022 14:31:29 +0100
Subject: [PATCH] Add check to ensure that column indices in derivative
 matrices do not overflow

Closes: #89
(cherry picked from commit 5e8b478ccf795b4b4684b3c89e305cc083e3f0a3)
---
 src/DynamicModel.cc | 13 +++++++++++++
 src/StaticModel.cc  | 13 +++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 6079d1c8..2e984d4d 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -4333,6 +4333,19 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
   // Computes dynamic jacobian columns, must be done after computeDerivIDs()
   computeDynJacobianCols(jacobianExo);
 
+  /* In both MATLAB and Julia, tensors for higher-order derivatives are stored
+     in matrices whose columns correspond to variable multi-indices. Since we
+     currently are limited to 32-bit signed integers (hence 31 bits) for matrix
+     indices, check that we will not overflow (see #89). Note that such a check
+     is not needed for parameter derivatives, since tensors for those are not
+     stored as matrices. This check cannot be done before since
+     dynJacobianColsNbr is not yet set.*/
+  if (log2(dynJacobianColsNbr)*derivsOrder >= numeric_limits<int>::digits)
+    {
+      cerr << "ERROR: The dynamic derivatives matrix is too large. Please decrease the approximation order." << endl;
+      exit(EXIT_FAILURE);
+    }
+
   // Compute derivatives w.r. to all endogenous, and possibly exogenous and exogenous deterministic
   set<int> vars;
   for (auto &it : deriv_id_table)
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index daf54426..68fafdc6 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -1003,6 +1003,19 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
   equations.clear();
   copy(neweqs.begin(), neweqs.end(), back_inserter(equations));
 
+  /* In both MATLAB and Julia, tensors for higher-order derivatives are stored
+     in matrices whose columns correspond to variable multi-indices. Since we
+     currently are limited to 32-bit signed integers (hence 31 bits) for matrix
+     indices, check that we will not overflow (see #89). Note that such a check
+     is not needed for parameter derivatives, since tensors for those are not
+     stored as matrices. This check is implemented at this place for symmetry
+     with DynamicModel::computingPass(). */
+  if (log2(symbol_table.endo_nbr())*derivsOrder >= numeric_limits<int>::digits)
+    {
+      cerr << "ERROR: The static derivatives matrix is too large. Please decrease the approximation order." << endl;
+      exit(EXIT_FAILURE);
+    }
+
   // Compute derivatives w.r. to all endogenous
   set<int> vars;
   for (int i = 0; i < symbol_table.endo_nbr(); i++)
-- 
GitLab