Fix a bug in CompressedRowSparseMatrix::AppendRows
The test for CompressedRowSparseMatrix::AppendRows tries to add
a matrix of size zero, which results in an invalid pointer deferencing
even though that pointer is never written to.
Change-Id: I97dba37082bd5dad242ae1af0447a9178cd92027
diff --git a/docs/source/version_history.rst b/docs/source/version_history.rst
index 664826c..87ad50e 100644
--- a/docs/source/version_history.rst
+++ b/docs/source/version_history.rst
@@ -27,6 +27,9 @@
Bug Fixes & Minor Changes
-------------------------
+#. Fix invalid memory access bug in
+ ``CompressedRowSparseMatrix::AppendRows`` when it was called with a
+ matrix of size zero.
#. Build position independent code when compiling Ceres statically
(Alexander Alekhin).
#. Fix a bug in DetectStructure (Johannes Schonberger).
diff --git a/internal/ceres/compressed_row_sparse_matrix.cc b/internal/ceres/compressed_row_sparse_matrix.cc
index 36f87a5..91d18bb 100644
--- a/internal/ceres/compressed_row_sparse_matrix.cc
+++ b/internal/ceres/compressed_row_sparse_matrix.cc
@@ -241,16 +241,24 @@
<< "The matrix being appended has: " << m.row_blocks().size()
<< " row blocks.";
+ if (m.num_rows() == 0) {
+ return;
+ }
+
if (cols_.size() < num_nonzeros() + m.num_nonzeros()) {
cols_.resize(num_nonzeros() + m.num_nonzeros());
values_.resize(num_nonzeros() + m.num_nonzeros());
}
// Copy the contents of m into this matrix.
- std::copy(m.cols(), m.cols() + m.num_nonzeros(), &cols_[num_nonzeros()]);
- std::copy(m.values(),
- m.values() + m.num_nonzeros(),
- &values_[num_nonzeros()]);
+ DCHECK_LT(num_nonzeros(), cols_.size());
+ if (m.num_nonzeros() > 0) {
+ std::copy(m.cols(), m.cols() + m.num_nonzeros(), &cols_[num_nonzeros()]);
+ std::copy(m.values(),
+ m.values() + m.num_nonzeros(),
+ &values_[num_nonzeros()]);
+ }
+
rows_.resize(num_rows_ + m.num_rows() + 1);
// new_rows = [rows_, m.row() + rows_[num_rows_]]
std::fill(rows_.begin() + num_rows_,