From 79cad1342dbc9fa557ceadf6bfeea64cfe111de2 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 18 Jan 2022 13:20:21 +0900 Subject: [PATCH 1/5] =?UTF-8?q?glb=20=E3=81=AE=20parse=20=E3=82=92?= =?UTF-8?q?=E5=8E=B3=E6=A0=BC=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UniGLTF/Tests/UniGLTF/GlbParserTests.cs | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs index 3acbc4a65..02de02b20 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs @@ -1,4 +1,6 @@ using System; +using System.IO; +using System.Linq; using NUnit.Framework; namespace UniGLTF @@ -37,5 +39,40 @@ namespace UniGLTF // NOTE: 大文字小文字が違うだけの名前は、同一としてみなされ、Suffix が付く。 Assert.AreEqual("foobar__UNIGLTF__DUPLICATED__2", parsed.GLTF.textures[1].name); } + + /// + /// ヘッダが正しいが、後ろが切れている場合に throw する + /// + [Test] + public void GlbLengthTest() + { + var env = System.Environment.GetEnvironmentVariable("GLTF_SAMPLE_MODELS"); + if (string.IsNullOrEmpty(env)) + { + return; + } + var root = new DirectoryInfo($"{env}/2.0"); + if (!root.Exists) + { + return; + } + + var path = Path.Combine(root.ToString(), "DamagedHelmet\\glTF-Binary\\DamagedHelmet.glb"); + Assert.True(File.Exists(path)); + + var bytes = File.ReadAllBytes(path); + var data = new GlbBinaryParser(bytes, Path.GetFileNameWithoutExtension(path)).Parse(); + + // 2個目のチャンクを削る + var mod = bytes.Take(12 + 8 + data.Chunks[0].Bytes.Count).ToArray(); + // 再パース + + Assert.Throws(() => + { + var data2 = new GlbBinaryParser(mod, Path.GetFileNameWithoutExtension(path)).Parse(); + }); + + var a = 0; + } } -} \ No newline at end of file +} From 217cc552eb543643e804e8c7a86b81aeff4653e1 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 18 Jan 2022 13:52:57 +0900 Subject: [PATCH 2/5] =?UTF-8?q?glb=20parser=20=E3=81=8C=20glb=20header=20?= =?UTF-8?q?=E3=81=AE=20length=20=E3=82=92=E3=83=81=E3=82=A7=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=81=97=E6=97=A9=E6=9C=9F=E3=81=AB=20throw=20?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs | 18 ++++++++++++------ Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs | 8 +++----- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs index d6415a0de..a0d489672 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs @@ -48,27 +48,33 @@ namespace UniGLTF public static List ParseGlbChunks(Byte[] bytes) { - if (bytes.Length == 0) + // + // glb header(12byte) + // + if (bytes.Length < 12) { - throw new Exception("empty bytes"); + throw new FormatException("not glb header"); } int pos = 0; if (Encoding.ASCII.GetString(bytes, 0, 4) != GLB_MAGIC) { - throw new Exception("invalid magic"); + throw new FormatException("invalid magic"); } pos += 4; var version = BitConverter.ToUInt32(bytes, pos); if (version != GLB_VERSION) { - Debug.LogWarningFormat("unknown version: {0}", version); - return null; + throw new FormatException($"unknown version: {version}"); } pos += 4; - //var totalLength = BitConverter.ToUInt32(bytes, pos); + var totalLength = BitConverter.ToUInt32(bytes, pos); + if (bytes.Length < totalLength) + { + throw new System.IO.EndOfStreamException($"Not enough size: {bytes.Length} < {totalLength}"); + } pos += 4; var chunks = new List(); diff --git a/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs index 02de02b20..ae99dba8c 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs @@ -63,16 +63,14 @@ namespace UniGLTF var bytes = File.ReadAllBytes(path); var data = new GlbBinaryParser(bytes, Path.GetFileNameWithoutExtension(path)).Parse(); - // 2個目のチャンクを削る + // glb header + 1st chunk only var mod = bytes.Take(12 + 8 + data.Chunks[0].Bytes.Count).ToArray(); - // 再パース - Assert.Throws(() => + Assert.Throws(() => { + // 再パース var data2 = new GlbBinaryParser(mod, Path.GetFileNameWithoutExtension(path)).Parse(); }); - - var a = 0; } } } From c372032e27e3dcb36c08e9ecde3b5bd2a1142b49 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 18 Jan 2022 14:12:55 +0900 Subject: [PATCH 3/5] =?UTF-8?q?test=20=E3=81=A7=E6=96=B0=E3=81=97=E3=81=84?= =?UTF-8?q?=20parser=20=E3=82=92=E4=BD=BF=E3=81=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/VRM10/Tests/MigrationTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Assets/VRM10/Tests/MigrationTests.cs b/Assets/VRM10/Tests/MigrationTests.cs index 21ea537c2..d1c8f7763 100644 --- a/Assets/VRM10/Tests/MigrationTests.cs +++ b/Assets/VRM10/Tests/MigrationTests.cs @@ -22,8 +22,8 @@ namespace UniVRM10 static JsonNode GetVRM0(byte[] bytes) { - var glb = UniGLTF.Glb.Parse(bytes); - var json = glb.Json.Bytes.ParseAsJson(); + var glb = new GlbBinaryParser(bytes, "vrm0").Parse(); + var json = glb.Json.ParseAsJson(); return json["extensions"]["VRM"]; } @@ -50,8 +50,8 @@ namespace UniVRM10 var vrm0Json = GetVRM0(vrm0Bytes); var vrm1 = MigrationVrm.Migrate(vrm0Bytes); - var glb = UniGLTF.Glb.Parse(vrm1); - var json = glb.Json.Bytes.ParseAsJson(); + var glb = new GlbBinaryParser(vrm1, "vrm1").Parse(); + var json = glb.Json.ParseAsJson(); var gltf = UniGLTF.GltfDeserializer.Deserialize(json); MigrationVrm.Check(vrm0Json, GetExtension(gltf.extensions, UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.ExtensionNameUtf8, From 94f5354f4eb7f4e47f3f8c82db412d2ff8bd347c Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 18 Jan 2022 14:14:36 +0900 Subject: [PATCH 4/5] =?UTF-8?q?glb=20=E3=81=AE=E3=83=91=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E3=81=AF=E3=80=81GlbLowLevelParser=20=E3=81=AB=E8=B2=AC?= =?UTF-8?q?=E5=8B=99=E3=81=8C=E7=A7=BB=E5=8B=95=E3=81=97=E3=81=9F=E3=80=82?= =?UTF-8?q?=E5=8F=A4=E3=81=84=E6=96=B9=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/Format/glbTypes.cs | 94 ------------------- 1 file changed, 94 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/Format/glbTypes.cs b/Assets/UniGLTF/Runtime/UniGLTF/Format/glbTypes.cs index 59c352a4c..9628e9344 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/Format/glbTypes.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/Format/glbTypes.cs @@ -24,30 +24,6 @@ namespace UniGLTF s.Write(GLB_VERSION, 0, GLB_VERSION.Length); } - public static int TryParse(ArraySegment bytes, out int pos, out Exception message) - { - pos = 0; - - if (!bytes.Slice(0, 4).SequenceEqual(GLB_MAGIC)) - { - message = new FormatException("invalid magic"); - return 0; - } - pos += 4; - - if (!bytes.Slice(pos, 4).SequenceEqual(GLB_VERSION)) - { - message = new FormatException("invalid magic"); - return 0; - } - pos += 4; - - var totalLength = BitConverter.ToInt32(bytes.Array, bytes.Offset + pos); - pos += 4; - - message = null; - return totalLength; - } } public struct GlbChunk @@ -219,75 +195,5 @@ namespace UniGLTF throw new FormatException("unknown chunk type: " + src); } } - - public static Glb Parse(Byte[] bytes) - { - return Parse(new ArraySegment(bytes)); - } - - public static Glb Parse(ArraySegment bytes) - { - if (TryParse(bytes, out Glb glb, out Exception ex)) - { - return glb; - } - else - { - throw ex; - } - } - - public static bool TryParse(Byte[] bytes, out Glb glb, out Exception ex) - { - return TryParse(new ArraySegment(bytes), out glb, out ex); - } - - public static bool TryParse(ArraySegment bytes, out Glb glb, out Exception ex) - { - glb = default(Glb); - if (bytes.Count == 0) - { - ex = new Exception("empty bytes"); - return false; - } - - var length = GlbHeader.TryParse(bytes, out int pos, out ex); - if (length == 0) - { - return false; - } - bytes = bytes.Slice(0, length); - - try - { - var chunks = new List(); - while (pos < bytes.Count) - { - var chunkDataSize = BitConverter.ToInt32(bytes.Array, bytes.Offset + pos); - pos += 4; - - //var type = (GlbChunkType)BitConverter.ToUInt32(bytes, pos); - var chunkTypeBytes = bytes.Slice(pos, 4).Where(x => x != 0).ToArray(); - var chunkTypeStr = Encoding.ASCII.GetString(chunkTypeBytes); - pos += 4; - - chunks.Add(new GlbChunk - { - ChunkTypeString = chunkTypeStr, - Bytes = bytes.Slice(pos, chunkDataSize) - }); - - pos += chunkDataSize; - } - - glb = new Glb(chunks[0], chunks[1]); - return true; - } - catch (Exception _ex) - { - ex = _ex; - return false; - } - } } } From 0d0da0bcad9611f92e856a26dd2b47bef7c59234 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 18 Jan 2022 20:26:36 +0900 Subject: [PATCH 5/5] =?UTF-8?q?GlbParseException=20=E3=82=92=E4=BD=9C?= =?UTF-8?q?=E3=82=8A=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs | 11 +++++------ Assets/UniGLTF/Runtime/UniGLTF/UniGLTFException.cs | 8 ++++++++ Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs index a0d489672..ac3eabf2d 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/glbImporter.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using UnityEngine; namespace UniGLTF @@ -14,7 +13,7 @@ namespace UniGLTF public static GlbChunkType ToChunkType(this string src) { - switch(src) + switch (src) { case "BIN": return GlbChunkType.BIN; @@ -53,27 +52,27 @@ namespace UniGLTF // if (bytes.Length < 12) { - throw new FormatException("not glb header"); + throw new GlbParseException("glb header not found"); } int pos = 0; if (Encoding.ASCII.GetString(bytes, 0, 4) != GLB_MAGIC) { - throw new FormatException("invalid magic"); + throw new GlbParseException("invalid magic"); } pos += 4; var version = BitConverter.ToUInt32(bytes, pos); if (version != GLB_VERSION) { - throw new FormatException($"unknown version: {version}"); + throw new GlbParseException($"unknown version: {version}"); } pos += 4; var totalLength = BitConverter.ToUInt32(bytes, pos); if (bytes.Length < totalLength) { - throw new System.IO.EndOfStreamException($"Not enough size: {bytes.Length} < {totalLength}"); + throw new GlbParseException($"not enough size: {bytes.Length} < {totalLength}"); } pos += 4; diff --git a/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFException.cs b/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFException.cs index fde2faaf8..8522e2201 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFException.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/UniGLTFException.cs @@ -14,4 +14,12 @@ namespace UniGLTF public UniGLTFNotSupportedException(string fmt, params object[] args) : this(string.Format(fmt, args)) { } public UniGLTFNotSupportedException(string msg) : base(msg) { } } + + /// + /// Exception in parse the glb header + /// + public class GlbParseException : UniGLTFException + { + public GlbParseException(string msg) : base(msg) { } + } } diff --git a/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs index ae99dba8c..9c36ec786 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/GlbParserTests.cs @@ -66,7 +66,7 @@ namespace UniGLTF // glb header + 1st chunk only var mod = bytes.Take(12 + 8 + data.Chunks[0].Bytes.Count).ToArray(); - Assert.Throws(() => + Assert.Throws(() => { // 再パース var data2 = new GlbBinaryParser(mod, Path.GetFileNameWithoutExtension(path)).Parse();