From a2026b1fa5ac3e730cf31483cdac1b008fc00cf9 Mon Sep 17 00:00:00 2001 From: Peter Dell Date: Sun, 26 Feb 2023 16:17:59 +0100 Subject: [PATCH] Improve IFF file detection and parsing --- .../ide/hex/HexEditorParserComponent.java | 17 +++++++--- .../com/wudsn/ide/hex/parser/IFFParser.java | 32 +++++++++++++++---- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParserComponent.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParserComponent.java index 75d5ff3b..f3840ff7 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParserComponent.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParserComponent.java @@ -41,6 +41,7 @@ import com.wudsn.ide.hex.parser.AtariDiskImageKFileParser; import com.wudsn.ide.hex.parser.AtariMADSParser; import com.wudsn.ide.hex.parser.AtariParser; import com.wudsn.ide.hex.parser.AtariSDXParser; +import com.wudsn.ide.hex.parser.IFFParser; final class HexEditorParserComponent { @@ -256,16 +257,22 @@ final class HexEditorParserComponent { // IFF files always have an even number of bytes if (fileContent.getLength() > 8 && (fileContent.getLength() & 0x1) == 0) { - possibleFileContentModes.add(HexEditorFileContentMode.IFF_FILE); char[] id = new char[4]; + int offset = 0; id[0] = (char) fileContent.getByte(0); id[1] = (char) fileContent.getByte(1); id[2] = (char) fileContent.getByte(2); id[3] = (char) fileContent.getByte(3); - String chunk = String.copyValueOf(id); - boolean iff = chunk.equals("FORM") || chunk.equals("LIST") || chunk.equals("CAT "); - if (result.equals(HexEditorFileContentMode.BINARY) && iff) { - result = HexEditorFileContentMode.IFF_FILE; + String chunkName = String.copyValueOf(id); + offset += 4; + var chunkLength = fileContent.getDoubleWordBigEndian(4); + offset += 4; + if (IFFParser.isValidChunkName(chunkName) && offset + chunkLength <= fileContent.getLength()) { + possibleFileContentModes.add(HexEditorFileContentMode.IFF_FILE); + boolean iff = chunkName.equals("FORM") || chunkName.equals("LIST") || chunkName.equals("CAT "); + if (result.equals(HexEditorFileContentMode.BINARY) && iff) { + result = HexEditorFileContentMode.IFF_FILE; + } } } return result; diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/IFFParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/IFFParser.java index ce4d1b8e..adf371a1 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/IFFParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/IFFParser.java @@ -30,6 +30,22 @@ import com.wudsn.ide.hex.Texts; public final class IFFParser extends HexEditorParser { + public static boolean isValidChunkName(String chunkName) { + if (chunkName == null) { + throw new IllegalArgumentException("Parameter 'chunkName' must not be null."); + } + if (chunkName.length() != 4) { + return false; + } + for (int i = 0; i < chunkName.length(); i++) { + char c = chunkName.charAt(i); + if (c < 'A' || c > 'Z') { + return false; + } + } + return true; + } + @Override public final boolean parse(StyledString contentBuilder) { if (contentBuilder == null) { @@ -45,19 +61,23 @@ public final class IFFParser extends HexEditorParser { private boolean parse(StyledString contentBuilder, long offset, long fileContentLength, HexEditorContentOutlineTreeObject treeObject) { boolean error; - + String chunkName = null; error = (fileContentLength - offset) < 8; if (!error) { while ((fileContentLength - offset) >= 8 && !error) { long headerLength = 8; - String chunkName = getChunkName(offset); - long chunkLength = fileContent.getDoubleWordBigEndian(offset + 4); + chunkName = getChunkName(offset); + if (!isValidChunkName(chunkName)) { + error = true; // Non ASCII chunk name + break; + } + var chunkLength = fileContent.getDoubleWordBigEndian(offset + 4); String headerText; String formTypeName = ""; boolean hasInnerChunks = false; if (chunkName.equals("FORM")) { if (chunkLength >= 4) { - formTypeName = getChunkName(offset + 8); + formTypeName = getChunkName(offset); headerText = TextUtility.format(Texts.HEX_EDITOR_IFF_FORM_CHUNK, chunkName, formTypeName, HexUtility.getLongValueHexString(chunkLength), NumberUtility.getLongValueDecimalString(chunkLength)); @@ -75,6 +95,7 @@ public final class IFFParser extends HexEditorParser { headerText = TextUtility.format(Texts.HEX_EDITOR_IFF_CHUNK, chunkName, HexUtility.getLongValueHexString(chunkLength), NumberUtility.getLongValueDecimalString(chunkLength)); + } if (!error) { @@ -98,11 +119,10 @@ public final class IFFParser extends HexEditorParser { if ((offset & 0x1) == 1) { offset++; } - } } - } + if (error) { printBlockWithError(contentBuilder, Texts.HEX_EDITOR_IFF_FILE_ERROR, fileContentLength, offset); }