From 53a7864c48a2b2fc226c69e9184d7cc8e6b36b6d Mon Sep 17 00:00:00 2001 From: Adam Shapiro Date: Tue, 23 Feb 2021 21:32:39 +0000 Subject: [PATCH] Fixed sparse conservativeResize() when both num cols and rows decreased. The previous implementation caused a buffer overflow trying to calculate non- zero counts for columns that no longer exist. (cherry picked from commit 2ac0b787399df718dc61219145f44a6ae99813aa) (cherry picked from commit f4b67691c42952b44ce7dae62f5c18ed93b53521) --- Eigen/src/SparseCore/SparseMatrix.h | 6 ++++-- test/sparse_basic.cpp | 22 +++++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h index 88a904059..8c7a18295 100644 --- a/Eigen/src/SparseCore/SparseMatrix.h +++ b/Eigen/src/SparseCore/SparseMatrix.h @@ -577,10 +577,12 @@ class SparseMatrix else if (innerChange < 0) { // Inner size decreased: allocate a new m_innerNonZeros - m_innerNonZeros = static_cast(std::malloc((m_outerSize+outerChange+1) * sizeof(StorageIndex))); + m_innerNonZeros = static_cast(std::malloc((m_outerSize + outerChange) * sizeof(StorageIndex))); if (!m_innerNonZeros) internal::throw_std_bad_alloc(); - for(Index i = 0; i < m_outerSize; i++) + for(Index i = 0; i < m_outerSize + (std::min)(outerChange, Index(0)); i++) m_innerNonZeros[i] = m_outerIndex[i+1] - m_outerIndex[i]; + for(Index i = m_outerSize; i < m_outerSize + outerChange; i++) + m_innerNonZeros[i] = 0; } // Change the m_innerNonZeros in case of a decrease of inner size diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 43318da79..08d598462 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -537,30 +537,38 @@ template void sparse_basic(const SparseMatrixType& re inc.push_back(std::pair(3,2)); inc.push_back(std::pair(3,0)); inc.push_back(std::pair(0,3)); - + inc.push_back(std::pair(0,-1)); + inc.push_back(std::pair(-1,0)); + inc.push_back(std::pair(-1,-1)); + for(size_t i = 0; i< inc.size(); i++) { StorageIndex incRows = inc[i].first; StorageIndex incCols = inc[i].second; SparseMatrixType m1(rows, cols); DenseMatrix refMat1 = DenseMatrix::Zero(rows, cols); initSparse(density, refMat1, m1); - + + SparseMatrixType m2 = m1; + m2.makeCompressed(); + m1.conservativeResize(rows+incRows, cols+incCols); + m2.conservativeResize(rows+incRows, cols+incCols); refMat1.conservativeResize(rows+incRows, cols+incCols); if (incRows > 0) refMat1.bottomRows(incRows).setZero(); if (incCols > 0) refMat1.rightCols(incCols).setZero(); - + VERIFY_IS_APPROX(m1, refMat1); - + VERIFY_IS_APPROX(m2, refMat1); + // Insert new values if (incRows > 0) m1.insert(m1.rows()-1, 0) = refMat1(refMat1.rows()-1, 0) = 1; if (incCols > 0) m1.insert(0, m1.cols()-1) = refMat1(0, refMat1.cols()-1) = 1; - + VERIFY_IS_APPROX(m1, refMat1); - - + + } }