Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz
2026-08-06 11:31:16 -04:00
4 changed files with 86 additions and 38 deletions

View File

@@ -0,0 +1,42 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.som;
/**
* An exception class to handle encountering invalid SOM headers
*/
public class SomException extends Exception {
/**
* Constructs a new exception with the specified detail message
*
* @param message the detail message
*/
public SomException(String message) {
super(message);
}
/**
* Constructs a new exception with the specified cause and a detail message
*
* @param cause the cause (which is saved for later retrieval by the {@link #getCause()}
* method (a {@code null} value is permitted, and indicates that the cause is nonexistent
* or unknown).
*/
public SomException(Exception cause) {
super(cause);
}
}

View File

@@ -84,12 +84,18 @@ public class SomHeader implements StructConverter {
* Creates a new {@link SomHeader} * Creates a new {@link SomHeader}
* *
* @param reader A {@link BinaryReader} positioned at the start of the header * @param reader A {@link BinaryReader} positioned at the start of the header
* @throws SomException if the header is invalid
* @throws IOException if there was an IO-related error * @throws IOException if there was an IO-related error
*/ */
public SomHeader(BinaryReader reader) throws IOException { public SomHeader(BinaryReader reader) throws SomException, IOException {
systemId = reader.readNextUnsignedShort(); systemId = reader.readNextUnsignedShort();
magic = reader.readNextUnsignedShort(); magic = reader.readNextUnsignedShort();
versionId = reader.readNextUnsignedInt(); versionId = reader.readNextUnsignedInt();
if (!hasValidMagic() || !hasValidVersionId()) {
throw new SomException("Invalid SOM header");
}
fileTime = new SomSysClock(reader); fileTime = new SomSysClock(reader);
entrySpace = reader.readNextUnsignedInt(); entrySpace = reader.readNextUnsignedInt();
entrySubspace = reader.readNextUnsignedInt(); entrySubspace = reader.readNextUnsignedInt();
@@ -173,25 +179,6 @@ public class SomHeader implements StructConverter {
return magic; return magic;
} }
/**
* {@return true if this {@link SomHeader} has a valid magic number; otherwise false}
*/
public boolean hasValidMagic() {
return switch (magic) {
case MAGIC_LIBRARY:
case MAGIC_RELOCATABLE:
case MAGIC_NON_SHAREABLE_EXE:
case MAGIC_SHAREABLE_EXE:
case MAGIC_SHARABLE_DEMAND_LOADABLE_EXE:
case MAGIC_DYNAMIC_LOAD_LIBRARY:
case MAGIC_SHARED_LIBRARY:
case MAGIC_RELOCATABLE_LIBRARY:
yield true;
default:
yield false;
};
}
/** /**
* {@return the version ID} * {@return the version ID}
*/ */
@@ -199,13 +186,6 @@ public class SomHeader implements StructConverter {
return versionId; return versionId;
} }
/**
* {@return true if this {@link SomHeader} has a valid version ID; otherwise false}
*/
public boolean hasValidVersionId() {
return versionId == 85082112 || versionId == 87102412;
}
/** /**
* {@return the file time} * {@return the file time}
*/ */
@@ -558,6 +538,32 @@ public class SomHeader implements StructConverter {
} }
} }
/**
* {@return true if this {@link SomHeader} has a valid magic number; otherwise false}
*/
private boolean hasValidMagic() {
return switch (magic) {
case MAGIC_LIBRARY:
case MAGIC_RELOCATABLE:
case MAGIC_NON_SHAREABLE_EXE:
case MAGIC_SHAREABLE_EXE:
case MAGIC_SHARABLE_DEMAND_LOADABLE_EXE:
case MAGIC_DYNAMIC_LOAD_LIBRARY:
case MAGIC_SHARED_LIBRARY:
case MAGIC_RELOCATABLE_LIBRARY:
yield true;
default:
yield false;
};
}
/**
* {@return true if this {@link SomHeader} has a valid version ID; otherwise false}
*/
private boolean hasValidVersionId() {
return versionId == 85082112 || versionId == 87102412;
}
@Override @Override
public DataType toDataType() throws DuplicateNameException, IOException { public DataType toDataType() throws DuplicateNameException, IOException {
StructureDataType struct = new StructureDataType("header", SIZE); StructureDataType struct = new StructureDataType("header", SIZE);

View File

@@ -77,10 +77,12 @@ public class MotorolaHexLoader extends AbstractProgramLoader {
} }
static boolean isPossibleHexFile(ByteProvider provider) { static boolean isPossibleHexFile(ByteProvider provider) {
final int MAX_BLANK_LINES = 100;
try (BoundedBufferedReader reader = try (BoundedBufferedReader reader =
new BoundedBufferedReader(new InputStreamReader(provider.getInputStream(0)))) { new BoundedBufferedReader(new InputStreamReader(provider.getInputStream(0)))) {
int i = 0;
String line = reader.readLine(); String line = reader.readLine();
while (line.matches("^\\s*$")) { while (i++ < MAX_BLANK_LINES && line.isBlank()) {
line = reader.readLine(); line = reader.readLine();
} }
return line.matches("^[S:][0-9a-fA-F]+$"); return line.matches("^[S:][0-9a-fA-F]+$");

View File

@@ -50,18 +50,16 @@ public class SomLoader extends AbstractProgramWrapperLoader {
try { try {
SomHeader header = new SomHeader(new BinaryReader(provider, false)); SomHeader header = new SomHeader(new BinaryReader(provider, false));
if (header.hasValidMagic() && header.hasValidVersionId()) { List<QueryResult> results = QueryOpinionService.query(getName(),
List<QueryResult> results = QueryOpinionService.query(getName(), Integer.toString(header.getSystemId()), null);
Integer.toString(header.getSystemId()), null); for (QueryResult result : results) {
for (QueryResult result : results) { loadSpecs.add(new LoadSpec(this, 0, result));
loadSpecs.add(new LoadSpec(this, 0, result)); }
} if (loadSpecs.isEmpty()) {
if (loadSpecs.isEmpty()) { loadSpecs.add(new LoadSpec(this, 0, true));
loadSpecs.add(new LoadSpec(this, 0, true));
}
} }
} }
catch (IOException e) { catch (SomException | IOException e) {
// that's ok, not a System Object Model // that's ok, not a System Object Model
} }
return loadSpecs; return loadSpecs;