# HG changeset patch
# User Markus Mützel <markus.muetzel@gmx.de>
# Date 1600510197 -7200
#      Sat Sep 19 12:09:57 2020 +0200
# Node ID aa3d35f1898d07e6254bdead831cc162b184a4d0
# Parent  877e876338cc695a3752588d6abba201417165c1
Add functions to check for integer overflow on multiplication (bug #59094).

* liboctave/wrappers/intprops-wrappers.c, intprops-wrappers.h: New files with
  functions to wrap around gnulib macros.
* liboctave/wrappers/module.mk: Add new files to lists.
* bootstrap.conf: Add gnulib module "intprops".
* liboctave/util/lo-utils.cc, lo-utils.h (int_multiply_overflow): Add new
  (overloaded) functions to check for integer overflow on multiplication.
* libinterp/dldfcn/__ode15__.cc (IDA::set_up): Check if multiplication would
  overflow.

diff -r 877e876338cc -r aa3d35f1898d bootstrap.conf
--- a/bootstrap.conf	Fri Sep 18 15:51:20 2020 -0700
+++ b/bootstrap.conf	Sat Sep 19 12:09:57 2020 +0200
@@ -56,6 +56,7 @@
   getrusage
   gettimeofday
   glob
+  intprops
   isatty
   largefile
   link
diff -r 877e876338cc -r aa3d35f1898d libinterp/dldfcn/__ode15__.cc
--- a/libinterp/dldfcn/__ode15__.cc	Fri Sep 18 15:51:20 2020 -0700
+++ b/libinterp/dldfcn/__ode15__.cc	Sat Sep 19 12:09:57 2020 +0200
@@ -31,6 +31,7 @@
 #include "dMatrix.h"
 #include "dSparse.h"
 #include "f77-fcn.h"
+#include "lo-utils.h"
 
 #include "Cell.h"
 #include "defun-dld.h"
@@ -401,9 +402,9 @@
         // entries.
         m_sunJacMatrix = SUNSparseMatrix (m_num, m_num, 0, CSC_MAT);
 #    else
-        // FIXME: m_num*m_num might be larger than the largest
-        // octave_f77_int_type (integer overflow).  Consider using a save
-        // calculation method.
+        if (octave::math::int_multiply_overflow (m_num, m_num))
+          error ("Unable to allocate memory for sparse Jacobian");
+
         m_sunJacMatrix = SUNSparseMatrix (m_num, m_num, m_num*m_num, CSC_MAT);
 #    endif
         if (! m_sunJacMatrix)
diff -r 877e876338cc -r aa3d35f1898d liboctave/util/lo-utils.cc
--- a/liboctave/util/lo-utils.cc	Fri Sep 18 15:51:20 2020 -0700
+++ b/liboctave/util/lo-utils.cc	Sat Sep 19 12:09:57 2020 +0200
@@ -38,6 +38,7 @@
 
 #include "quit.h"
 
+#include "intprops-wrappers.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
@@ -424,4 +425,43 @@
     write_value<float> (os, imag (value));
     os << ')';
   }
+
+  namespace math
+  {
+    bool int_multiply_overflow (int a, int b)
+    {
+      return octave_i_multiply_overflow_wrapper (a, b);
+    }
+
+    bool int_multiply_overflow (long int a, long int b)
+    {
+      return octave_li_multiply_overflow_wrapper (a, b);
+    }
+
+#if defined (OCTAVE_HAVE_LONG_LONG_INT)
+    bool int_multiply_overflow (long long int a, long long int b)
+    {
+      return octave_lli_multiply_overflow_wrapper (a, b);
+    }
+#endif
+
+    bool int_multiply_overflow (unsigned int a, unsigned int b)
+    {
+      return octave_ui_multiply_overflow_wrapper (a, b);
+    }
+
+    bool int_multiply_overflow (unsigned long int a, unsigned long int b)
+    {
+      return octave_uli_multiply_overflow_wrapper (a, b);
+    }
+
+#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)
+    bool int_multiply_overflow (unsigned long long int a,
+                                unsigned long long int b)
+    {
+      return octave_ulli_multiply_overflow_wrapper (a, b);
+    }
+#endif
+
+  }
 }
diff -r 877e876338cc -r aa3d35f1898d liboctave/util/lo-utils.h
--- a/liboctave/util/lo-utils.h	Fri Sep 18 15:51:20 2020 -0700
+++ b/liboctave/util/lo-utils.h	Sat Sep 19 12:09:57 2020 +0200
@@ -123,6 +123,21 @@
   template <> void write_value (std::ostream& os, const Complex& value);
   template <> void write_value (std::ostream& os, const float& value);
   template <> void write_value (std::ostream& os, const FloatComplex& value);
+
+  namespace math
+  {
+    bool int_multiply_overflow (int a, int b);
+    bool int_multiply_overflow (long int a, long int b);
+#if defined (OCTAVE_HAVE_LONG_LONG_INT)
+    bool int_multiply_overflow (long long int a, long long int b);
+#endif
+    bool int_multiply_overflow (unsigned int a, unsigned int b);
+    bool int_multiply_overflow (unsigned long int a, unsigned long int b);
+#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)
+    bool int_multiply_overflow (unsigned long long int a,
+                                unsigned long long int b);
+#endif
+  }
 }
 
 OCTAVE_DEPRECATED (7, "use 'octave::read_value<T>' instead")
diff -r 877e876338cc -r aa3d35f1898d liboctave/wrappers/intprops-wrappers.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/intprops-wrappers.c	Sat Sep 19 12:09:57 2020 +0200
@@ -0,0 +1,75 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2020 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Octave is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Octave; see the file COPYING.  If not, see
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#include "intprops.h"
+
+#include "intprops-wrappers.h"
+
+// The *_OVERFLOW macros are provided by gnulib.  We don't include gnulib
+// headers directly in Octave's C++ source files to avoid problems that
+// may be caused by the way that gnulib overrides standard library
+// functions.
+
+int
+octave_i_multiply_overflow_wrapper (int a, int b)
+{
+  return INT_MULTIPLY_OVERFLOW (a, b);
+}
+
+int
+octave_li_multiply_overflow_wrapper (long int a, long int b)
+{
+  return INT_MULTIPLY_OVERFLOW (a, b);
+}
+
+#if defined (OCTAVE_HAVE_LONG_LONG_INT)
+int
+octave_lli_multiply_overflow_wrapper (long long int a, long long int b)
+{
+  return INT_MULTIPLY_OVERFLOW (a, b);
+}
+#endif
+
+int
+octave_ui_multiply_overflow_wrapper (unsigned int a, unsigned int b)
+{
+  return INT_MULTIPLY_OVERFLOW (a, b);
+}
+
+int
+octave_uli_multiply_overflow_wrapper (unsigned long int a,
+                                      unsigned long int b)
+{
+  return INT_MULTIPLY_OVERFLOW (a, b);
+}
+
+#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)
+int
+octave_ulli_multiply_overflow_wrapper (unsigned long long int a,
+                                       unsigned long long int b)
+{
+  return INT_MULTIPLY_OVERFLOW (a, b);
+}
+#endif
diff -r 877e876338cc -r aa3d35f1898d liboctave/wrappers/intprops-wrappers.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/liboctave/wrappers/intprops-wrappers.h	Sat Sep 19 12:09:57 2020 +0200
@@ -0,0 +1,62 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2020 The Octave Project Developers
+//
+// See the file COPYRIGHT.md in the top-level directory of this
+// distribution or <https://octave.org/copyright/>.
+//
+// This file is part of Octave.
+//
+// Octave is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Octave is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Octave; see the file COPYING.  If not, see
+// <https://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////
+
+#if ! defined (octave_localcharset_wrapper_h)
+#define octave_localcharset_wrapper_h 1
+
+#include "octave-config.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+// These functions return 1 if the operation between the input arguments would
+// overflow.
+
+extern int octave_i_multiply_overflow_wrapper (int a, int b);
+
+extern int octave_li_multiply_overflow_wrapper (long int a, long int b);
+
+#  if defined (OCTAVE_HAVE_LONG_LONG_INT)
+extern int octave_lli_multiply_overflow_wrapper (long long int a,
+                                                 long long int b);
+#  endif
+
+extern int octave_ui_multiply_overflow_wrapper (unsigned int a,
+                                                unsigned int b);
+
+extern int octave_uli_multiply_overflow_wrapper (unsigned long int a,
+                                                 unsigned long int b);
+
+#  if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)
+extern int octave_ulli_multiply_overflow_wrapper (unsigned long long int a,
+                                                  unsigned long long int b);
+#  endif
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
diff -r 877e876338cc -r aa3d35f1898d liboctave/wrappers/module.mk
--- a/liboctave/wrappers/module.mk	Fri Sep 18 15:51:20 2020 -0700
+++ b/liboctave/wrappers/module.mk	Sat Sep 19 12:09:57 2020 +0200
@@ -12,6 +12,7 @@
   %reldir%/glob-wrappers.h \
   %reldir%/hash-wrappers.h \
   %reldir%/iconv-wrappers.h \
+  %reldir%/intprops-wrappers.h \
   %reldir%/localcharset-wrapper.h \
   %reldir%/math-wrappers.h \
   %reldir%/mkostemp-wrapper.h \
@@ -54,6 +55,7 @@
   %reldir%/glob-wrappers.c \
   %reldir%/hash-wrappers.c \
   %reldir%/iconv-wrappers.c \
+  %reldir%/intprops-wrappers.c \
   %reldir%/localcharset-wrapper.c \
   %reldir%/math-wrappers.c \
   %reldir%/mkostemp-wrapper.c \
