fix(gui): validate hex address in GotoAddressDialog (PR #2512)

chore: use check if entered valid hex address from GotoAddressDialog & make error style search field if hex search value not valid in hex viewer
This commit is contained in:
Yaroslav
2025-05-25 01:00:18 +03:00
committed by GitHub
parent fb02e32a6a
commit abd64007e2
5 changed files with 67 additions and 51 deletions
@@ -4,6 +4,7 @@ import javax.swing.JOptionPane;
import org.exbin.bined.swing.section.SectCodeArea;
import jadx.gui.utils.HexUtils;
import jadx.gui.utils.NLS;
public class GotoAddressDialog {
@@ -14,6 +15,11 @@ public class GotoAddressDialog {
JOptionPane.QUESTION_MESSAGE, null, null,
Long.toHexString(codeArea.getDataPosition()));
if (o != null) {
boolean isValidAddress = HexUtils.isValidHexString(toString());
if (!isValidAddress) {
return;
}
codeArea.setActiveCaretPosition(Long.parseLong(o.toString(), 16));
codeArea.validateCaret();
codeArea.revealCursor();
@@ -486,7 +486,7 @@ public class SearchDialog extends CommonSearchDialog {
String searchPackageText = packageField.getText();
SearchSettings searchSettings = new SearchSettings(text, !ignoreCase, useRegex, searchPackageText);
String error = searchSettings.prepare(mainWindow);
changeSearchFieldStyle(!StringUtils.isEmpty(error));
UiUtils.highlightAsErrorField(searchField, !StringUtils.isEmpty(error));
if (!StringUtils.isEmpty(error)) {
resultsInfoLabel.setText(error);
return null;
@@ -499,15 +499,6 @@ public class SearchDialog extends CommonSearchDialog {
return newSearchTask;
}
private void changeSearchFieldStyle(boolean isError) {
if (isError) {
searchField.putClientProperty("JComponent.outline", "error");
} else {
searchField.putClientProperty("JComponent.outline", "");
}
searchField.repaint();
}
private boolean buildSearch(SearchTask newSearchTask, String text, SearchSettings searchSettings) {
List<JavaClass> searchClasses;
if (options.contains(ACTIVE_TAB)) {
@@ -25,9 +25,11 @@ import jadx.gui.ui.hexviewer.search.BinarySearch;
import jadx.gui.ui.hexviewer.search.SearchCondition;
import jadx.gui.ui.hexviewer.search.SearchParameters;
import jadx.gui.ui.hexviewer.search.service.BinarySearchServiceImpl;
import jadx.gui.utils.HexUtils;
import jadx.gui.utils.Icons;
import jadx.gui.utils.NLS;
import jadx.gui.utils.TextStandardActions;
import jadx.gui.utils.UiUtils;
public class HexSearchBar extends JToolBar {
private static final long serialVersionUID = 1836871286618633003L;
@@ -237,8 +239,10 @@ public class HexSearchBar extends JToolBar {
condition.setSearchText(searchField.getText());
} else {
String hexBytes = searchField.getText();
if (isValidHexString(hexBytes)) {
condition.setBinaryData(new ByteArrayEditableData(hexStringToByteArray(hexBytes)));
boolean isValidHexInput = HexUtils.isValidHexString(hexBytes);
UiUtils.highlightAsErrorField(searchField, !isValidHexInput);
if (isValidHexInput) {
condition.setBinaryData(new ByteArrayEditableData(HexUtils.hexStringToByteArray(hexBytes)));
}
}
}
@@ -246,6 +250,7 @@ public class HexSearchBar extends JToolBar {
}
public void updateFindStatus() {
UiUtils.highlightAsErrorField(searchField, false);
SearchCondition condition = makeSearchCondition();
if (condition.getSearchMode() == SearchCondition.SearchMode.TEXT) {
findTypeCB.setSelected(false);
@@ -262,45 +267,6 @@ public class HexSearchBar extends JToolBar {
findTypeCB.setToolTipText(NLS.str("search.find_type_hex"));
}
private boolean isValidHexString(String hexString) {
String cleanS = hexString.replace(" ", "");
int len = cleanS.length();
try {
boolean isPair = len % 2 == 0;
if (isPair) {
Long.parseLong(cleanS, 16);
return true;
}
} catch (NumberFormatException ex) {
// ignore error
return false;
}
return false;
}
public byte[] hexStringToByteArray(String hexString) {
if (hexString == null || hexString.isEmpty()) {
return new byte[0];
}
String cleanS = hexString.replace(" ", "");
int len = cleanS.length();
if (!isValidHexString(hexString)) {
throw new IllegalArgumentException("Hex string must have even length. Input length: " + len);
}
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
String byteString = cleanS.substring(i, i + 2);
try {
int intValue = Integer.parseInt(byteString, 16);
data[i / 2] = (byte) intValue;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Input string contains non-hex characters at index " + i + ": " + byteString, e);
}
}
return data;
}
public interface Control {
void prevMatch();
@@ -0,0 +1,43 @@
package jadx.gui.utils;
public class HexUtils {
public static boolean isValidHexString(String hexString) {
String cleanS = hexString.replace(" ", "");
int len = cleanS.length();
try {
boolean isPair = len % 2 == 0;
if (isPair) {
Long.parseLong(cleanS, 16);
return true;
}
} catch (NumberFormatException ex) {
// ignore error
return false;
}
return false;
}
public static byte[] hexStringToByteArray(String hexString) {
if (hexString == null || hexString.isEmpty()) {
return new byte[0];
}
String cleanS = hexString.replace(" ", "");
int len = cleanS.length();
if (!isValidHexString(hexString)) {
throw new IllegalArgumentException("Hex string must have even length. Input length: " + len);
}
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
String byteString = cleanS.substring(i, i + 2);
try {
int intValue = Integer.parseInt(byteString, 16);
data[i / 2] = (byte) intValue;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Input string contains non-hex characters at index " + i + ": " + byteString, e);
}
}
return data;
}
}
@@ -27,6 +27,7 @@ import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.RootPaneContainer;
@@ -514,4 +515,13 @@ public class UiUtils {
hsb[2] = Math.min(1.0f, hsb[2] * factor); // Adjust brightness
return Color.getHSBColor(hsb[0], hsb[1], hsb[2]);
}
public static void highlightAsErrorField(final JTextField field, boolean isError) {
if (isError) {
field.putClientProperty("JComponent.outline", "error");
} else {
field.putClientProperty("JComponent.outline", "");
}
field.repaint();
}
}