From cf1739b4b5dab9ca44573b2722c9eb018cb9a09c Mon Sep 17 00:00:00 2001
From: emteere <47253321+emteere@users.noreply.github.com>
Date: Fri, 18 Sep 2020 17:03:45 -0400
Subject: [PATCH] GP-182 Fixing unknown resource blowup
---
.../app/util/bin/format/ne/Resource.java | 39 ++--
.../app/util/bin/format/ne/ResourceType.java | 201 ++++++++++--------
.../ghidra/app/util/opinion/NeLoader.java | 7 +-
3 files changed, 140 insertions(+), 107 deletions(-)
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Resource.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Resource.java
index 2dc2eb5c24..91eda63926 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Resource.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/Resource.java
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
- * REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +15,11 @@
*/
package ghidra.app.util.bin.format.ne;
-import ghidra.app.util.bin.format.*;
-import ghidra.util.Conv;
-
import java.io.IOException;
+import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
+import ghidra.util.Conv;
+
/**
* An implementation of the new-executable TNAMEINFO structure.
*
@@ -61,6 +60,7 @@ public class Resource {
public short getFileOffset() {
return fileOffset;
}
+
/**
* Returns the file length of this resource.
* @return the file length of this resource
@@ -68,6 +68,7 @@ public class Resource {
public short getFileLength() {
return fileLength;
}
+
/**
* Returns the flag word of this resource.
* @return the flag word of this resource
@@ -75,6 +76,7 @@ public class Resource {
public short getFlagword() {
return flagword;
}
+
/**
* Returns the resource ID of this resource.
* @return the resource ID of this resource
@@ -82,6 +84,7 @@ public class Resource {
public short getResourceID() {
return resourceID;
}
+
/**
* Returns the handle of this resource.
* @return the handle of this resource
@@ -89,6 +92,7 @@ public class Resource {
public short getHandle() {
return handle;
}
+
/**
* Returns the usage of this resource.
* @return the usage of this resource
@@ -96,6 +100,7 @@ public class Resource {
public short getUsage() {
return usage;
}
+
/**
* Returns true if this resource is moveable.
* @return true if this resource is moveable
@@ -103,6 +108,7 @@ public class Resource {
public boolean isMoveable() {
return (flagword & FLAG_MOVEABLE) != 0;
}
+
/**
* Returns true if this resource is pure.
* @return true if this resource is pure
@@ -110,13 +116,15 @@ public class Resource {
public boolean isPure() {
return (flagword & FLAG_PURE) != 0;
}
+
/**
* Returns true if this resource is preloaded.
* @return true if this resource is preloaded
- */
+ */
public boolean isPreload() {
return (flagword & FLAG_PRELOAD) != 0;
}
+
/**
* Returns the shifted file offset of this resource.
* this.getFileOffset() << ResourceTable.getAlignmentShiftCount()
@@ -127,6 +135,7 @@ public class Resource {
int offset_int = Conv.shortToInt(fileOffset);
return offset_int << shift_int;
}
+
/**
* Returns the shifted file length of this resource.
* this.getFileLength() << ResourceTable.getAlignmentShiftCount()
@@ -137,20 +146,20 @@ public class Resource {
int length_int = Conv.shortToInt(fileLength);
return length_int << shift_int;
}
+
/**
* Returns the actual bytes for this resource.
* @return the actual bytes for this resource
*/
public byte[] getBytes() throws IOException {
- return reader.readByteArray(
- getFileOffsetShifted(),
- getFileLengthShifted());
+ return reader.readByteArray(getFileOffsetShifted(), getFileLengthShifted());
}
+
/**
* @see java.lang.Object#toString()
*/
@Override
- public String toString() {
+ public String toString() {
//if MSB is set, then resourceID is a unique id of this resource...
if ((resourceID & 0x8000) != 0) {
return "" + (resourceID & 0x7fff);
@@ -159,12 +168,14 @@ public class Resource {
//index to a resource name relative to the
//beginning of the resource table...
ResourceName[] names = rt.getResourceNames();
- for (int i = 0; i < names.length; ++i) {
- if (resourceID == names[i].getIndex() - rt.getIndex()) {
- return names[i].getName();
+ for (ResourceName name : names) {
+ if (resourceID == name.getIndex() - rt.getIndex()) {
+ return name.getName();
}
}
- throw new RuntimeException(
- "NE - Resource - unknown id - " + Conv.toHexString(resourceID));
+ if (resourceID >= 0 && resourceID < names.length) {
+ return names[resourceID].getName();
+ }
+ return ("NE - Resource - unknown id - " + Conv.toHexString(resourceID));
}
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/ResourceType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/ResourceType.java
index 6d426f6955..e73ef7fcb2 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/ResourceType.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/ne/ResourceType.java
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
- * REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,12 +15,12 @@
*/
package ghidra.app.util.bin.format.ne;
-import ghidra.app.util.bin.format.*;
-import ghidra.util.Conv;
-
import java.io.IOException;
import java.util.ArrayList;
+import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader;
+import ghidra.util.Conv;
+
/**
* An implementation of the TTYPEINFO structure.
*
@@ -30,123 +29,143 @@ import java.util.ArrayList;
public class ResourceType {
//0x00 is not defined...?
/**Constant indicating cursor resource type.*/
- public final static short RT_CURSOR = 0x01;
+ public final static short RT_CURSOR = 0x01;
/**Constant indicating bitmap resource type.*/
- public final static short RT_BITMAP = 0x02;
+ public final static short RT_BITMAP = 0x02;
/**Constant indicating icon resource type.*/
- public final static short RT_ICON = 0x03;
+ public final static short RT_ICON = 0x03;
/**Constant indicating menu resource type.*/
- public final static short RT_MENU = 0x04;
+ public final static short RT_MENU = 0x04;
/**Constant indicating dialog resource type.*/
- public final static short RT_DIALOG = 0x05;
+ public final static short RT_DIALOG = 0x05;
/**Constant indicating string resource type.*/
- public final static short RT_STRING = 0x06;
+ public final static short RT_STRING = 0x06;
/**Constant indicating font directory resource type.*/
- public final static short RT_FONTDIR = 0x07;
+ public final static short RT_FONTDIR = 0x07;
/**Constant indicating font resource type.*/
- public final static short RT_FONT = 0x08;
+ public final static short RT_FONT = 0x08;
/**Constant indicating an accelerator resource type.*/
- public final static short RT_ACCELERATOR = 0x09;
+ public final static short RT_ACCELERATOR = 0x09;
/**Constant indicating RC data resource type.*/
- public final static short RT_RCDATA = 0x0a;
+ public final static short RT_RCDATA = 0x0a;
/**Constant indicating message table resource type.*/
- public final static short RT_MESSAGETABLE = 0x0b;
+ public final static short RT_MESSAGETABLE = 0x0b;
/**Constant indicating cursor group resource type.*/
- public final static short RT_GROUP_CURSOR = 0x0c;
- //0x0d is not defined...?
+ public final static short RT_GROUP_CURSOR = 0x0c;
+ //0x0d is not defined...?
/**Constant indicating icon group resource type.*/
- public final static short RT_GROUP_ICON = 0x0e;
- //0x0f is not defined...?
+ public final static short RT_GROUP_ICON = 0x0e;
+ //0x0f is not defined...?
/**Constant indicating version resource type.*/
- public final static byte RT_VERSION = 0x10;
+ public final static byte RT_VERSION = 0x10;
- private short typeID; //if >= 0x8000, then
- private short count; //number of resources of this type
- private int reserved; //reserved...for what?
- private Resource [] resources;
+ private short typeID; //if >= 0x8000, then
+ private short count; //number of resources of this type
+ private int reserved; //reserved...for what?
+ private Resource[] resources;
/**
* Constructs a new resource type.
* @param reader the binary reader
* @param rt the resource table
*/
- ResourceType(FactoryBundledWithBinaryReader reader, ResourceTable rt) throws IOException {
- typeID = reader.readNextShort();
- if (typeID == 0) return; //not a valid resource type...
+ ResourceType(FactoryBundledWithBinaryReader reader, ResourceTable rt) throws IOException {
+ typeID = reader.readNextShort();
+ if (typeID == 0) {
+ return; //not a valid resource type...
+ }
- count = reader.readNextShort();
- reserved = reader.readNextInt();
+ count = reader.readNextShort();
+ reserved = reader.readNextInt();
- ArrayList list = new ArrayList();
+ ArrayList list = new ArrayList();
- int count_int = Conv.shortToInt(count);
- for (int i = 0 ; i < count_int ; ++i) {
- if ((short)(typeID&0x7fff) == RT_STRING) {
- list.add(new ResourceStringTable(reader, rt));
- }
- else {
- list.add(new Resource(reader, rt));
- }
- }
- resources = new Resource[list.size()];
- list.toArray(resources);
- }
+ int count_int = Conv.shortToInt(count);
+ for (int i = 0; i < count_int; ++i) {
+ if ((short) (typeID & 0x7fff) == RT_STRING) {
+ list.add(new ResourceStringTable(reader, rt));
+ }
+ else {
+ list.add(new Resource(reader, rt));
+ }
+ }
+ resources = new Resource[list.size()];
+ list.toArray(resources);
+ }
/**
* Returns the resource type ID.
* @return the resource type ID
*/
- public short getTypeID() {
- return typeID;
- }
- /**
- * Returns the number of resources of this type.
- * @return the number of resources of this type
- */
- public short getCount() {
- return count;
- }
- /**
- * Returns the reserved value (purpose is unknown).
- * @return the reserved value
- */
- public int getReserved() {
- return reserved;
- }
- /**
- * Returns the array of resources of this type.
- * @return the array of resources of this type
- */
- public Resource [] getResources() {
- return resources;
- }
+ public short getTypeID() {
+ return typeID;
+ }
+
+ /**
+ * Returns the number of resources of this type.
+ * @return the number of resources of this type
+ */
+ public short getCount() {
+ return count;
+ }
+
+ /**
+ * Returns the reserved value (purpose is unknown).
+ * @return the reserved value
+ */
+ public int getReserved() {
+ return reserved;
+ }
+
+ /**
+ * Returns the array of resources of this type.
+ * @return the array of resources of this type
+ */
+ public Resource[] getResources() {
+ return resources;
+ }
+
/**
* @see java.lang.Object#toString()
*/
- @Override
- public String toString() {
- if ((typeID & 0x8000) == 0) {
- throw new RuntimeException("NE - ResourceType - name lookup required - "+typeID);
- }
- int idx = typeID&0x7fff;
- switch (idx) {
- case RT_CURSOR: return "Cursor";
- case RT_BITMAP: return "Bitmap";
- case RT_ICON: return "Icon";
- case RT_MENU: return "Menu";
- case RT_DIALOG: return "Dialog Box";
- case RT_STRING: return "String Table";
- case RT_FONTDIR: return "Font Directory";
- case RT_FONT: return "Font";
- case RT_ACCELERATOR: return "Accelerator Table";
- case RT_RCDATA: return "Resource Data";
- case RT_MESSAGETABLE: return "Message Table";
- case RT_GROUP_CURSOR: return "Cursor Directory";
- case RT_GROUP_ICON: return "Icon Directory";
- case RT_VERSION: return "Version Information";
+ @Override
+ public String toString() {
+ if ((typeID & 0x8000) == 0) {
+ return "UnknownResourceType_" + typeID;
+ }
+ int idx = typeID & 0x7fff;
+ switch (idx) {
+ case RT_CURSOR:
+ return "Cursor";
+ case RT_BITMAP:
+ return "Bitmap";
+ case RT_ICON:
+ return "Icon";
+ case RT_MENU:
+ return "Menu";
+ case RT_DIALOG:
+ return "Dialog Box";
+ case RT_STRING:
+ return "String Table";
+ case RT_FONTDIR:
+ return "Font Directory";
+ case RT_FONT:
+ return "Font";
+ case RT_ACCELERATOR:
+ return "Accelerator Table";
+ case RT_RCDATA:
+ return "Resource Data";
+ case RT_MESSAGETABLE:
+ return "Message Table";
+ case RT_GROUP_CURSOR:
+ return "Cursor Directory";
+ case RT_GROUP_ICON:
+ return "Icon Directory";
+ case RT_VERSION:
+ return "Version Information";
- default:
- return "Unknown_"+idx;
- }
- }
+ default:
+ return "Unknown_" + idx;
+ }
+ }
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java
index cf81045b2d..db764ee0d9 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/NeLoader.java
@@ -362,7 +362,9 @@ public class NeLoader extends AbstractLibrarySupportLoader {
buf.append("Handle: " + Conv.toHexString(resource.getHandle()) + "\n");
buf.append("Usage: " + Conv.toHexString(resource.getUsage()) + "\n");
CodeUnit cu = listing.getCodeUnitAt(addr);
- cu.setComment(CodeUnit.PRE_COMMENT, buf.toString());
+ if (cu != null) {
+ cu.setComment(CodeUnit.PRE_COMMENT, buf.toString());
+ }
//if this resource is a string table,
//then go and create the strings...
@@ -435,7 +437,8 @@ public class NeLoader extends AbstractLibrarySupportLoader {
Function refFunction = null;
try {
ExternalLocation loc;
- loc = externalManager.addExtFunction(moduleName, callname, null, SourceType.IMPORTED);
+ loc = externalManager.addExtFunction(moduleName, callname, null,
+ SourceType.IMPORTED);
refFunction = loc.getFunction();
}
catch (DuplicateNameException e) {