changeset 1192:9884efa1f88a spectrogram-minor-refactor

Fix potential crash in Dense3dModelPeakCache owing to combination of wrong width calculation and wrong handling of width overrun
author Chris Cannam
date Thu, 14 Jul 2016 14:49:04 +0100
parents 6d09ad2ab21f
children 927d329252bf
files data/model/Dense3DModelPeakCache.cpp data/model/Dense3DModelPeakCache.h
diffstat 2 files changed, 23 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/data/model/Dense3DModelPeakCache.cpp	Wed Jul 13 13:06:28 2016 +0100
+++ b/data/model/Dense3DModelPeakCache.cpp	Thu Jul 14 14:49:04 2016 +0100
@@ -88,15 +88,29 @@
     Profiler profiler("Dense3DModelPeakCache::fillColumn");
 
     if (!in_range_for(m_coverage, column)) {
-        // see note in sourceModelChanged
-        if (m_coverage.size() > 0) m_coverage[m_coverage.size()-1] = false;
+        if (m_coverage.size() > 0) {
+            // The last peak may have come from an incomplete read, which
+            // may since have been filled, so reset it
+            m_coverage[m_coverage.size()-1] = false;
+        }
         m_coverage.resize(column + 1, false);
     }
 
+    int sourceWidth = m_source->getWidth();
+    
     Column peak;
     int n = 0;
     for (int i = 0; i < m_columnsPerPeak; ++i) {
-        Column here = m_source->getColumn(column * m_columnsPerPeak + i);
+
+        int sourceColumn = column * m_columnsPerPeak + i;
+        if (sourceColumn >= sourceWidth) break;
+        
+        Column here = m_source->getColumn(sourceColumn);
+
+//        cerr << "Dense3DModelPeakCache::fillColumn(" << column << "): source col "
+//             << sourceColumn << " of " << sourceWidth
+//             << " returned " << here.size() << " elts" << endl;
+        
         if (i == 0) {
             peak = here;
             n = int(peak.size());
--- a/data/model/Dense3DModelPeakCache.h	Wed Jul 13 13:06:28 2016 +0100
+++ b/data/model/Dense3DModelPeakCache.h	Thu Jul 14 14:49:04 2016 +0100
@@ -53,7 +53,12 @@
     }
     
     virtual int getWidth() const {
-        return m_source->getWidth() / m_columnsPerPeak + 1;
+        int sourceWidth = m_source->getWidth();
+        if ((sourceWidth % m_columnsPerPeak) == 0) {
+            return sourceWidth / m_columnsPerPeak;
+        } else {
+            return sourceWidth / m_columnsPerPeak + 1;
+        }
     }
 
     virtual int getHeight() const {