diff --git a/Ghidra/Features/Base/src/main/java/ghidra/base/actions/HorizontalRuleAction.java b/Ghidra/Features/Base/src/main/java/ghidra/base/actions/HorizontalRuleAction.java
index 568855e25c..81834beb74 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/base/actions/HorizontalRuleAction.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/base/actions/HorizontalRuleAction.java
@@ -48,9 +48,16 @@ public class HorizontalRuleAction extends DockingAction {
// the description is meant to be used for the tooltip and is larger
String padding = " ";
- setDescription("
" + padding + HTMLUtilities.escapeHTML(topName) + padding +
- "
" + padding + HTMLUtilities.escapeHTML(bottomName) + padding +
- "");
+ setDescription("" + padding +
+ fixupFirstAmp(HTMLUtilities.escapeHTML(topName) + padding + "
" + padding +
+ HTMLUtilities.escapeHTML(bottomName)) +
+ padding + "");
+ }
+
+ private String fixupFirstAmp(String text) {
+ // add an extra & to replace the one that the MenuData will eat
+ int index = text.indexOf('&');
+ return index < 0 ? text : text.substring(0, index) + "&" + text.substring(index);
}
@Override
diff --git a/Ghidra/Features/Base/src/test/java/ghidra/app/util/html/DataTypeDifferTest.java b/Ghidra/Features/Base/src/test/java/ghidra/app/util/html/DataTypeDifferTest.java
index ac7dd9824b..ad0ee0c5aa 100644
--- a/Ghidra/Features/Base/src/test/java/ghidra/app/util/html/DataTypeDifferTest.java
+++ b/Ghidra/Features/Base/src/test/java/ghidra/app/util/html/DataTypeDifferTest.java
@@ -26,7 +26,7 @@ import javax.swing.*;
import org.junit.Assert;
import org.junit.Test;
-import docking.widgets.label.GDHtmlLabel;
+import docking.widgets.label.GHtmlLabel;
import ghidra.app.util.html.diff.*;
public class DataTypeDifferTest {
@@ -490,24 +490,19 @@ public class DataTypeDifferTest {
JPanel panel = new JPanel(new BorderLayout());
JPanel rightPanel = new JPanel(new BorderLayout());
- StringBuffer buffy1 = new StringBuffer(htmlLeft);
- JLabel rightLabel = new GDHtmlLabel();
+ JLabel rightLabel = new GHtmlLabel(htmlLeft);
rightLabel.setOpaque(true);
rightLabel.setBackground(Color.WHITE);
rightLabel.setVerticalAlignment(SwingConstants.TOP);
rightPanel.add(rightLabel);
JPanel leftPanel = new JPanel(new BorderLayout());
- StringBuffer buffy2 = new StringBuffer(htmlRight);
- JLabel leftLabel = new GDHtmlLabel();
+ JLabel leftLabel = new GHtmlLabel(htmlRight);
leftLabel.setOpaque(true);
leftLabel.setBackground(Color.WHITE);
leftLabel.setVerticalAlignment(SwingConstants.TOP);
leftPanel.add(leftLabel);
- rightLabel.setText(buffy1.toString());
- leftLabel.setText(buffy2.toString());
-
JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(leftPanel),
new JScrollPane(rightPanel));
pane.setResizeWeight(.5);
diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java
index a6526adc62..98d79a0e00 100644
--- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java
+++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/HTMLUtilities.java
@@ -601,9 +601,12 @@ public class HTMLUtilities {
/**
* Escapes any HTML special characters in the specified text.
*
- * Does not otherwise modify the input text or wrap lines.
+ * Does not otherwise modify the input text or wrap lines.
+ *
+ * Calling this twice will result in text being double-escaped, which will not display correctly.
+ *
+ * See also {@link StringEscapeUtils#escapeHtml3(String)} if you need quote-safe html encoding.
*
- * See also {@link StringEscapeUtils#escapeHtml3(String)}.
*
* @param text plain-text that might have some characters that should NOT be interpreted as HTML
* @return string with any html characters replaced with equivalents
diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java b/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java
index 2f46d72948..92c1203df4 100644
--- a/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java
+++ b/Ghidra/Framework/Generic/src/test/java/ghidra/util/HTMLUtilitiesTest.java
@@ -173,4 +173,17 @@ public class HTMLUtilitiesTest {
String htmlStr = HTMLUtilities.convertLinkPlaceholdersToHyperlinks(placeholderStr);
assertEquals("Stuff inside link tag", htmlStr);
}
+
+ @Test
+ public void testEscapeHTML() {
+ assertEquals("abc", HTMLUtilities.escapeHTML("abc"));
+ assertEquals("∢", HTMLUtilities.escapeHTML("\u2222"));
+
+ // unicode char above 0xffff encoded with 2 utf-16 characters
+ assertEquals("🍄", HTMLUtilities.escapeHTML("\uD83C\uDF44"));
+
+ assertEquals("<abc>", HTMLUtilities.escapeHTML(""));
+ assertEquals("a&b", HTMLUtilities.escapeHTML("a&b"));
+
+ }
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java
index e988107073..aca4e79313 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java
@@ -30,7 +30,7 @@ import docking.ComponentProvider;
import docking.action.DockingActionIf;
import docking.help.Help;
import docking.help.HelpService;
-import docking.widgets.label.GDHtmlLabel;
+import docking.widgets.label.GHtmlLabel;
import docking.widgets.table.*;
import docking.widgets.table.threaded.*;
import ghidra.framework.main.FrontEndPlugin;
@@ -222,8 +222,8 @@ public class ProjectDataTablePanel extends JPanel {
}
}
- private JLabel capacityExceededText =
- new GDHtmlLabel("Table view disabled for very large projects, or
" +
+ private GHtmlLabel capacityExceededText =
+ new GHtmlLabel("Table view disabled for very large projects, or
" +
"if an older project/repository filesystem is in use.
" +
"View will remain disabled until project is closed.");