changeset 17189:ca5103ab0b21

check_gzip_magic before get_file_format (wrong type detection, bug #39652) * load-save.cc (get_file_format): call check_gzip_magic before get_file_format to avoid random LS_MAT_ASCII detections in gzipped files. * ls-mat-ascii.cc (looks_like_mat_ascii_file): New arg, IS which could also be a gzipped file, is now opened in the calling function. * ls-mat-ascii.h (looks_like_mat_ascii_file): New arg, IS.
author Andreas Weber <andy.weber.aw@gmail.com>
date Fri, 02 Aug 2013 19:48:34 +0200
parents fa724bdd52d0
children 397bbb215632
files libinterp/corefcn/load-save.cc libinterp/corefcn/ls-mat-ascii.cc libinterp/corefcn/ls-mat-ascii.h
diffstat 3 files changed, 47 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/load-save.cc
+++ b/libinterp/corefcn/load-save.cc
@@ -269,6 +269,20 @@
 
               if (! tmp.empty ())
                 retval = LS_ASCII;
+              else
+                {
+                  file.clear ();
+                  file.seekg (0, std::ios::beg);
+
+                  // FIXME -- looks_like_mat_ascii_file does not check to see
+                  // whether the file contains numbers.  It just skips comments and
+                  // checks for the same number of words on each line.  We may need
+                  // a better check here.  The best way to do that might be just
+                  // to try to read the file and see if it works.
+
+                  if (looks_like_mat_ascii_file (file, filename))
+                    retval = LS_MAT_ASCII;
+                }
             }
         }
     }
@@ -288,39 +302,36 @@
     return LS_HDF5;
 #endif /* HAVE_HDF5 */
 
-  std::ifstream file (fname.c_str ());
+#ifdef HAVE_ZLIB
+  use_zlib = check_gzip_magic (fname);
+#else
   use_zlib = false;
-
-  if (file)
-    {
-      retval = get_file_format (file, orig_fname);
-      file.close ();
-
-#ifdef HAVE_ZLIB
-      if (retval == LS_UNKNOWN && check_gzip_magic (fname))
-        {
-          gzifstream gzfile (fname.c_str ());
-          use_zlib = true;
-
-          if (gzfile)
-            {
-              retval = get_file_format (gzfile, orig_fname);
-              gzfile.close ();
-            }
-        }
 #endif
 
-      // FIXME -- looks_like_mat_ascii_file does not check to see
-      // whether the file contains numbers.  It just skips comments and
-      // checks for the same number of words on each line.  We may need
-      // a better check here.  The best way to do that might be just
-      // to try to read the file and see if it works.
-
-      if (retval == LS_UNKNOWN && looks_like_mat_ascii_file (fname))
-        retval = LS_MAT_ASCII;
+  if (! use_zlib)
+    {
+      std::ifstream file (fname.c_str ());
+      if (file)
+        {
+          retval = get_file_format (file, orig_fname);
+          file.close ();
+        }
+      else if (! quiet)
+        gripe_file_open ("load", orig_fname);
     }
-  else if (! quiet)
-    gripe_file_open ("load", orig_fname);
+#ifdef HAVE_ZLIB
+  else
+    {
+      gzifstream gzfile (fname.c_str ());
+      if (gzfile)
+        {
+          retval = get_file_format (gzfile, orig_fname);
+          gzfile.close ();
+        }
+      else if (! quiet)
+        gripe_file_open ("load", orig_fname);
+    }
+#endif
 
   return retval;
 }
--- a/libinterp/corefcn/ls-mat-ascii.cc
+++ b/libinterp/corefcn/ls-mat-ascii.cc
@@ -107,7 +107,7 @@
 }
 
 static void
-get_lines_and_columns (std::istream& is, 
+get_lines_and_columns (std::istream& is,
                        octave_idx_type& nr, octave_idx_type& nc,
                        const std::string& filename = std::string (),
                        bool quiet = false, bool check_numeric = false)
@@ -410,21 +410,14 @@
 }
 
 bool
-looks_like_mat_ascii_file (const std::string& filename)
+looks_like_mat_ascii_file (std::istream& is, const std::string& filename)
 {
   bool retval = false;
-
-  std::ifstream is (filename.c_str ());
+  octave_idx_type nr = 0;
+  octave_idx_type nc = 0;
 
-  if (is)
-    {
-      octave_idx_type nr = 0;
-      octave_idx_type nc = 0;
-
-      get_lines_and_columns (is, nr, nc, filename, true, true);
-
-      retval = (nr != 0 && nc != 0);
-    }
+  get_lines_and_columns (is, nr, nc, filename, true, true);
+  retval = (nr != 0 && nc != 0);
 
   return retval;
 }
--- a/libinterp/corefcn/ls-mat-ascii.h
+++ b/libinterp/corefcn/ls-mat-ascii.h
@@ -31,6 +31,6 @@
 save_mat_ascii_data (std::ostream& os, const octave_value& val_arg,
                      int precision, bool tabs = false);
 
-extern bool looks_like_mat_ascii_file (const std::string& filename);
+extern bool looks_like_mat_ascii_file (std::istream& is, const std::string& filename);
 
 #endif