From 878a739f3c3b516b0c5d08389c40a685aa4ab5ea Mon Sep 17 00:00:00 2001
From: Bastien Montagne <montagne29@wanadoo.fr>
Date: Sat, 8 Sep 2012 09:15:52 +0000
Subject: [PATCH] Fix [#32511] blender hangs on importing malformed ply file

Made a few refactoring/style cleanup of code here...
---
 io_mesh_ply/import_ply.py | 112 +++++++++++++++++++-------------------
 1 file changed, 55 insertions(+), 57 deletions(-)

diff --git a/io_mesh_ply/import_ply.py b/io_mesh_ply/import_ply.py
index f5c96d7bf..6c80a3900 100644
--- a/io_mesh_ply/import_ply.py
+++ b/io_mesh_ply/import_ply.py
@@ -148,68 +148,64 @@ def read(filepath):
                   b'double': 'd',
                   b'string': 's'}
     obj_spec = object_spec()
+    invalid_ply = (None, None, None)
 
-    file = open(filepath, 'rb')  # Only for parsing the header, not binary data
-    signature = file.readline()
+    with open(filepath, 'rb') as plyf:
+        signature = plyf.readline()
 
-    if not signature.startswith(b'ply'):
-        print('Signature line was invalid')
-        return None
+        if not signature.startswith(b'ply'):
+            print('Signature line was invalid')
+            return invalid_ply
 
-    while 1:
-        tokens = re.split(br'[ \r\n]+', file.readline())
+        valid_header = False
+        for line in plyf:
+            tokens = re.split(br'[ \r\n]+', line)
 
-        if len(tokens) == 0:
-            continue
-        if tokens[0] == b'end_header':
-            break
-        elif tokens[0] == b'comment':
-            if len(tokens) < 2:
+            if len(tokens) == 0:
                 continue
-            elif tokens[1] == b'TextureFile':
-                if len(tokens) < 4:
-                    print('Invalid texture line')
+            if tokens[0] == b'end_header':
+                valid_header = True
+                break
+            elif tokens[0] == b'comment':
+                if len(tokens) < 2:
+                    continue
+                elif tokens[1] == b'TextureFile':
+                    if len(tokens) < 4:
+                        print('Invalid texture line')
+                    else:
+                        texture = tokens[2]
+                continue
+            elif tokens[0] == b'obj_info':
+                continue
+            elif tokens[0] == b'format':
+                if len(tokens) < 3:
+                    print('Invalid format line')
+                    return invalid_ply
+                if tokens[1] not in format_specs:
+                    print('Unknown format', tokens[1])
+                    return invalid_ply
+                if tokens[2] != version:
+                    print('Unknown version', tokens[2])
+                    return invalid_ply
+                format = tokens[1]
+            elif tokens[0] == b'element':
+                if len(tokens) < 3:
+                    print(b'Invalid element line')
+                    return invalid_ply
+                obj_spec.specs.append(element_spec(tokens[1], int(tokens[2])))
+            elif tokens[0] == b'property':
+                if not len(obj_spec.specs):
+                    print('Property without element')
+                    return invalid_ply
+                if tokens[1] == b'list':
+                    obj_spec.specs[-1].properties.append(property_spec(tokens[4], type_specs[tokens[2]], type_specs[tokens[3]]))
                 else:
-                    texture = tokens[2]
-            continue
-        elif tokens[0] == b'obj_info':
-            continue
-        elif tokens[0] == b'format':
-            if len(tokens) < 3:
-                print('Invalid format line')
-                return None
-            if tokens[1] not in format_specs:
-                print('Unknown format', tokens[1])
-                return None
-            if tokens[2] != version:
-                print('Unknown version', tokens[2])
-                return None
-            format = tokens[1]
-        elif tokens[0] == b'element':
-            if len(tokens) < 3:
-                print(b'Invalid element line')
-                return None
-            obj_spec.specs.append(element_spec(tokens[1], int(tokens[2])))
-        elif tokens[0] == b'property':
-            if not len(obj_spec.specs):
-                print('Property without element')
-                return None
-            if tokens[1] == b'list':
-                obj_spec.specs[-1].properties.append(property_spec(tokens[4], type_specs[tokens[2]], type_specs[tokens[3]]))
-            else:
-                obj_spec.specs[-1].properties.append(property_spec(tokens[2], None, type_specs[tokens[1]]))
-
-    if format != b'ascii':
-        file.close()  # was ascii, now binary
-        file = open(filepath, 'rb')
+                    obj_spec.specs[-1].properties.append(property_spec(tokens[2], None, type_specs[tokens[1]]))
+        if not valid_header:
+            print("Invalid header ('end_header' line not found!)")
+            return invalid_ply
 
-        # skip the header...
-        while not file.readline().startswith(b'end_header'):
-            pass
-
-    obj = obj_spec.load(format_specs[format], file)
-
-    file.close()
+        obj = obj_spec.load(format_specs[format], plyf)
 
     return obj_spec, obj, texture
 
@@ -364,6 +360,8 @@ def load_ply(filepath):
     ply_name = bpy.path.display_name_from_filepath(filepath)
 
     mesh = load_ply_mesh(filepath, ply_name)
+    if not mesh:
+        return {'CANCELLED'}
 
     scn = bpy.context.scene
 
@@ -373,8 +371,8 @@ def load_ply(filepath):
     obj.select = True
 
     print('\nSuccessfully imported %r in %.3f sec' % (filepath, time.time() - t))
+    return {'FINISHED'}
 
 
 def load(operator, context, filepath=""):
-    load_ply(filepath)
-    return {'FINISHED'}
+    return load_ply(filepath)
-- 
GitLab