From af7f54bc8b59bd9283a3a91f9bc1f930ad25e123 Mon Sep 17 00:00:00 2001
From: Federico Montesino Pouzols <federico.montesino-pouzols@stfc.ac.uk>
Date: Mon, 19 Oct 2015 20:50:21 +0100
Subject: [PATCH] check potentially large file section sizes read from file, re
 #14028

---
 MantidPlot/src/origin/OPJFile.cpp | 70 +++++++++++++++++++++++++++----
 MantidPlot/src/origin/OPJFile.h   |  8 ++--
 2 files changed, 65 insertions(+), 13 deletions(-)

diff --git a/MantidPlot/src/origin/OPJFile.cpp b/MantidPlot/src/origin/OPJFile.cpp
index 73c397f65f2..b251bfcbde2 100644
--- a/MantidPlot/src/origin/OPJFile.cpp
+++ b/MantidPlot/src/origin/OPJFile.cpp
@@ -713,6 +713,18 @@ int OPJFile::ParseFormatNew() {
   char vers[5];
   vers[4]=0;
 
+  // get file size
+  int file_size = 0;
+  {
+    int rv = fseek(f, 0 , SEEK_END);
+    if (rv < 0)
+      fprintf(debug, "Error: could not move to the end of the file\n");
+    file_size = ftell(f);
+    rv = fseek(f, 0, SEEK_SET);
+    if (rv < 0)
+      fprintf(debug, "Error: could not move to the beginning of the file\n");
+  }
+
   // get version
   fseek(f,0x7,SEEK_SET);
   fread(&vers,4,1,f);
@@ -1160,13 +1172,13 @@ int OPJFile::ParseFormatNew() {
     fseek(f,POS,SEEK_SET);
 
     if(compareSpreadnames(object_name)!=-1)
-      readSpreadInfo(f, debug);
+      readSpreadInfo(f, file_size, debug);
     else if(compareMatrixnames(object_name)!=-1)
-      readMatrixInfo(f, debug);
+      readMatrixInfo(f, file_size, debug);
     else if(compareExcelnames(object_name)!=-1)
-      readExcelInfo(f, debug);
+      readExcelInfo(f, file_size, debug);
     else
-      readGraphInfo(f, debug);
+      readGraphInfo(f, file_size, debug);
   }
 
 
@@ -1276,7 +1288,7 @@ int OPJFile::ParseFormatNew() {
   return 0;
 }
 
-void OPJFile::readSpreadInfo(FILE *f, FILE *debug)
+void OPJFile::readSpreadInfo(FILE *f, int file_size, FILE *debug)
 {
   int POS=int(ftell(f));
 
@@ -1334,6 +1346,12 @@ void OPJFile::readSpreadInfo(FILE *f, FILE *debug)
         fflush(debug);
       }
 
+      if (file_size < sec_size) {
+        fprintf(debug, "Error in readSpread: found section size (%d) bigger than total file size: %d\n", sec_size, file_size);
+        fflush(debug);
+        return;
+      }
+
     //section_body_1
       LAYER+=0x5;
       fseek(f,LAYER,SEEK_SET);
@@ -1507,7 +1525,7 @@ void OPJFile::readSpreadInfo(FILE *f, FILE *debug)
   fseek(f,POS,SEEK_SET);
 }
 
-void OPJFile::readExcelInfo(FILE *f, FILE *debug)
+void OPJFile::readExcelInfo(FILE *f, int file_size, FILE *debug)
 {
   int POS=int(ftell(f));
 
@@ -1568,6 +1586,12 @@ void OPJFile::readExcelInfo(FILE *f, FILE *debug)
         fflush(debug);
       }
 
+      if (file_size < sec_size) {
+        fprintf(debug, "Error in readExcel: found section size (%d) bigger than total file size: %d\n", sec_size, file_size);
+        fflush(debug);
+        return;
+    }
+
     //section_body_1
       LAYER+=0x5;
       fseek(f,LAYER,SEEK_SET);
@@ -1748,7 +1772,7 @@ void OPJFile::readExcelInfo(FILE *f, FILE *debug)
   fseek(f,POS,SEEK_SET);
 }
 
-void OPJFile::readMatrixInfo(FILE *f, FILE *debug)
+void OPJFile::readMatrixInfo(FILE *f, int file_size, FILE *debug)
 {
   int POS=int(ftell(f));
 
@@ -1824,7 +1848,13 @@ void OPJFile::readMatrixInfo(FILE *f, FILE *debug)
       fflush(debug);
     }
 
-  //section_body_1
+    if (file_size < sec_size) {
+        fprintf(debug, "Error in readMatrix: found section size (%d) bigger than total file size: %d\n", sec_size, file_size);
+        fflush(debug);
+        return;
+    }
+
+    //section_body_1
     LAYER+=0x5;
     //check if it is a formula
     if(0==strcmp(sec_name,"MV"))
@@ -1909,7 +1939,7 @@ void OPJFile::readMatrixInfo(FILE *f, FILE *debug)
 }
 
 
-void OPJFile::readGraphInfo(FILE *f, FILE *debug)
+void OPJFile::readGraphInfo(FILE *f, int file_size, FILE *debug)
 {
   int POS=int(ftell(f));
 
@@ -2130,6 +2160,12 @@ void OPJFile::readGraphInfo(FILE *f, FILE *debug)
       fread(&sec_size,4,1,f);
       if(IsBigEndian()) SwapBytes(sec_size);
 
+      if (file_size < sec_size) {
+        fprintf(debug, "Error in readGraph: found section size (%d) bigger than total file size: %d\n", sec_size, file_size);
+        fflush(debug);
+        return;
+    }
+
     //section_body_2
       LAYER+=0x5;
       //check if it is a axis or legend
@@ -2938,6 +2974,17 @@ void OPJFile::readProjectTreeFolder(FILE *f, FILE *debug, tree<projectNode>::ite
 {
   int POS=int(ftell(f));
 
+  int file_size = 0;
+  {
+    int rv = fseek(f, 0 , SEEK_END);
+    if (rv < 0)
+      fprintf(debug, "Error: could not move to the end of the file\n");
+    file_size = ftell(f);
+    rv = fseek(f, POS, SEEK_SET);
+    if (rv < 0)
+      fprintf(debug, "Error: could not move to the beginning of the file\n");
+  }
+
   double creation_date, modification_date;
 
   POS+=5;
@@ -2977,6 +3024,10 @@ void OPJFile::readProjectTreeFolder(FILE *f, FILE *debug, tree<projectNode>::ite
   if(IsBigEndian()) SwapBytes(objectcount);
   POS+=5+5;
 
+  // there cannot be more objects than bytes
+  if (objectcount > file_size)
+    objectcount = 0;
+
   for(int i=0; i<objectcount; ++i)
   {
     POS+=5;
@@ -2997,6 +3048,7 @@ void OPJFile::readProjectTreeFolder(FILE *f, FILE *debug, tree<projectNode>::ite
   }
   fseek(f,POS,SEEK_SET);
   fread(&objectcount,4,1,f);
+
   if(IsBigEndian()) SwapBytes(objectcount);
   fseek(f,1,SEEK_CUR);
   for(int i=0; i<objectcount; ++i)
diff --git a/MantidPlot/src/origin/OPJFile.h b/MantidPlot/src/origin/OPJFile.h
index 7f4f529ad29..75ffe32caa3 100644
--- a/MantidPlot/src/origin/OPJFile.h
+++ b/MantidPlot/src/origin/OPJFile.h
@@ -782,10 +782,10 @@ private:
 	int compareFunctionnames(const char *sname) const;				//!< returns matching function index
 	std::vector<std::string> findDataByIndex(int index) const;
 	std::string findObjectByIndex(int index);
-	void readSpreadInfo(FILE *fopj, FILE *fdebug);
-	void readExcelInfo(FILE *f, FILE *debug);
-	void readMatrixInfo(FILE *fopj, FILE *fdebug);
-	void readGraphInfo(FILE *fopj, FILE *fdebug);
+	void readSpreadInfo(FILE *fopj, int file_size, FILE *fdebug);
+	void readExcelInfo(FILE *f, int file_size, FILE *debug);
+	void readMatrixInfo(FILE *fopj, int file_size, FILE *fdebug);
+	void readGraphInfo(FILE *fopj, int file_size, FILE *fdebug);
 	void readGraphGridInfo(graphGrid &grid, FILE *fopj, int pos);
 	void readGraphAxisBreakInfo(graphAxisBreak &axis_break, FILE *fopj, int pos);
 	void readGraphAxisFormatInfo(graphAxisFormat &format, FILE *fopj, int pos);
-- 
GitLab