Fix pxj JSON output to match radare2 byte arrays

This commit is contained in:
pancake committed 2026-10-16 00:03:02 +02:00
1 parent a7dfaa7712
commit 856fb00c47
2 files changed
+30 -29

No files matched your search

@@ -86,7 +86,7 @@ private String executeP8Command(R2Command command, R2Context context) throws R2C
// Format output based on suffix
if (command.hasSuffix('j')) {
return formatP8Json(bytes);
return formatBytesJson(bytes);
} else {
return formatP8Text(bytes);
}
@@ -105,7 +105,7 @@ private String formatP8Text(byte[] bytes) {
}
/** Format bytes as a JSON array */
private String formatP8Json(byte[] bytes) {
private String formatBytesJson(byte[] bytes) {
JSONArray array = new JSONArray();
for (byte b : bytes) {
array.put(b & 0xFF);
@@ -136,7 +136,7 @@ private String executeP8fCommand(R2Command command, R2Context context) throws R2
// Format output based on suffix
if (command.hasSuffix('j')) {
return formatP8Json(bytes);
return formatBytesJson(bytes);
} else {
return formatP8Text(bytes);
}
@@ -332,7 +332,7 @@ private String executePxCommand(R2Command command, R2Context context) throws R2C
try {
byte[] bytes = context.getAPI().getBytes(baseAddr, count);
if (command.hasSuffix('j')) {
return formatPxJson(bytes, baseAddr, context);
return formatBytesJson(bytes);
}
return formatPxText(bytes, baseAddr, context);
} catch (Exception e) {
@@ -362,7 +362,7 @@ private String executePxfCommand(R2Command command, R2Context context) throws R2
byte[] bytes = context.getAPI().getBytes(baseAddr, functionSize);
if (command.hasSuffix('j')) {
return formatPxJson(bytes, baseAddr, context);
return formatBytesJson(bytes);
}
return formatPxText(bytes, baseAddr, context);
} catch (Exception e) {
@@ -519,30 +519,6 @@ private String executePdfCommand(R2Command command, R2Context context) throws R2
}
}
/** Format hexdump as JSON array of objects with address, bytes, and ascii */
private String formatPxJson(byte[] bytes, Address baseAddr, R2Context context) {
JSONArray array = new JSONArray();
int lineSize = 16;
for (int offset = 0; offset < bytes.length; offset += lineSize) {
long addrOffset = baseAddr.getOffset() + offset;
JSONObject obj = new JSONObject();
obj.put("addr", addrOffset);
JSONArray data = new JSONArray();
int end = Math.min(offset + lineSize, bytes.length);
StringBuilder ascii = new StringBuilder();
for (int i = offset; i < end; i++) {
data.put(bytes[i] & 0xFF);
int b = bytes[i] & 0xFF;
char c = (b >= 32 && b < 127) ? (char) b : '.';
ascii.append(c);
}
obj.put("bytes", data);
obj.put("ascii", ascii.toString());
array.put(obj);
}
return array.toString() + "\n";
}
/** Class to hold disassembled instruction data */
private static class DisassembledInstruction {
long address;
@@ -18,6 +18,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.json.JSONArray;
import r4ghidra.R4GhidraState;
import r4ghidra.project.R2Project.*;
import r4ghidra.repl.*;
@@ -80,6 +81,7 @@ public class R2ProjectIntegrationTest {
check(
program.getReferenceManager().getReferencesFrom(base.add(0x20)).length == 1,
"rebased reference");
testHexdumpJson(program, repl, base);
check(repl.executeCommand("prj?").contains("prj save"), "multi-character help");
check(repl.executeCommand("? prj").contains("prj save"), "help lookup");
check(repl.executeCommand("prj load").contains("Usage:"), "missing path");
@@ -175,6 +177,29 @@ public class R2ProjectIntegrationTest {
}
}
private static void testHexdumpJson(ProgramDB program, R2REPLImpl repl, Address base)
throws Exception {
byte[] bytes = {
0, 1, 127, (byte) 128, (byte) 255, 16, 32, 48, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74
};
int tx = program.startTransaction("JSON hexdump fixture");
try {
program.getMemory().setBytes(base.add(0x80), bytes);
} finally {
program.endTransaction(tx, true);
}
List<Integer> expected =
List.of(0, 1, 127, 128, 255, 16, 32, 48, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74);
for (String command : List.of("pxj 19 @0x2080", "xj 19 @0x2080", "p8j 19 @0x2080")) {
String output = repl.executeCommand(command);
check(new JSONArray(output).toList().equals(expected), command + " byte array: " + output);
}
String output = repl.executeCommand("pxfj @0x2020");
check(
new JSONArray(output).toList().equals(List.of(144, 144, 144, 144, 144, 144, 144, 144)),
"pxfj byte array: " + output);
}
private static void testNativeImport(Language language, byte[] data) throws Exception {
Object consumer = new Object();
ProgramDB program =