Skip to content

Commit

Permalink
Handle malformed TOH/TOT resources more gracefully
Browse files Browse the repository at this point in the history
Fixes issues caused by 2767993 and d6c39dc.
  • Loading branch information
Argent77 committed Apr 6, 2024
1 parent d6c39dc commit 3f2507d
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 12 deletions.
24 changes: 18 additions & 6 deletions src/org/infinity/resource/sav/SavResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,15 @@ public void actionPerformed(ActionEvent event) {
} else if (buttonPanel.getControlByType(CTRL_DECOMPRESS) == event.getSource()) {
decompressData(true);
} else if (buttonPanel.getControlByType(CTRL_EDIT) == event.getSource()) {
ResourceEntry fileentry = entries.get(filelist.getSelectedIndex());
Resource res = ResourceFactory.getResource(fileentry);
new ViewFrame(panel.getTopLevelAncestor(), res);
try {
ResourceEntry fileentry = entries.get(filelist.getSelectedIndex());
Resource res = ResourceFactory.getResource(fileentry);
new ViewFrame(panel.getTopLevelAncestor(), res);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(panel.getTopLevelAncestor(), "Could not open selected resource.", "Error",
JOptionPane.ERROR_MESSAGE);
}
} else if (buttonPanel.getControlByType(ButtonPanel.Control.EXPORT_BUTTON) == event.getSource()) {
ResourceFactory.exportResource(entry, panel.getTopLevelAncestor());
} else if (buttonPanel.getControlByType(CTRL_DELETE) == event.getSource()) {
Expand Down Expand Up @@ -209,9 +215,15 @@ public JComponent makeViewer(ViewableContainer container) {
@Override
public void mouseClicked(MouseEvent event) {
if (event.getClickCount() == 2) {
ResourceEntry fileentry = entries.get(filelist.getSelectedIndex());
Resource res = ResourceFactory.getResource(fileentry);
new ViewFrame(panel.getTopLevelAncestor(), res);
try {
ResourceEntry fileentry = entries.get(filelist.getSelectedIndex());
Resource res = ResourceFactory.getResource(fileentry);
new ViewFrame(panel.getTopLevelAncestor(), res);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(panel.getTopLevelAncestor(), "Could not open selected resource.", "Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/org/infinity/resource/to/StringEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public int read(ByteBuffer buffer, int offset) throws Exception {
addField(new HexNumber(buffer, offset, 4, TOT_STRING_OFFSET_FREE_REGION));
addField(new HexNumber(buffer, offset + 4, 4, TOT_STRING_OFFSET_PREV_ENTRY));
addField(new TextEdit(buffer, offset + 8, 512, TOT_STRING_TEXT));
addField(new HexNumber(buffer, offset + 520, 4, TOT_STRING_OFFSET_NEXT_ENTRY)); // Note: offset value is relative to structure base offset
addField(new HexNumber(buffer, offset + 520, 4, TOT_STRING_OFFSET_NEXT_ENTRY));
return offset + 524;
}
}
3 changes: 0 additions & 3 deletions src/org/infinity/resource/to/TohResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,6 @@ public static String getOverrideString(TohResource toh, TotResource tot, int str
if (se != null) {
retVal += se.getAttribute(StringEntry.TOT_STRING_TEXT).toString();
sofs = ((IsNumeric) se.getAttribute(StringEntry.TOT_STRING_OFFSET_NEXT_ENTRY)).getValue();
if (sofs != -1) {
sofs += se.getOffset();
}
} else {
sofs = -1;
}
Expand Down
28 changes: 26 additions & 2 deletions src/org/infinity/resource/to/TotResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@ public int read(ByteBuffer buffer, int offset) throws Exception {
// looping through entries to consider split text segments
StringEntry stringEntry = new StringEntry(this, buffer, offset, idx);
while (stringEntry != null) {
if (!isStringEntryValid(stringEntry)) {
throw new Exception(String.format("Invalid string section found at offset 0x%x", stringEntry.getOffset()));
}
offset = stringEntry.getEndOffset();
addField(stringEntry);
idx++;
int ofsNextEntry = ((IsNumeric) stringEntry.getAttribute(StringEntry.TOT_STRING_OFFSET_NEXT_ENTRY))
.getValue();
if (ofsNextEntry != -1) {
// Note: next entry offset is relative to structure base offset
stringEntry = new StringEntry(this, buffer, stringEntry.getOffset() + ofsNextEntry, idx);
stringEntry = new StringEntry(this, buffer, ofsNextEntry, idx);
} else {
stringEntry = null;
}
Expand Down Expand Up @@ -111,6 +113,28 @@ public int read(ByteBuffer buffer, int offset) throws Exception {
return endoffset;
}

/**
* Analyzes a TOT {@code StringEntry} to determine whether the entry contains valid data.
*
* @param entry a {@link StringEntry}
* @return {@code true} if the entry is valid, {@code false} otherwise.
*/
public static boolean isStringEntryValid(StringEntry entry) {
boolean retVal = false;

if (entry != null) {
try {
int ofsPrev = ((IsNumeric) entry.getAttribute(StringEntry.TOT_STRING_OFFSET_PREV_ENTRY)).getValue();
int ofsNext = ((IsNumeric) entry.getAttribute(StringEntry.TOT_STRING_OFFSET_NEXT_ENTRY)).getValue();
retVal = (ofsPrev == -1 && ofsNext == -1) || (ofsPrev != ofsNext);
} catch (Exception e) {
e.printStackTrace();
}
}

return retVal;
}

/**
* Attempts to find the associated TOH resource in the same directory as the current TOT resource and loads it if
* available.
Expand Down

0 comments on commit 3f2507d

Please sign in to comment.