Explorar el Código

Detect invalid content (#458)

Lutz Roeder hace 2 años
padre
commit
1b2e151eec
Se han modificado 5 ficheros con 75 adiciones y 52 borrados
  1. 53 48
      source/hdf5.js
  2. 1 1
      source/hickle.js
  3. 1 1
      source/keras.js
  4. 13 2
      source/view.js
  5. 7 0
      test/models.json

+ 53 - 48
source/hdf5.js

@@ -18,57 +18,62 @@ hdf5.File = class {
     }
 
     constructor(data) {
-        // https://support.hdfgroup.org/HDF5/doc/H5.format.html
-        const reader = data instanceof Uint8Array ?
-            new hdf5.BinaryReader(data) :
-            (data.length < 0x10000000 ? new hdf5.BinaryReader(data.peek()) : new hdf5.StreamReader(data));
-        reader.skip(8);
-        this._globalHeap = new hdf5.GlobalHeap(reader);
-        const version = reader.byte();
-        switch (version) {
-            case 0:
-            case 1: {
-                this._freeSpaceStorageVersion = reader.byte();
-                this._rootGroupEntryVersion = reader.byte();
-                reader.skip(1);
-                this._sharedHeaderMessageVersionFormat = reader.byte();
-                reader.initialize();
-                reader.skip(1);
-                this._groupLeafNodeK = reader.uint16(); // 0x04?
-                this._groupInternalNodeK = reader.uint16(); // 0x10?
-                reader.skip(4);
-                if (version > 0) {
-                    this._indexedStorageInternalNodeK = reader.uint16();
-                    this.skip(2); // Reserved
+        this.data = data;
+    }
+
+    read() {
+        if (this.data) {
+            // https://support.hdfgroup.org/HDF5/doc/H5.format.html
+            const data = this.data;
+            delete this.data;
+            const reader = data instanceof Uint8Array ? new hdf5.BinaryReader(data) : (data.length < 0x10000000 ? new hdf5.BinaryReader(data.peek()) : new hdf5.StreamReader(data));
+            reader.skip(8);
+            this._globalHeap = new hdf5.GlobalHeap(reader);
+            const version = reader.byte();
+            switch (version) {
+                case 0:
+                case 1: {
+                    this._freeSpaceStorageVersion = reader.byte();
+                    this._rootGroupEntryVersion = reader.byte();
+                    reader.skip(1);
+                    this._sharedHeaderMessageVersionFormat = reader.byte();
+                    reader.initialize();
+                    reader.skip(1);
+                    this._groupLeafNodeK = reader.uint16(); // 0x04?
+                    this._groupInternalNodeK = reader.uint16(); // 0x10?
+                    reader.skip(4);
+                    if (version > 0) {
+                        this._indexedStorageInternalNodeK = reader.uint16();
+                        this.skip(2); // Reserved
+                    }
+                    this._baseAddress = reader.offset();
+                    reader.offset(); // Address of File Free space Info
+                    this._endOfFileAddress = reader.offset();
+                    reader.offset(); // Driver Information Block Address
+                    if (this._baseAddress != 0) {
+                        throw new hdf5.Error('Base address is not zero.');
+                    }
+                    const rootGroupEntry = new hdf5.SymbolTableEntry(reader);
+                    this._rootGroup = new hdf5.Group(reader, rootGroupEntry, null, this._globalHeap, '', '');
+                    break;
                 }
-                this._baseAddress = reader.offset();
-                reader.offset(); // Address of File Free space Info
-                this._endOfFileAddress = reader.offset();
-                reader.offset(); // Driver Information Block Address
-                if (this._baseAddress != 0) {
-                    throw new hdf5.Error('Base address is not zero.');
+                case 2:
+                case 3: {
+                    reader.initialize();
+                    reader.byte();
+                    this._baseAddress = reader.offset();
+                    this._superBlockExtensionAddress = reader.offset();
+                    this._endOfFileAddress = reader.offset();
+                    const rootGroupObjectHeader = new hdf5.DataObjectHeader(reader.at(reader.offset()));
+                    this._rootGroup = new hdf5.Group(reader, null, rootGroupObjectHeader, this._globalHeap, '', '');
+                    break;
                 }
-                const rootGroupEntry = new hdf5.SymbolTableEntry(reader);
-                this._rootGroup = new hdf5.Group(reader, rootGroupEntry, null, this._globalHeap, '', '');
-                break;
+                default:
+                    throw new hdf5.Error('Unsupported Superblock version ' + version + '.');
             }
-            case 2:
-            case 3: {
-                reader.initialize();
-                reader.byte();
-                this._baseAddress = reader.offset();
-                this._superBlockExtensionAddress = reader.offset();
-                this._endOfFileAddress = reader.offset();
-                const rootGroupObjectHeader = new hdf5.DataObjectHeader(reader.at(reader.offset()));
-                this._rootGroup = new hdf5.Group(reader, null, rootGroupObjectHeader, this._globalHeap, '', '');
-                break;
-            }
-            default:
-                throw new hdf5.Error('Unsupported Superblock version ' + version + '.');
+            delete this.data;
+            this._rootGroup.attributes;
         }
-    }
-
-    get rootGroup() {
         return this._rootGroup;
     }
 };
@@ -471,7 +476,7 @@ hdf5.BinaryReader = class extends hdf5.Reader {
     skip(offset) {
         this._position += offset;
         if (this._offset + this._position > this._buffer.length) {
-            throw new hdf5.Error('Expected ' + (this._offset + this._position - this._buffer.length) + ' more bytes. The file might be corrupted. Unexpected end of file.');
+            throw new hdf5.Error('Unexpected end of file. Expected ' + (this._offset + this._position - this._buffer.length) + ' more bytes. The file might be corrupted.');
         }
     }
 

+ 1 - 1
source/hickle.js

@@ -5,7 +5,7 @@ hickle.ModelFactory = class {
 
     match(context) {
         const group = context.open('hdf5');
-        if (group && group.attributes.get('CLASS') === 'hickle') {
+        if (group && group.attributes && group.attributes.get('CLASS') === 'hickle') {
             return group;
         }
         return null;

+ 1 - 1
source/keras.js

@@ -8,7 +8,7 @@ keras.ModelFactory = class {
 
     match(context) {
         const group = context.open('hdf5');
-        if (group && group.attributes.get('CLASS') !== 'hickle') {
+        if (group && group.attributes && group.attributes.get('CLASS') !== 'hickle') {
             return 'keras.h5';
         }
         const json = context.open('json');

+ 13 - 2
source/view.js

@@ -4892,8 +4892,12 @@ view.ModelContext = class {
                         }
                         case 'hdf5': {
                             const file = hdf5.File.open(stream);
-                            if (file && file.rootGroup && file.rootGroup.attributes) {
-                                this._content.set(type, file.rootGroup);
+                            if (file) {
+                                try {
+                                    this._content.set(type, file.read());
+                                } catch (error) {
+                                    this._content.set(type, error);
+                                }
                             }
                             break;
                         }
@@ -5328,6 +5332,12 @@ view.ModelFactoryService = class {
                 throw new view.Error("Unsupported XML content '" + tags.keys().next().value + "'.");
             }
         };
+        const hdf5 = () => {
+            const obj = context.open('hdf5');
+            if (obj instanceof Error) {
+                throw obj;
+            }
+        };
         const unknown = () => {
             if (stream) {
                 stream.seek(0);
@@ -5343,6 +5353,7 @@ view.ModelFactoryService = class {
         pb();
         flatbuffers();
         xml();
+        hdf5();
         unknown();
     }
 

+ 7 - 0
test/models.json

@@ -6,6 +6,13 @@
     "error":    "Unsupported Pickle content.",
     "link":     "https://github.com/lutzroeder/netron/issues/458"
   },
+  {
+    "type":     "_",
+    "target":   "cnn_classifier.h5",
+    "source":   "https://github.com/lutzroeder/netron/files/12706986/cnn_classifier.h5.zip[cnn_classifier.h5]",
+    "error":    "Unexpected end of file. Expected 441 more bytes. The file might be corrupted.",
+    "link":     "https://github.com/lutzroeder/netron/issues/458"
+  },
   {
     "type":     "_",
     "target":   "config.json",