Infinite loop in RebinToWorkspace due to inf X value
I found this with a sample workspace where I had accidentally created X values containing an infinite value. Rebinning to this workspace caused Mantid to enter an infinite loop and eventually run out of memory.

### Expected behavior
Mantid should not hang or throw an unexpected exception

### Actual behavior
Mantid enters an infinite loop because the check [here](https://github.com/mantidproject/mantid/blob/master/Framework/Kernel/src/VectorHelper.cpp#L65) always returns true due to the infinite value. The vector [here](https://github.com/mantidproject/mantid/blob/master/Framework/Kernel/src/VectorHelper.cpp#L85) continues to grow until it eventually throws `std::bad_alloc`.

### Steps to reproduce the behavior
```
CreateSampleWorkspace(OutputWorkspace='ws', WorkspaceType='Histogram', BankPixelWidth=3, PixelSpacing=0.1, NumBanks=1, Random=True, XMin=0, XMax=20, BinWidth=2, XUnit="Wavelength")
MoveInstrumentComponent(Workspace='ws', ComponentName='bank1', Y=0.026181)
ConvertUnits(InputWorkspace='ws',OutputWorkspace='ws_Q', Target='MomentumTransfer')
RebinToWorkspace(WorkspaceToRebin='ws_Q',WorkspaceToMatch='ws_Q', OutputWorkspace='ws_Q_rebinned')
```


### Platforms affected
Ubuntu 16.04, probably all
diff --git a/qt/python/mantidqtpython/mantidqtpython_def.sip b/qt/python/mantidqtpython/mantidqtpython_def.sip
index 18c1193d7a7..7c8f52894c3 100644
--- a/qt/python/mantidqtpython/mantidqtpython_def.sip
+++ b/qt/python/mantidqtpython/mantidqtpython_def.sip
@@ -1529,7 +1529,7 @@ class ProcessingAlgorithm
 #include "MantidQtWidgets/Common/DataProcessorUI/ProcessingAlgorithm.h"
 %End
 public:
-ProcessingAlgorithm(const QString &, const QString &, const QString &blacklist = "");
+ProcessingAlgorithm(const QString &, const QString &, int, const QString &blacklist = "");
 };
 
 class PostprocessingAlgorithm
diff --git a/qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp b/qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp
index 3cb871a8e63..17ea85b0dc6 100644
--- a/qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp
+++ b/qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp
@@ -73,7 +73,7 @@ ReflGenericDataProcessorPresenterFactory::create(int group) {
       /*The name of the algorithm */
       "ReflectometryReductionOneAuto",
       /*Prefixes to the output workspaces*/
-      std::vector<QString>{"IvsQ_binned_", "IvsQ_", "IvsLam_"},
+      std::vector<QString>{"IvsQ_binned_", "IvsQ_", "IvsLam_"}, 1,
       /*The blacklist*/
       std::set<QString>{"ThetaIn", "ThetaOut", "InputWorkspace",
                         "OutputWorkspace", "OutputWorkspaceBinned",
diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/ProcessingAlgorithm.h b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/ProcessingAlgorithm.h
index 194a685fb4d..133ff33ff24 100644
--- a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/ProcessingAlgorithm.h
+++ b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/ProcessingAlgorithm.h
@@ -42,9 +42,11 @@ public:
   ProcessingAlgorithm();
   // Constructor
   ProcessingAlgorithm(QString name, std::vector<QString> prefix,
+                      std::size_t postprocessedOutputPrefixIndex,
                       std::set<QString> blacklist = std::set<QString>());
   // Delegating constructor
   ProcessingAlgorithm(QString name, QString const &prefix,
+                      std::size_t postprocessedOutputPrefixIndex,
                       QString const &blacklist = "");
   // Destructor
   virtual ~ProcessingAlgorithm();
@@ -62,6 +64,10 @@ public:
   QString defaultOutputPropertyName() const;
   // The default input ws property
   QString defaultInputPropertyName() const;
+  // The prefix for the postprocessed output ws property
+  QString postprocessedOutputPrefix() const;
+  // The postprocessed output ws property
+  QString postprocessedOutputPropertyName() const;
   // The input properties
   std::vector<QString> inputProperties() const;
   // The output properties
@@ -70,6 +76,9 @@ public:
   std::vector<QString> prefixes() const;
 
 private:
+  bool isValidOutputPrefixIndex(std::size_t outputPrefixIndex) const;
+  void ensureValidPostprocessedOutput() const;
+  std::size_t m_postprocessedOutputPrefixIndex;
   // The prefix of the output workspace(s)
   std::vector<QString> m_prefix;
   // The names of the input workspace properties
diff --git a/qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp b/qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp
index 33ae9bbf33a..d42d17eb7b2 100644
--- a/qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp
+++ b/qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp
@@ -622,9 +622,9 @@ void GenericDataProcessorPresenter::postProcessGroup(
     const GroupData &groupData) {
   if (hasPostprocessing()) {
     const auto outputWSName = getPostprocessedWorkspaceName(groupData);
-    m_postprocessing->postProcessGroup(outputWSName,
-                                       m_processor.defaultOutputPropertyName(),
-                                       m_whitelist, groupData);
+    m_postprocessing->postProcessGroup(
+        outputWSName, m_processor.postprocessedOutputPropertyName(),
+        m_whitelist, groupData);
   }
 }
 
diff --git a/qt/widgets/common/src/DataProcessorUI/ProcessingAlgorithm.cpp b/qt/widgets/common/src/DataProcessorUI/ProcessingAlgorithm.cpp
index 8940b87f2c1..1aaa65903e0 100644
--- a/qt/widgets/common/src/DataProcessorUI/ProcessingAlgorithm.cpp
+++ b/qt/widgets/common/src/DataProcessorUI/ProcessingAlgorithm.cpp
@@ -8,14 +8,19 @@ namespace DataProcessor {
 * @param name : The name of this algorithm
 * @param prefix : The list of prefixes that will be used for the output
 * workspaces' names
+* @param postprocessedOutputPrefixIndex The zero based index of the prefix for
+* the workspace which should be postprocessed
 * @param blacklist : The list of properties we do not want to show
 */
-ProcessingAlgorithm::ProcessingAlgorithm(QString name,
-                                         std::vector<QString> prefix,
-                                         std::set<QString> blacklist)
+ProcessingAlgorithm::ProcessingAlgorithm(
+    QString name, std::vector<QString> prefix,
+    std::size_t postprocessedOutputPrefixIndex, std::set<QString> blacklist)
     : ProcessingAlgorithmBase(std::move(name), std::move(blacklist)),
+      m_postprocessedOutputPrefixIndex(postprocessedOutputPrefixIndex),
       m_prefix(std::move(prefix)) {
 
+  ensureValidPostprocessedOutput();
+
   m_inputProperties = getInputWsProperties();
   if (!m_inputProperties.size())
     throw std::invalid_argument("Invalid Processing algorithm. A valid "
@@ -42,11 +47,15 @@ ProcessingAlgorithm::ProcessingAlgorithm(QString name,
 * @param name : The name of this algorithm
 * @param prefix : The list of prefixes that will be used for the output
 * workspaces' names, as a string
+* @param postprocessedOutputPrefixIndex The zero based index of the prefix for
+* the workspace which should be postprocessed
 * @param blacklist : The list of properties we do not want to show, as a string
 */
-ProcessingAlgorithm::ProcessingAlgorithm(QString name, QString const &prefix,
-                                         QString const &blacklist)
+ProcessingAlgorithm::ProcessingAlgorithm(
+    QString name, QString const &prefix,
+    std::size_t postprocessedOutputPrefixIndex, QString const &blacklist)
     : ProcessingAlgorithm(std::move(name), convertStringToVector(prefix),
+                          postprocessedOutputPrefixIndex,
                           convertStringToSet(blacklist)) {}
 
 /**
@@ -96,6 +105,28 @@ QString ProcessingAlgorithm::defaultOutputPropertyName() const {
   return m_outputProperties[0];
 }
 
+bool ProcessingAlgorithm::isValidOutputPrefixIndex(
+    std::size_t outputPrefixIndex) const {
+  return outputPrefixIndex < m_prefix.size();
+}
+
+void ProcessingAlgorithm::ensureValidPostprocessedOutput() const {
+  if (!isValidOutputPrefixIndex(m_postprocessedOutputPrefixIndex))
+    throw std::runtime_error("Postprocessed output index must be a valid index "
+                             "into the prefix array.");
+}
+
+QString ProcessingAlgorithm::postprocessedOutputPrefix() const {
+  return m_prefix[m_postprocessedOutputPrefixIndex];
+}
+
+/** Returns the postprocessed output ws property. This is property
+ * name specified on construction.
+ */
+QString ProcessingAlgorithm::postprocessedOutputPropertyName() const {
+  return m_outputProperties[m_postprocessedOutputPrefixIndex];
+}
+
 /** Returns the default input ws property. This is just the first
  * property declared by the algorithm. Algorithm properties are
  * extracted in order, so this is the first in our list.
diff --git a/qt/widgets/common/test/DataProcessorUI/GenerateNotebookTest.h b/qt/widgets/common/test/DataProcessorUI/GenerateNotebookTest.h
index 5f7ea571ced..19f911f5ed8 100644
--- a/qt/widgets/common/test/DataProcessorUI/GenerateNotebookTest.h
+++ b/qt/widgets/common/test/DataProcessorUI/GenerateNotebookTest.h
@@ -44,7 +44,7 @@ private:
 
     return ProcessingAlgorithm(
         "ReflectometryReductionOneAuto",
-        std::vector<QString>{"IvsQ_binned_", "IvsQ_", "IvsLam_"},
+        std::vector<QString>{"IvsQ_binned_", "IvsQ_", "IvsLam_"}, 1,
         std::set<QString>{"ThetaIn", "ThetaOut", "InputWorkspace",
                           "OutputWorkspace", "OutputWorkspaceWavelength",
                           "FirstTransmissionRun", "SecondTransmissionRun"});
diff --git a/qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h b/qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h
index 31094046f1c..c6317dcaf4f 100644
--- a/qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h
+++ b/qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h
@@ -160,10 +160,9 @@ private:
   }
 
   ProcessingAlgorithm createReflectometryProcessor() {
-
     return ProcessingAlgorithm(
         "ReflectometryReductionOneAuto",
-        std::vector<QString>{"IvsQ_binned_", "IvsQ_", "IvsLam_"},
+        std::vector<QString>{"IvsQ_binned_", "IvsQ_", "IvsLam_"}, 1,
         std::set<QString>{"ThetaIn", "ThetaOut", "InputWorkspace",
                           "OutputWorkspace", "OutputWorkspaceWavelength",
                           "FirstTransmissionRun", "SecondTransmissionRun"});
@@ -199,7 +198,8 @@ private:
   void createTOFWorkspace(const QString &wsName,
                           const QString &runNumber = "") {
     auto tinyWS =
-        WorkspaceCreationHelper::create2DWorkspaceWithReflectometryInstrument();
+        WorkspaceCreationHelper::create2DWorkspaceWithReflectometryInstrument(
+            2000);
     auto inst = tinyWS->getInstrument();
 
     inst->getParameterMap()->addDouble(inst.get(), "I0MonitorIndex", 1.0);
@@ -1296,6 +1296,8 @@ public:
     auto ws =
         createPrefilledWorkspace("TestWorkspace", presenter->getWhiteList());
     ws->String(0, ThetaCol) = "";
+    ws->String(1, ThetaCol) = "";
+    ws->String(0, ScaleCol) = "";
     ws->String(1, ScaleCol) = "";
     expectGetWorkspace(mockDataProcessorView, Exactly(1), "TestWorkspace");
     presenter->notify(DataProcessorPresenter::OpenTableFlag);
@@ -1318,6 +1320,8 @@ public:
     TS_ASSERT_EQUALS(ws->String(0, RunCol), "12345");
     TS_ASSERT_EQUALS(ws->String(1, RunCol), "12346");
     TS_ASSERT(ws->String(0, ThetaCol) != "");
+    TS_ASSERT(ws->String(0, ScaleCol) != "");
+    TS_ASSERT(ws->String(1, ThetaCol) != "");
     TS_ASSERT(ws->String(1, ScaleCol) != "");
 
     // Check output and tidy up
@@ -3191,16 +3195,16 @@ public:
             "IvsQ_TOF_12345_TOF_12346");
     TSM_ASSERT_DELTA(
         "Logarithmic rebinning should have been applied, with param 0.04",
-        out->x(0)[0], 0.100, 1e-5);
+        out->x(0)[0], 0.01108, 1e-5);
     TSM_ASSERT_DELTA(
         "Logarithmic rebinning should have been applied, with param 0.04",
-        out->x(0)[1], 0.104, 1e-5);
+        out->x(0)[1], 0.01153, 1e-5);
     TSM_ASSERT_DELTA(
         "Logarithmic rebinning should have been applied, with param 0.04",
-        out->x(0)[2], 0.10816, 1e-5);
+        out->x(0)[2], 0.01199, 1e-5);
     TSM_ASSERT_DELTA(
         "Logarithmic rebinning should have been applied, with param 0.04",
-        out->x(0)[3], 0.11248, 1e-5);
+        out->x(0)[3], 0.01247, 1e-5);
 
     // Check output and tidy up
     checkWorkspacesExistInADS(m_defaultWorkspacesNoPrefix);
diff --git a/qt/widgets/common/test/DataProcessorUI/ProcessingAlgorithmTest.h b/qt/widgets/common/test/DataProcessorUI/ProcessingAlgorithmTest.h
index c4f12ae190f..1e1adfd32f8 100644
--- a/qt/widgets/common/test/DataProcessorUI/ProcessingAlgorithmTest.h
+++ b/qt/widgets/common/test/DataProcessorUI/ProcessingAlgorithmTest.h
@@ -35,9 +35,9 @@ public:
     // Currently ws must be either MatrixWorkspace or Workspace but this can be
     // changed
     std::vector<QString> prefix = {"run_"};
-    TS_ASSERT_THROWS_NOTHING(ProcessingAlgorithm("Rebin", prefix));
-    TS_ASSERT_THROWS_NOTHING(ProcessingAlgorithm("ExtractSpectra", prefix));
-    TS_ASSERT_THROWS_NOTHING(ProcessingAlgorithm("ConvertUnits", prefix));
+    TS_ASSERT_THROWS_NOTHING(ProcessingAlgorithm("Rebin", prefix, 0));
+    TS_ASSERT_THROWS_NOTHING(ProcessingAlgorithm("ExtractSpectra", prefix, 0));
+    TS_ASSERT_THROWS_NOTHING(ProcessingAlgorithm("ConvertUnits", prefix, 0));
   }
 
   void test_invalid_algorithms() {
@@ -45,10 +45,10 @@ public:
     std::vector<QString> prefix = {"IvsQ_"};
 
     // Algorithms with no input workspace properties
-    TS_ASSERT_THROWS(ProcessingAlgorithm("Stitch1DMany", prefix),
+    TS_ASSERT_THROWS(ProcessingAlgorithm("Stitch1DMany", prefix, 0),
                      std::invalid_argument);
     // Algorithms with no output workspace properties
-    TS_ASSERT_THROWS(ProcessingAlgorithm("SaveAscii", prefix),
+    TS_ASSERT_THROWS(ProcessingAlgorithm("SaveAscii", prefix, 0),
                      std::invalid_argument);
   }
   void test_ReflectometryReductionOneAuto() {
@@ -59,27 +59,30 @@ public:
     // We should provide three prefixes, one for each ws
     std::vector<QString> prefixes;
     prefixes.emplace_back("IvsQ_binned_");
+    prefixes.emplace_back("IvsQ_");
     // This should throw
     TS_ASSERT_THROWS(
-        ProcessingAlgorithm(algName, prefixes, std::set<QString>()),
+        ProcessingAlgorithm(algName, prefixes, 0, std::set<QString>()),
         std::invalid_argument);
 
-    prefixes.push_back("IvsQ_");
     // This should also throw
     TS_ASSERT_THROWS(
-        ProcessingAlgorithm(algName, prefixes, std::set<QString>()),
+        ProcessingAlgorithm(algName, prefixes, 0, std::set<QString>()),
         std::invalid_argument);
     // But this should be OK
-    prefixes.push_back("IvsLam_");
+    prefixes.emplace_back("IvsLam_");
     TS_ASSERT_THROWS_NOTHING(
-        ProcessingAlgorithm(algName, prefixes, std::set<QString>()));
+        ProcessingAlgorithm(algName, prefixes, 0, std::set<QString>()));
 
-    auto alg = ProcessingAlgorithm(algName, prefixes, std::set<QString>());
+    auto const postprocessedOutputPrefixIndex = 1;
+    auto alg = ProcessingAlgorithm(
+        algName, prefixes, postprocessedOutputPrefixIndex, std::set<QString>());
     TS_ASSERT_EQUALS(alg.name(), "ReflectometryReductionOneAuto");
     TS_ASSERT_EQUALS(alg.numberOfOutputProperties(), 3);
     TS_ASSERT_EQUALS(alg.prefix(0), "IvsQ_binned_");
     TS_ASSERT_EQUALS(alg.prefix(1), "IvsQ_");
     TS_ASSERT_EQUALS(alg.prefix(2), "IvsLam_");
+    TS_ASSERT_EQUALS(alg.postprocessedOutputPrefix(), "IvsQ_");
     TS_ASSERT_EQUALS(alg.inputPropertyName(0), "InputWorkspace");
     TS_ASSERT_EQUALS(alg.inputPropertyName(1), "FirstTransmissionRun");
     TS_ASSERT_EQUALS(alg.inputPropertyName(2), "SecondTransmissionRun");
diff --git a/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py b/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py
index 7423e1acce1..cbbe92c448b 100644
--- a/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py
+++ b/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py
@@ -322,8 +322,9 @@ class SANSDataProcessorGui(QtGui.QMainWindow, ui_sans_data_processor_window.Ui_S
                                       entry.show_value, entry.prefix)
 
         # Processing algorithm (mandatory)
+        unused_postprocessing_index = 0
         alg = MantidQt.MantidWidgets.DataProcessor.ProcessingAlgorithm(self._gui_algorithm_name,
-                                                                       'unused_', self._black_list)
+                                                                       'unused_', unused_postprocessing_index, self._black_list)
 
         self.data_processor_table = MantidQt.MantidWidgets.DataProcessor.QDataProcessorWidget(white_list, alg, self)
         self.data_processor_table.setForcedReProcessing(True)
['qt/scientific_interfaces/ISISReflectometry/ReflGenericDataProcessorPresenterFactory.cpp', 'qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h', 'scripts/Interface/ui/sans_isis/sans_data_processor_gui.py', 'qt/python/mantidqtpython/mantidqtpython_def.sip', 'qt/widgets/common/src/DataProcessorUI/ProcessingAlgorithm.cpp', 'qt/widgets/common/test/DataProcessorUI/GenerateNotebookTest.h', 'qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/ProcessingAlgorithm.h', 'qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp', 'qt/widgets/common/test/DataProcessorUI/ProcessingAlgorithmTest.h']