Skip to content

Commit

Permalink
librz/core/cmd: convert pj to RzShell (#4726)
Browse files Browse the repository at this point in the history
Move the `pj `command to RzShell. It also does some clean ups:

 -  Remove `pj.`, because it was an alias for pj @ 0
 -  Remove `pj..`, because the JSON path function always returned NULL (never a valid value), and did not document what it does in the first place.
 -  Print message for user if no valid data was found at address.
 -  Change description of command to be more clear it only prints formatted JSON strings.
 -  Remove unused size/len argument.
 - Add a new test for `pj`.
 - Add some general documentation how to implement or find a command.
  • Loading branch information
Rot127 authored Nov 24, 2024
1 parent 3556a7e commit be24ca8
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 164 deletions.
60 changes: 16 additions & 44 deletions librz/core/cmd/cmd_print.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <rz_types.h>

#include "../core_private.h"
#include "rz_util/rz_strbuf.h"
#include <rz_util/rz_strbuf.h>

#define PF_USAGE_STR "pf[.k[.f[=v]]|[v]]|[n]|[0|cnt][fmt] [a0 a1 ...]"

Expand Down Expand Up @@ -131,7 +131,6 @@ static const char *help_msg_p[] = {
"ph", "[?][=|hash] ([len])", "calculate hash for a block",
"pi", "[?][bdefrj] [num]", "print instructions",
"pI", "[?][iI][df] [len]", "print N instructions/bytes (f=func)",
"pj", "[?] [len]", "print as indented JSON",
"pm", "[?] [magic]", "print libmagic data (see pm? and /m?)",
"po", "[?] hex", "print operation applied to block (see po?)",
"pp", "[?][sz] [len]", "print patterns, see pp? for more help",
Expand All @@ -145,14 +144,6 @@ static const char *help_msg_p[] = {
NULL
};

static const char *help_msg_pj[] = {
"Usage:", "pj[..] [size]", "",
"pj", "", "print current block as indented JSON",
"pj.", "", "print as indented JSON from 0 to the current offset",
"pj..", "", "print JSON path from 0 to the current offset",
NULL
};

static const char *help_msg_px[] = {
"Usage:", "px[0afoswqWqQ][f]", " # Print heXadecimal",
"px", "", "show hexdump",
Expand Down Expand Up @@ -2507,40 +2498,6 @@ RZ_IPI int rz_cmd_print(void *data, const char *input) {
rz_core_block_read(core);
}
switch (*input) {
case 'j': // "pj"
if (input[1] == '?') {
rz_core_cmd_help(core, help_msg_pj);
} else if (input[1] == '.') {
if (input[2] == '.') {
ut8 *data = calloc(core->offset + 1, 1);
if (data) {
data[core->offset] = 0;
(void)rz_io_read_at(core->io, 0, data, core->offset);
char *res = rz_print_json_path((const char *)data, core->offset);
if (res) {
rz_cons_printf("-> res(%s)\n", res);
}
/*
char *res = rz_print_json_indent ((char*)data, false, " ", NULL);
print_json_path (core, res);
free (res);
*/
} else {
RZ_LOG_ERROR("core: Cannot allocate %d\n", (int)(core->offset));
}
} else {
rz_core_cmdf(core, "pj %" PFMT64u " @ 0", core->offset);
}
} else {
if (core->blocksize < 4 || !memcmp(core->block, "\xff\xff\xff\xff", 4)) {
RZ_LOG_ERROR("core: Cannot read\n");
} else {
char *res = rz_print_json_indent((const char *)core->block, true, " ", NULL);
rz_cons_printf("%s\n", res);
free(res);
}
}
break;
case 'x': // "px"
{
bool show_offset = rz_config_get_i(core->config, "hex.offset");
Expand Down Expand Up @@ -3517,6 +3474,21 @@ RZ_IPI RzCmdStatus rz_cmd_disassembly_function_handler(RzCore *core, int argc, c
return RZ_CMD_STATUS_OK;
}

RZ_IPI RzCmdStatus rz_print_current_block_json_handler(RzCore *core, int argc, const char **argv) {
rz_return_val_if_fail(core, RZ_CMD_STATUS_ERROR);
bool enable_color = rz_config_get_i(core->config, "escr.color") != 0;
char *res = rz_print_json_indent((const char *)core->block, enable_color, " ", NULL);
if (RZ_STR_ISEMPTY(res)) {
free(res);
RZ_LOG_ERROR("Couldn't find a JSON string.\n");
return RZ_CMD_STATUS_ERROR;
} else {
rz_cons_printf("%s\n", res);
}
free(res);
return RZ_CMD_STATUS_OK;
}

RZ_IPI RzCmdStatus rz_print_function_rzil_handler(RzCore *core, int argc, const char **argv) {
RzAnalysisFunction *f = rz_analysis_first_function_in(core->analysis, core->offset);
if (!f) {
Expand Down
11 changes: 11 additions & 0 deletions librz/core/cmd_descs/cmd_descs.c
Original file line number Diff line number Diff line change
Expand Up @@ -13994,6 +13994,14 @@ static const RzCmdDescHelp print_instructions_function_help = {
.args = print_instructions_function_args,
};

static const RzCmdDescArg print_current_block_json_args[] = {
{ 0 },
};
static const RzCmdDescHelp print_current_block_json_help = {
.summary = "Parse, format and print JSON at current offset.",
.args = print_current_block_json_args,
};

static const RzCmdDescArg print_function_rzil_args[] = {
{ 0 },
};
Expand Down Expand Up @@ -21975,6 +21983,9 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) {
RzCmdDesc *print_instructions_function_cd = rz_cmd_desc_argv_new(core->rcmd, pI_cd, "pIf", rz_print_instructions_function_handler, &print_instructions_function_help);
rz_warn_if_fail(print_instructions_function_cd);

RzCmdDesc *print_current_block_json_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_print_cd, "pj", rz_print_current_block_json_handler, &print_current_block_json_help);
rz_warn_if_fail(print_current_block_json_cd);

RzCmdDesc *print_function_rzil_cd = rz_cmd_desc_argv_new(core->rcmd, cmd_print_cd, "plf", rz_print_function_rzil_handler, &print_function_rzil_help);
rz_warn_if_fail(print_function_rzil_cd);

Expand Down
2 changes: 2 additions & 0 deletions librz/core/cmd_descs/cmd_descs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,8 @@ RZ_IPI RzCmdStatus rz_assembly_of_hex_alias_handler(RzCore *core, int argc, cons
RZ_IPI RzCmdStatus rz_print_instructions_handler(RzCore *core, int argc, const char **argv);
// "pIf"
RZ_IPI RzCmdStatus rz_print_instructions_function_handler(RzCore *core, int argc, const char **argv);
// "pj"
RZ_IPI RzCmdStatus rz_print_current_block_json_handler(RzCore *core, int argc, const char **argv);
// "plf"
RZ_IPI RzCmdStatus rz_print_function_rzil_handler(RzCore *core, int argc, const char **argv);
// "pp0"
Expand Down
4 changes: 4 additions & 0 deletions librz/core/cmd_descs/cmd_print.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,10 @@ commands:
summary: Print all instructions at the current function
cname: print_instructions_function
args: []
- name: pj
summary: Parse, format and print JSON at current offset.
cname: print_current_block_json
args: []
- name: plf
summary: Print the RzIL of the function
cname: print_function_rzil
Expand Down
3 changes: 1 addition & 2 deletions librz/include/rz_util/rz_print.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,8 @@ RZ_API int rz_print_row_at_off(RzPrint *p, ut32 offset);

// WIP
RZ_API void rz_print_set_screenbounds(RzPrint *p, ut64 addr);
RZ_API char *rz_print_json_indent(const char *s, bool color, const char *tab, const char **colors);
RZ_API RZ_OWN char *rz_print_json_indent(RZ_NULLABLE const char *s, bool color, const char *tab, RZ_NULLABLE const char **palette);
RZ_API char *rz_print_json_human(const char *s);
RZ_API char *rz_print_json_path(const char *s, int pos);

RZ_API RZ_OWN RzStrBuf *rz_print_colorize_asm_str(RZ_BORROW RzPrint *p, const RzAsmTokenString *toks);
RZ_API void rz_print_colored_help_option(const char *option, const char *arg, const char *description, size_t maxOptionAndArgLength);
Expand Down
135 changes: 18 additions & 117 deletions librz/util/json_indent.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,126 +31,16 @@ enum {
JC_RESET,
};

static const char *origColors[] = {
/**
* \brief Default colors for json printing.
*/
static const char *default_colors[] = {
"\x1b[31m",
"\x1b[32m",
"\x1b[33m",
"\x1b[34m",
"\x1b[0m",
};
// static const char colors

RZ_API char *rz_print_json_path(const char *s, int pos) {
int indent = 0;
#define DSZ 128
const char *words[DSZ] = { NULL };
int lengths[DSZ] = { 0 };
int indexs[DSZ] = { 0 };
int instr = 0;
bool isarr = false;
if (!s) {
return NULL;
}
int arrpos = 0;
const char *os = s;
int osz = (1 + strlen(s)) * 20;
if (osz < 1) {
return NULL;
}

const char *str_a = NULL;
for (; *s; s++) {
if (instr) {
if (s[0] == '"') {
instr = 0;
ut64 cur = str_a - os;
if (cur > pos) {
break;
}
if (indent < DSZ) {
words[indent - 1] = str_a;
lengths[indent - 1] = s - str_a;
indexs[indent - 1] = 0;
}
}
continue;
}

if (s[0] == '"') {
instr = 1;
str_a = s + 1;
}
if (*s == '\n' || *s == '\r' || *s == '\t' || *s == ' ') {
continue;
}
switch (*s) {
case ':':
break;
case ',':
if (isarr) {
arrpos++;
if (indent < DSZ) {
indexs[indent - 1] = arrpos;
lengths[indent - 1] = (s - os);
}
}
break;
case '{':
case '[':
if (*s == '[') {
isarr = true;
arrpos = 0;
}
if (indent > 128) {
eprintf("JSON indentation is too deep\n");
indent = 0;
} else {
indent++;
}
break;
case '}':
case ']':
if (*s == ']') {
isarr = false;
}
indent--;
break;
}
}
int i;
ut64 opos = 0;
for (i = 0; i < DSZ && i < indent; i++) {
if ((int)(size_t)words[i] < DSZ) {
ut64 cur = lengths[i];
if (cur < opos) {
continue;
}
opos = cur;
if (cur > pos) {
break;
}
eprintf("0x%08" PFMT64x " %d [%d]\n", cur, i, indexs[i]);
} else {
ut64 cur = words[i] - os - 1;
if (cur < opos) {
continue;
}
opos = cur;
if (cur > pos) {
break;
}
char *a = rz_str_ndup(words[i], lengths[i]);
char *q = strchr(a, '"');
if (q) {
*q = 0;
}
eprintf("0x%08" PFMT64x " %d %s\n", cur, i, a);
free(a);
}
}
// TODO return something
return NULL;
}

RZ_API char *rz_print_json_human(const char *s) {
int indent = 0;
Expand Down Expand Up @@ -251,7 +141,18 @@ RZ_API char *rz_print_json_human(const char *s) {
return O;
}

RZ_API char *rz_print_json_indent(const char *s, bool color, const char *tab, const char **palette) {
/**
* \brief Formats the JSON string at \p s with indentation.
*
* \param s The JSON string to format.
* \param color Format with color?
* \param tab The string to use as indentation tab.
* \param palette The color palette to use. If NULL and \p color == true, a default color palatte is used.
*
* \return The formatted JSON string or NULL in case of failure.
*/
RZ_API RZ_OWN char *rz_print_json_indent(RZ_NULLABLE const char *s, bool color, const char *tab, RZ_NULLABLE const char **palette) {
rz_return_val_if_fail(tab, NULL);
int indent = 0;
const int indentSize = strlen(tab);
int instr = 0;
Expand All @@ -260,13 +161,13 @@ RZ_API char *rz_print_json_indent(const char *s, bool color, const char *tab, co
if (!s) {
return NULL;
}
const char **colors = palette ? palette : origColors;
const char **colors = palette ? palette : default_colors;
int osz = (1 + strlen(s)) * 20;
if (osz < 1) {
return NULL;
}

char *O = malloc(osz);
char *O = RZ_NEWS0(char, osz);
if (!O) {
return NULL;
}
Expand Down
46 changes: 45 additions & 1 deletion test/db/cmd/print
Original file line number Diff line number Diff line change
Expand Up @@ -266,5 +266,49 @@ prz 100 | rz-ax -S
EOF
EXPECT=<<EOF
7f454c46020101
EOF
EOF
RUN

NAME=pj - Print json
FILE==
CMDS=<<EOF
ws "{\"as\": [1, 2, 3],\"asdf\": {\"a\": 1,\"b\": 0}}"
pj
s 0x4
pj
pj @ 0
pj @ 0x80
EOF
EXPECT=<<EOF
{
"as": [
1,
2,
3
],
"asdf": {
"a": 1,
"b": 0
}
}
[
1,
2,
3
] {
"a": 1,
"b": 0
}
{
"as": [
1,
2,
3
],
"asdf": {
"a": 1,
"b": 0
}
}
EOF
RUN

0 comments on commit be24ca8

Please sign in to comment.