GP-3210 fix manual xml serialization of high unicode characters

This commit is contained in:
dev747368
2023-03-16 23:55:22 +00:00
parent 82ba4831b6
commit eb130ac8e2
3 changed files with 27 additions and 20 deletions

View File

@@ -17,11 +17,12 @@ package ghidra.framework.options;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Date;
import java.awt.Color; import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.io.*; import java.io.*;
import java.util.Arrays;
import java.util.Date;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
@@ -342,7 +343,7 @@ public class SaveStateTest extends AbstractGenericTest {
ss.putString(greaterThanLessThanKey, stringWithGreaterThanAndLessThan); ss.putString(greaterThanLessThanKey, stringWithGreaterThanAndLessThan);
String stringWithLargeHexDigit = String stringWithLargeHexDigit =
"The following is a large hex digit: \u0128, \u0132, \307 and \253 " + "The following is a large hex digit: \u0128, \u0132, \307 and \253 \uD835\uDCC8 " +
"with some trailing text ÿ"; "with some trailing text ÿ";
String hexDigitKey = "HEX_DIGIT_KEY"; String hexDigitKey = "HEX_DIGIT_KEY";
ss.putString(hexDigitKey, stringWithLargeHexDigit); ss.putString(hexDigitKey, stringWithLargeHexDigit);

View File

@@ -59,7 +59,8 @@ public class PropertyFileTest extends AbstractGenericTest {
pf.putInt("TestInt", 1234); pf.putInt("TestInt", 1234);
pf.putLong("TestLong", 0x12345678); pf.putLong("TestLong", 0x12345678);
StringBuffer sb = new StringBuffer("Line1\nLine2\n\"Ugly\" & Special <Values>; "); StringBuffer sb = new StringBuffer(
"Line1\nLine2\n\"Ugly\" & Special <Values>; \u0128, \u0132, \307 and \253");
for (int i = 1; i < 35; i++) { for (int i = 1; i < 35; i++) {
sb.append((char) i); sb.append((char) i);
} }
@@ -70,6 +71,10 @@ public class PropertyFileTest extends AbstractGenericTest {
pf.putString("TestString", URLEncoder.encode(str, "UTF-8")); pf.putString("TestString", URLEncoder.encode(str, "UTF-8"));
// also test plain unicode values, as well as a 32bit unicode value
String string2 = "non-control char values: < & ; > \u00bb \u0128, \u0132, \uD835\uDCC8";
pf.putString("TestString2", string2);
pf.writeState(); pf.writeState();
PropertyFile pf2 = new PropertyFile(parent, storageName, "/", NAME); PropertyFile pf2 = new PropertyFile(parent, storageName, "/", NAME);
@@ -81,6 +86,7 @@ public class PropertyFileTest extends AbstractGenericTest {
assertEquals(1234, pf2.getInt("TestInt", -1)); assertEquals(1234, pf2.getInt("TestInt", -1));
assertEquals(0x12345678, pf2.getLong("TestLong", -1)); assertEquals(0x12345678, pf2.getLong("TestLong", -1));
assertEquals(str, URLDecoder.decode(pf2.getString("TestString", null), "UTF-8")); assertEquals(str, URLDecoder.decode(pf2.getString("TestString", null), "UTF-8"));
assertEquals(string2, pf2.getString("TestString2", null));
} }

View File

@@ -15,12 +15,13 @@
*/ */
package ghidra.util.xml; package ghidra.util.xml;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.io.*;
import java.nio.charset.StandardCharsets;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParserFactory;
@@ -87,19 +88,21 @@ public class XmlUtilities {
* @return the encoded XML string * @return the encoded XML string
*/ */
public static String escapeElementEntities(String xml) { public static String escapeElementEntities(String xml) {
StringBuffer buffer = new StringBuffer(); StringBuilder buffer = new StringBuilder();
for (int i = 0; i < xml.length(); i++) { for (int offset = 0; offset < xml.length();) {
char next = xml.charAt(i); int codePoint = xml.codePointAt(offset);
if ((next < ' ') && (next != 0x09) && (next != 0x0A) && (next != 0x0D)) { offset += Character.charCount(codePoint);
if ((codePoint < ' ') && (codePoint != 0x09) && (codePoint != 0x0A) && (codePoint != 0x0D)) {
continue; continue;
} }
if (next >= 0x7F) { if (codePoint >= 0x7F) {
buffer.append("&#x"); buffer.append("&#x");
buffer.append(Integer.toString(next, 16).toUpperCase()); buffer.append(Integer.toString(codePoint, 16).toUpperCase());
buffer.append(";"); buffer.append(";");
continue; continue;
} }
switch (next) { switch (codePoint) {
case '<': case '<':
buffer.append(LESS_THAN); buffer.append(LESS_THAN);
break; break;
@@ -115,11 +118,8 @@ public class XmlUtilities {
case '&': case '&':
buffer.append(AMPERSAND); buffer.append(AMPERSAND);
break; break;
// Why was 7F deleted
// case 0x7F:
// break;
default: default:
buffer.append(next); buffer.appendCodePoint(codePoint);
break; break;
} }
} }
@@ -137,10 +137,10 @@ public class XmlUtilities {
public static String unEscapeElementEntities(String escapedXMLString) { public static String unEscapeElementEntities(String escapedXMLString) {
Matcher matcher = HEX_DIGIT_PATTERN.matcher(escapedXMLString); Matcher matcher = HEX_DIGIT_PATTERN.matcher(escapedXMLString);
StringBuffer buffy = new StringBuffer(); StringBuilder buffy = new StringBuilder();
while (matcher.find()) { while (matcher.find()) {
int intValue = Integer.parseInt(matcher.group(1), 16); int codePoint = Integer.parseInt(matcher.group(1), 16);
matcher.appendReplacement(buffy, Character.toString((char) intValue)); matcher.appendReplacement(buffy, Character.toString(codePoint));
} }
matcher.appendTail(buffy); matcher.appendTail(buffy);