Add cfg.json.* encoding options (#17681) ##json
This commit is contained in:
parent
7c86add0dc
commit
afb8b7bd1f
21 changed files with 419 additions and 53 deletions
|
|
@ -1101,7 +1101,7 @@ static bool rz_anal_class_list_json_cb(void *user, const char *k, const char *v)
|
|||
}
|
||||
|
||||
static void rz_anal_class_list_json(RzAnal *anal) {
|
||||
PJ *j = pj_new ();
|
||||
PJ *j = anal->coreb.pjWithEncoding (anal->coreb.core);
|
||||
if (!j) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1704,8 +1704,8 @@ RZ_API int rz_anal_function_complexity(RzAnalFunction *fcn) {
|
|||
|
||||
// tfj and afsj call this function
|
||||
RZ_API char *rz_anal_function_get_json(RzAnalFunction *function) {
|
||||
PJ *pj = pj_new ();
|
||||
RzAnal *a = function->anal;
|
||||
PJ *pj = a->coreb.pjWithEncoding (a->coreb.core);
|
||||
char *args = strdup ("");
|
||||
char *sdb_ret = rz_str_newf ("func.%s.ret", function->name);
|
||||
char *sdb_args = rz_str_newf ("func.%s.args", function->name);
|
||||
|
|
|
|||
|
|
@ -2040,7 +2040,7 @@ RZ_API void rz_sign_list(RzAnal *a, int format) {
|
|||
PJ *pj = NULL;
|
||||
|
||||
if (format == 'j') {
|
||||
pj = pj_new ();
|
||||
pj = a->coreb.pjWithEncoding (a->coreb.core);
|
||||
pj_a (pj);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ RZ_API void rz_anal_xrefs_list(RzAnal *anal, int rad) {
|
|||
listxrefs (anal->dict_refs, UT64_MAX, list);
|
||||
sortxrefs (list);
|
||||
if (rad == 'j') {
|
||||
pj = pj_new ();
|
||||
pj = anal->coreb.pjWithEncoding (anal->coreb.core);
|
||||
if (!pj) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ static char *anal_fcn_autoname(RzCore *core, RzAnalFunction *fcn, int dump, int
|
|||
RzList *refs = rz_anal_function_get_refs (fcn);
|
||||
if (mode == 'j') {
|
||||
// start a new JSON object
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (core);
|
||||
pj_a (pj);
|
||||
}
|
||||
if (refs) {
|
||||
|
|
@ -2786,7 +2786,7 @@ static int fcn_print_makestyle(RzCore *core, RzList *fcns, char mode) {
|
|||
PJ *pj = NULL;
|
||||
|
||||
if (mode == 'j') {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (core);
|
||||
pj_a (pj);
|
||||
}
|
||||
|
||||
|
|
@ -2985,7 +2985,7 @@ static int fcn_print_json(RzCore *core, RzAnalFunction *fcn, PJ *pj) {
|
|||
static int fcn_list_json(RzCore *core, RzList *fcns, bool quiet) {
|
||||
RzListIter *iter;
|
||||
RzAnalFunction *fcn;
|
||||
PJ *pj = pj_new ();
|
||||
PJ *pj = rz_core_pj_new (core);
|
||||
if (!pj) {
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -3653,7 +3653,7 @@ RZ_API int rz_core_anal_graph(RzCore *core, ut64 addr, int opts) {
|
|||
"\tedge [%s];\n", font, gv_spline, gv_node, gv_edge);
|
||||
}
|
||||
if (is_json) {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (core);
|
||||
if (!pj) {
|
||||
rz_config_hold_restore (hc);
|
||||
rz_config_hold_free (hc);
|
||||
|
|
@ -5708,7 +5708,7 @@ RZ_API void rz_core_anal_paths(RzCore *core, ut64 from, ut64 to, bool followCall
|
|||
|
||||
// Initialize a PJ object for json mode
|
||||
if (is_json) {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (core);
|
||||
pj_a (pj);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ static void _print_strings(RzCore *r, RzList *list, int mode, int va) {
|
|||
bin->minstrlen = minstr;
|
||||
bin->maxstrlen = maxstr;
|
||||
if (IS_MODE_JSON (mode)) {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (r);
|
||||
pj_a (pj);
|
||||
} else if (IS_MODE_RAD (mode)) {
|
||||
rz_cons_println ("fs strings");
|
||||
|
|
@ -455,7 +455,9 @@ static void _print_strings(RzCore *r, RzList *list, int mode, int va) {
|
|||
pj_kn (pj, "length", string->length);
|
||||
pj_ks (pj, "section", section_name);
|
||||
pj_ks (pj, "type", type_string);
|
||||
// data itself may be encoded so use pj_ks
|
||||
pj_ks (pj, "string", string->string);
|
||||
|
||||
switch (string->type) {
|
||||
case RZ_STRING_TYPE_UTF8:
|
||||
case RZ_STRING_TYPE_WIDE:
|
||||
|
|
@ -1126,7 +1128,7 @@ static int bin_dwarf(RzCore *core, int mode) {
|
|||
|
||||
PJ *j = NULL;
|
||||
if (IS_MODE_JSON (mode)) {
|
||||
j = pj_new ();
|
||||
j = rz_core_pj_new (core);
|
||||
pj_a (j);
|
||||
}
|
||||
|
||||
|
|
@ -1262,7 +1264,7 @@ RZ_API bool rz_core_pdb_info(RzCore *core, const char *file, int mode) {
|
|||
mode = 'd'; // default
|
||||
break;
|
||||
}
|
||||
PJ *pj = pj_new ();
|
||||
PJ *pj = rz_core_pj_new (core);
|
||||
|
||||
pdb.print_types (&pdb, pj, mode);
|
||||
pdb.print_gvars (&pdb, baddr, pj, mode);
|
||||
|
|
@ -1718,8 +1720,7 @@ static int bin_relocs(RzCore *r, int mode, int va) {
|
|||
rz_cons_println ("[Relocations]");
|
||||
rz_table_set_columnsf (table, "XXss", "vaddr", "paddr", "type", "name");
|
||||
} else if (IS_MODE_JSON (mode)) {
|
||||
// start a new JSON object
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (r);
|
||||
if (pj) {
|
||||
pj_a (pj);
|
||||
}
|
||||
|
|
@ -1972,7 +1973,7 @@ static int bin_imports(RzCore *r, int mode, int va, const char *name) {
|
|||
bool lit = info ? info->has_lit: false;
|
||||
char *str;
|
||||
int i = 0;
|
||||
PJ *pj = NULL;
|
||||
PJ *pj = NULL;
|
||||
|
||||
if (!info) {
|
||||
if (IS_MODE_JSON (mode)) {
|
||||
|
|
@ -1984,7 +1985,7 @@ static int bin_imports(RzCore *r, int mode, int va, const char *name) {
|
|||
RzList *imports = rz_bin_get_imports (r->bin);
|
||||
int cdsz = info? (info->bits == 64? 8: info->bits == 32? 4: info->bits == 16 ? 4: 0): 0;
|
||||
if (IS_MODE_JSON (mode)) {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (r);
|
||||
pj_a (pj);
|
||||
} else if (IS_MODE_RAD (mode)) {
|
||||
rz_cons_println ("fs imports");
|
||||
|
|
@ -2276,7 +2277,7 @@ static int bin_symbols(RzCore *r, int mode, ut64 laddr, int va, ut64 at, const c
|
|||
return 0;
|
||||
}
|
||||
|
||||
PJ *pj = pj_new ();
|
||||
PJ *pj = rz_core_pj_new (r);
|
||||
bool is_arm = info && info->arch && !strncmp (info->arch, "arm", 3);
|
||||
const char *lang = bin_demangle ? rz_config_get (r->config, "bin.lang") : NULL;
|
||||
|
||||
|
|
@ -3609,7 +3610,7 @@ static int bin_libs(RzCore *r, int mode) {
|
|||
|
||||
RzList *libs = rz_bin_get_libs (r->bin);
|
||||
if (IS_MODE_JSON (mode)) {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (r);
|
||||
pj_a (pj);
|
||||
} else {
|
||||
if (!libs) {
|
||||
|
|
@ -3845,7 +3846,7 @@ static void bin_elf_versioninfo(RzCore *r, int mode) {
|
|||
const char *oValue = NULL;
|
||||
PJ *pj = NULL;
|
||||
if (IS_MODE_JSON (mode)) {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (r);
|
||||
if (!pj) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -4030,7 +4031,7 @@ static void bin_pe_resources(RzCore *r, int mode) {
|
|||
} else if (IS_MODE_RAD (mode)) {
|
||||
rz_cons_printf ("fs resources\n");
|
||||
} else if (IS_MODE_JSON (mode)) {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (r);
|
||||
pj_a (pj);
|
||||
}
|
||||
while (true) {
|
||||
|
|
|
|||
|
|
@ -877,6 +877,40 @@ static bool cb_emuskip(void *user, void *data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool cb_jsonencoding(void *user, void *data) {
|
||||
RzConfigNode *node = (RzConfigNode*) data;
|
||||
if (*node->value == '?') {
|
||||
if (node->value[1] && node->value[1] == '?') {
|
||||
rz_cons_printf ("choose either: \n"\
|
||||
"none (default)\n" \
|
||||
"base64 - encode the json string values as base64\n" \
|
||||
"hex - convert the string to a string of hexpairs\n" \
|
||||
"array - convert the string to an array of chars\n" \
|
||||
"strip - strip non-printable characters\n");
|
||||
} else {
|
||||
print_node_options (node);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cb_jsonencoding_numbers(void *user, void *data) {
|
||||
RzConfigNode *node = (RzConfigNode*) data;
|
||||
if (*node->value == '?') {
|
||||
if (node->value[1] && node->value[1] == '?') {
|
||||
rz_cons_printf ("choose either: \n"\
|
||||
"none (default)\n" \
|
||||
"string - encode the json number values as strings\n" \
|
||||
"hex - encode the number values as hex, then as a string\n");
|
||||
} else {
|
||||
print_node_options (node);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cb_asm_armimm(void *user, void *data) {
|
||||
RzCore *core = (RzCore *) user;
|
||||
RzConfigNode *node = (RzConfigNode *) data;
|
||||
|
|
@ -3554,6 +3588,16 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
|||
SETBPREF ("esil.nonull", "false", "Prevent memory read, memory write at null pointer");
|
||||
SETCB ("esil.mdev.range", "", &cb_mdevrange, "Specify a range of memory to be handled by cmd.esil.mdev");
|
||||
|
||||
/* json encodings */
|
||||
n = NODECB ("cfg.json.str", "none", &cb_jsonencoding);
|
||||
SETDESC (n, "Encode strings from json outputs using the specified option");
|
||||
SETOPTIONS (n, "none", "base64", "strip", "hex", "array", NULL);
|
||||
|
||||
n = NODECB ("cfg.json.num", "none", &cb_jsonencoding_numbers);
|
||||
SETDESC (n, "Encode numbers from json outputs using the specified option");
|
||||
SETOPTIONS (n, "none", "string", "hex", NULL);
|
||||
|
||||
|
||||
/* scr */
|
||||
#if __EMSCRIPTEN__
|
||||
rz_config_set_cb (cfg, "scr.fgets", "true", cb_scrfgets);
|
||||
|
|
|
|||
|
|
@ -4487,11 +4487,11 @@ static void rz_core_disasm_table(RzCore * core, int l, const char *input) {
|
|||
|
||||
static void cmd_pxr(RzCore *core, int len, int mode, int wordsize, const char *arg) {
|
||||
PJ *pj = NULL;
|
||||
RzTable *t = NULL;
|
||||
RTable *t = NULL;
|
||||
if (mode == ',') {
|
||||
t = rz_table_new ();
|
||||
RzTableColumnType *n = rz_table_type ("number");
|
||||
RzTableColumnType *s = rz_table_type ("string");
|
||||
RTableColumnType *n = rz_table_type ("number");
|
||||
RTableColumnType *s = rz_table_type ("string");
|
||||
rz_table_add_column (t, n, "addr", 0);
|
||||
rz_table_add_column (t, n, "value", 0);
|
||||
rz_table_add_column (t, s, "refs", 0);
|
||||
|
|
|
|||
|
|
@ -327,6 +327,7 @@ RZ_API int rz_core_bind(RzCore *core, RzCoreBind *bnd) {
|
|||
bnd->numGet = (RzCoreNumGet)numget;
|
||||
bnd->isMapped = (RzCoreIsMapped)__isMapped;
|
||||
bnd->syncDebugMaps = (RzCoreDebugMapsSync)__syncDebugMaps;
|
||||
bnd->pjWithEncoding = (RzCorePJWithEncoding)rz_core_pj_new;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3460,3 +3461,29 @@ RZ_API RTable *rz_core_table(RzCore *core) {
|
|||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/* Config helper function for PJ json encodings */
|
||||
RZ_API PJ *rz_core_pj_new(RzCore *core) {
|
||||
const char *config_string_encoding = rz_config_get (core->config, "cfg.json.str");
|
||||
const char *config_num_encoding = rz_config_get (core->config, "cfg.json.num");
|
||||
PJEncodingNum number_encoding = PJ_ENCODING_NUM_DEFAULT;
|
||||
PJEncodingStr string_encoding = PJ_ENCODING_STR_DEFAULT;
|
||||
|
||||
if (!strcmp ("string", config_num_encoding)) {
|
||||
number_encoding = PJ_ENCODING_NUM_STR;
|
||||
} else if (!strcmp ("hex", config_num_encoding)) {
|
||||
number_encoding = PJ_ENCODING_NUM_HEX;
|
||||
}
|
||||
|
||||
if (!strcmp ("base64", config_string_encoding)) {
|
||||
string_encoding = PJ_ENCODING_STR_BASE64;
|
||||
} else if (!strcmp ("hex", config_string_encoding)) {
|
||||
string_encoding = PJ_ENCODING_STR_HEX;
|
||||
} else if (!strcmp ("array", config_string_encoding)) {
|
||||
string_encoding = PJ_ENCODING_STR_ARRAY;
|
||||
} else if (!strcmp ("strip", config_string_encoding)) {
|
||||
string_encoding = PJ_ENCODING_STR_STRIP;
|
||||
}
|
||||
|
||||
return pj_new_with_encoding (string_encoding, number_encoding);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5159,7 +5159,7 @@ RZ_API int rz_core_print_disasm(RPrint *p, RzCore *core, ut64 addr, ut8 *buf, in
|
|||
ds->pdf = pdf;
|
||||
|
||||
if (json) {
|
||||
ds->pj = pj ? pj : pj_new ();
|
||||
ds->pj = pj ? pj : rz_core_pj_new (core);
|
||||
if (!ds->pj) {
|
||||
ds_free (ds);
|
||||
return 0;
|
||||
|
|
@ -6605,7 +6605,7 @@ RZ_API int rz_core_disasm_pde(RzCore *core, int nb_opcodes, int mode) {
|
|||
}
|
||||
PJ *pj = NULL;
|
||||
if (mode == RZ_MODE_JSON) {
|
||||
pj = pj_new ();
|
||||
pj = rz_core_pj_new (core);
|
||||
if (!pj) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,11 @@ typedef bool (*RzCoreIsMapped)(void *core, ut64 addr, int perm);
|
|||
typedef bool (*RzCoreDebugMapsSync)(void *core);
|
||||
typedef const char *(*RzCoreGetName)(void *core, ut64 off);
|
||||
typedef char *(*RzCoreGetNameDelta)(void *core, ut64 off);
|
||||
typedef void (*RzCoreSeekArchBits)(void *core, ut64 addr);
|
||||
typedef void (*RzCoreSeekArchBits)(void *core, ut64 addr);
|
||||
typedef int (*RzCoreConfigGetI)(void *core, const char *key);
|
||||
typedef const char *(*RzCoreConfigGet)(void *core, const char *key);
|
||||
typedef ut64 (*RzCoreNumGet)(void *core, const char *str);
|
||||
typedef void *(*RzCorePJWithEncoding)(void *core);
|
||||
|
||||
typedef struct rz_core_bind_t {
|
||||
void *core;
|
||||
|
|
@ -41,6 +42,7 @@ typedef struct rz_core_bind_t {
|
|||
RzCoreNumGet numGet;
|
||||
RzCoreIsMapped isMapped;
|
||||
RzCoreDebugMapsSync syncDebugMaps;
|
||||
RzCorePJWithEncoding pjWithEncoding;
|
||||
} RzCoreBind;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -765,6 +765,7 @@ RZ_API int rz_core_cmpwatch_revert (RzCore *core, ut64 addr);
|
|||
// TODO MOVE SOMEWHERE ELSE
|
||||
typedef char *(*PrintItemCallback)(void *user, void *p, bool selected);
|
||||
RZ_API char *rz_str_widget_list(void *user, RzList *list, int rows, int cur, PrintItemCallback cb);
|
||||
RZ_API PJ *rz_core_pj_new(RzCore *core);
|
||||
/* help */
|
||||
RZ_API void rz_core_cmd_help(const RzCore *core, const char * help[]);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,16 +8,34 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* new encoding options of j commands */
|
||||
typedef enum PJEncodingStr {
|
||||
PJ_ENCODING_STR_DEFAULT = 0,
|
||||
PJ_ENCODING_STR_BASE64,
|
||||
PJ_ENCODING_STR_HEX,
|
||||
PJ_ENCODING_STR_ARRAY,
|
||||
PJ_ENCODING_STR_STRIP
|
||||
} PJEncodingStr;
|
||||
|
||||
typedef enum PJEncodingNum {
|
||||
PJ_ENCODING_NUM_DEFAULT = 0,
|
||||
PJ_ENCODING_NUM_STR,
|
||||
PJ_ENCODING_NUM_HEX
|
||||
} PJEncodingNum;
|
||||
|
||||
typedef struct pj_t {
|
||||
RzStrBuf sb;
|
||||
bool is_first;
|
||||
bool is_key;
|
||||
char braces[RZ_PRINT_JSON_DEPTH_LIMIT];
|
||||
int level;
|
||||
PJEncodingStr str_encoding;
|
||||
PJEncodingNum num_encoding;
|
||||
} PJ;
|
||||
|
||||
/* lifecycle */
|
||||
RZ_API PJ *pj_new(void);
|
||||
RZ_API PJ *pj_new_with_encoding(PJEncodingStr str_encoding, PJEncodingNum num_encoding);
|
||||
RZ_API void pj_free(PJ *j);
|
||||
RZ_API void pj_reset(PJ *j); // clear the pj contents, but keep the buffer allocated to re-use it
|
||||
RZ_API char *pj_drain(PJ *j);
|
||||
|
|
@ -48,7 +66,9 @@ RZ_API PJ *pj_r(PJ *j, const unsigned char *v, size_t v_len);
|
|||
RZ_API PJ *pj_kr(PJ *j, const char *k, const unsigned char *v, size_t v_len);
|
||||
RZ_API PJ *pj_b(PJ *j, bool v);
|
||||
RZ_API PJ *pj_s(PJ *j, const char *k);
|
||||
RZ_API PJ *pj_se(PJ *j, const char *k);
|
||||
RZ_API PJ *pj_n(PJ *j, ut64 n);
|
||||
RZ_API PJ *pj_ne(PJ *j, ut64 n);
|
||||
RZ_API PJ *pj_N(PJ *j, st64 n);
|
||||
RZ_API PJ *pj_d(PJ *j, double d);
|
||||
RZ_API PJ *pj_f(PJ *j, float d);
|
||||
|
|
|
|||
|
|
@ -166,6 +166,8 @@ RZ_API char *rz_str_utf16_decode(const ut8 *s, int len);
|
|||
RZ_API int rz_str_utf16_to_utf8(ut8 *dst, int len_dst, const ut8 *src, int len_src, int little_endian);
|
||||
RZ_API char *rz_str_utf16_encode(const char *s, int len);
|
||||
RZ_API char *rz_str_escape_utf8_for_json(const char *s, int len);
|
||||
RZ_API char *rz_str_escape_utf8_for_json_strip(const char *buf, int buf_size);
|
||||
RZ_API char *rz_str_encoded_json(const char *buf, int buf_size, int encoding);
|
||||
RZ_API char *rz_str_home(const char *str);
|
||||
RZ_API char *rz_str_rz_prefix(const char *str);
|
||||
RZ_API size_t rz_str_nlen(const char *s, int n);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,17 @@ RZ_API PJ *pj_new(void) {
|
|||
if (j) {
|
||||
rz_strbuf_init (&j->sb);
|
||||
j->is_first = true;
|
||||
j->str_encoding = PJ_ENCODING_STR_DEFAULT;
|
||||
j->num_encoding = PJ_ENCODING_NUM_DEFAULT;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
RZ_API PJ *pj_new_with_encoding(PJEncodingStr str_encoding, PJEncodingNum num_encoding) {
|
||||
PJ *j = pj_new ();
|
||||
if (j) {
|
||||
j->str_encoding = str_encoding;
|
||||
j->num_encoding = num_encoding;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
|
@ -119,7 +130,11 @@ RZ_API PJ *pj_knull(PJ *j, const char *k) {
|
|||
RZ_API PJ *pj_kn(PJ *j, const char *k, ut64 n) {
|
||||
rz_return_val_if_fail (j && k, j);
|
||||
pj_k (j, k);
|
||||
pj_n (j, n);
|
||||
if (j->num_encoding != PJ_ENCODING_NUM_DEFAULT) {
|
||||
pj_ne (j, n);
|
||||
} else {
|
||||
pj_n (j, n);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +183,11 @@ RZ_API PJ *pj_ka(PJ *j, const char *k) {
|
|||
RZ_API PJ *pj_ks(PJ *j, const char *k, const char *v) {
|
||||
rz_return_val_if_fail (j && k && v, j);
|
||||
pj_k (j, k);
|
||||
pj_s (j, v);
|
||||
if (j->str_encoding != PJ_ENCODING_STR_DEFAULT) {
|
||||
pj_se (j, v);
|
||||
} else {
|
||||
pj_s (j, v);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
|
|
@ -207,6 +226,27 @@ RZ_API PJ *pj_s(PJ *j, const char *k) {
|
|||
return j;
|
||||
}
|
||||
|
||||
RZ_API PJ *pj_se(PJ *j, const char *k) {
|
||||
rz_return_val_if_fail (j && k, j);
|
||||
pj_comma (j);
|
||||
if (j->str_encoding == PJ_ENCODING_STR_ARRAY) {
|
||||
pj_raw (j, "[");
|
||||
} else {
|
||||
pj_raw (j, "\"");
|
||||
}
|
||||
char *en = rz_str_encoded_json (k, -1, j->str_encoding);
|
||||
if (en) {
|
||||
pj_raw (j, en);
|
||||
free (en);
|
||||
}
|
||||
if (j->str_encoding == PJ_ENCODING_STR_ARRAY) {
|
||||
pj_raw (j, "]");
|
||||
} else {
|
||||
pj_raw (j, "\"");
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
RZ_API PJ *pj_r(PJ *j, const unsigned char *v, size_t v_len) {
|
||||
rz_return_val_if_fail (j && v, j);
|
||||
size_t i;
|
||||
|
|
@ -241,6 +281,19 @@ RZ_API PJ *pj_n(PJ *j, ut64 n) {
|
|||
return j;
|
||||
}
|
||||
|
||||
RZ_API PJ *pj_ne(PJ *j, ut64 n) {
|
||||
rz_return_val_if_fail (j, j);
|
||||
pj_comma (j);
|
||||
if (j->num_encoding == PJ_ENCODING_NUM_STR) {
|
||||
pj_raw (j, sdb_fmt ("\"%" PFMT64u "\"", n));
|
||||
} else if (j->num_encoding == PJ_ENCODING_NUM_HEX) {
|
||||
pj_raw (j, sdb_fmt ("\"0x%" PFMT64x "\"", n));
|
||||
} else {
|
||||
pj_n(j, n);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
RZ_API PJ *pj_N(PJ *j, st64 n) {
|
||||
rz_return_val_if_fail (j, NULL);
|
||||
pj_comma (j);
|
||||
|
|
|
|||
153
librz/util/str.c
153
librz/util/str.c
|
|
@ -9,6 +9,7 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <rz_util/rz_base64.h>
|
||||
|
||||
/* stable code */
|
||||
static const char *nullstr = "";
|
||||
|
|
@ -1508,8 +1509,150 @@ RZ_API char *rz_str_escape_utf32be(const char *buf, int buf_size, bool show_asci
|
|||
return rz_str_escape_utf (buf, buf_size, RZ_STRING_ENC_UTF32BE, show_asciidot, esc_bslash, false);
|
||||
}
|
||||
|
||||
// JSON has special escaping requirements
|
||||
// TODO: merge with rz_str_escape_utf() and rz_str_byte_escape() using RStrEsc
|
||||
RZ_API char *rz_str_encoded_json(const char *buf, int buf_size, int encoding) {
|
||||
rz_return_val_if_fail (buf, NULL);
|
||||
size_t buf_sz = buf_size < 0 ? strlen (buf) : buf_size;
|
||||
char *encoded_str;
|
||||
|
||||
if (encoding == PJ_ENCODING_STR_BASE64) {
|
||||
encoded_str = rz_base64_encode_dyn (buf, buf_sz);
|
||||
} else if (encoding == PJ_ENCODING_STR_HEX || encoding == PJ_ENCODING_STR_ARRAY) {
|
||||
size_t loop = 0;
|
||||
size_t i = 0;
|
||||
size_t increment = encoding == PJ_ENCODING_STR_ARRAY ? 4 : 2;
|
||||
|
||||
if (!SZT_MUL_OVFCHK (((buf_sz * increment) + 1), SZT_MAX)) {
|
||||
return NULL;
|
||||
}
|
||||
size_t new_sz = (buf_sz * increment) + 1;
|
||||
|
||||
encoded_str = malloc (new_sz);
|
||||
if (!encoded_str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *format = encoding == PJ_ENCODING_STR_ARRAY ? "%03u," : "%02X";
|
||||
while (buf[loop] != '\0' && i < (new_sz - 1)) {
|
||||
snprintf (encoded_str + i, sizeof (encoded_str), format, (ut8) buf[loop]);
|
||||
loop++;
|
||||
i += increment;
|
||||
}
|
||||
if (encoding == PJ_ENCODING_STR_ARRAY && i) {
|
||||
// get rid of the trailing comma
|
||||
encoded_str[i - 1] = '\0';
|
||||
} else {
|
||||
encoded_str[i] = '\0';
|
||||
}
|
||||
} else if (encoding == PJ_ENCODING_STR_STRIP) {
|
||||
encoded_str = rz_str_escape_utf8_for_json_strip (buf, buf_sz);
|
||||
} else {
|
||||
encoded_str = rz_str_escape_utf8_for_json (buf, buf_sz);
|
||||
}
|
||||
return encoded_str;
|
||||
}
|
||||
|
||||
RZ_API char *rz_str_escape_utf8_for_json_strip(const char *buf, int buf_size) {
|
||||
char *new_buf, *q;
|
||||
const char *p, *end;
|
||||
RRune ch;
|
||||
int i, len, ch_bytes;
|
||||
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
len = buf_size < 0 ? strlen (buf) : buf_size;
|
||||
end = buf + len;
|
||||
/* Worst case scenario, we convert every byte to \u00hh */
|
||||
new_buf = malloc (1 + (len * 6));
|
||||
if (!new_buf) {
|
||||
return NULL;
|
||||
}
|
||||
p = buf;
|
||||
q = new_buf;
|
||||
while (p < end) {
|
||||
ch_bytes = rz_utf8_decode ((ut8 *)p, end - p, &ch);
|
||||
if (ch_bytes == 1) {
|
||||
switch (*p) {
|
||||
case '\n':
|
||||
*q++ = '\\';
|
||||
*q++ = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
*q++ = '\\';
|
||||
*q++ = 'r';
|
||||
break;
|
||||
case '\\':
|
||||
*q++ = '\\';
|
||||
*q++ = '\\';
|
||||
break;
|
||||
case '\t':
|
||||
*q++ = '\\';
|
||||
*q++ = 't';
|
||||
break;
|
||||
case '"' :
|
||||
*q++ = '\\';
|
||||
*q++ = '"';
|
||||
break;
|
||||
case '\f':
|
||||
*q++ = '\\';
|
||||
*q++ = 'f';
|
||||
break;
|
||||
case '\b':
|
||||
*q++ = '\\';
|
||||
*q++ = 'b';
|
||||
break;
|
||||
default:
|
||||
if (IS_PRINTABLE (*p)) {
|
||||
*q++ = *p;
|
||||
}
|
||||
}
|
||||
} else if (ch_bytes == 4) {
|
||||
if (rz_isprint (ch)) {
|
||||
// Assumes buf is UTF8-encoded
|
||||
for (i = 0; i < ch_bytes; i++) {
|
||||
*q++ = *(p + i);
|
||||
}
|
||||
} else {
|
||||
RRune high, low;
|
||||
ch -= 0x10000;
|
||||
high = 0xd800 + (ch >> 10 & 0x3ff);
|
||||
low = 0xdc00 + (ch & 0x3ff);
|
||||
*q++ = '\\';
|
||||
*q++ = 'u';
|
||||
for (i = 2; i >= 0; i -= 2) {
|
||||
*q++ = "0123456789abcdef"[high >> 4 * (i + 1) & 0xf];
|
||||
*q++ = "0123456789abcdef"[high >> 4 * i & 0xf];
|
||||
}
|
||||
*q++ = '\\';
|
||||
*q++ = 'u';
|
||||
for (i = 2; i >= 0; i -= 2) {
|
||||
*q++ = "0123456789abcdef"[low >> 4 * (i + 1) & 0xf];
|
||||
*q++ = "0123456789abcdef"[low >> 4 * i & 0xf];
|
||||
}
|
||||
}
|
||||
} else if (ch_bytes > 1) {
|
||||
if (rz_isprint (ch)) {
|
||||
// Assumes buf is UTF8-encoded
|
||||
for (i = 0; i < ch_bytes; i++) {
|
||||
*q++ = *(p + i);
|
||||
}
|
||||
} else {
|
||||
*q++ = '\\';
|
||||
*q++ = 'u';
|
||||
for (i = 2; i >= 0; i -= 2) {
|
||||
*q++ = "0123456789abcdef"[ch >> 4 * (i + 1) & 0xf];
|
||||
*q++ = "0123456789abcdef"[ch >> 4 * i & 0xf];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ch_bytes = 1;
|
||||
}
|
||||
p += ch_bytes;
|
||||
}
|
||||
*q = '\0';
|
||||
return new_buf;
|
||||
}
|
||||
|
||||
RZ_API char *rz_str_escape_utf8_for_json(const char *buf, int buf_size) {
|
||||
char *new_buf, *q;
|
||||
const char *p, *end;
|
||||
|
|
@ -1544,12 +1687,6 @@ RZ_API char *rz_str_escape_utf8_for_json(const char *buf, int buf_size) {
|
|||
*q++ = '\\';
|
||||
*q++ = '\\';
|
||||
break;
|
||||
#if 0
|
||||
case '/': /* has 2-char esc seq in JSON spec, but escaping is optional */
|
||||
*q++ = '\\';
|
||||
*q++ = '/';
|
||||
break;
|
||||
#endif
|
||||
case '\t':
|
||||
*q++ = '\\';
|
||||
*q++ = 't';
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ rm -f $D.zip
|
|||
zip -r $D.zip $D > /dev/null
|
||||
|
||||
cat > .test.c <<EOF
|
||||
#include <r_core.h>
|
||||
#include <rz_core.h>
|
||||
int main() {
|
||||
RCore *core = r_core_new ();
|
||||
r_core_free (core);
|
||||
RzCore *core = rz_core_new ();
|
||||
rz_core_free (core);
|
||||
}
|
||||
EOF
|
||||
gcc .test.c -I $D/include $D/lib/librz.a
|
||||
|
|
|
|||
|
|
@ -69,18 +69,18 @@ for a in ${BINS} ; do
|
|||
)
|
||||
done
|
||||
|
||||
rm -rf r2-static
|
||||
mkdir r2-static || exit 1
|
||||
${MAKE} install DESTDIR="${PWD}/r2-static" || exit 1
|
||||
rm -rf rizin-static
|
||||
mkdir rizin-static || exit 1
|
||||
${MAKE} install DESTDIR="${PWD}/rizin-static" || exit 1
|
||||
|
||||
echo "Using PREFIX ${PREFIX}"
|
||||
|
||||
# testing installation
|
||||
cat > .test.c <<EOF
|
||||
#include <r_core.h>
|
||||
#include <rz_core.h>
|
||||
int main() {
|
||||
RCore *core = r_core_new ();
|
||||
r_core_free (core);
|
||||
RzCore *core = rz_core_new ();
|
||||
rz_core_free (core);
|
||||
}
|
||||
EOF
|
||||
cat .test.c
|
||||
|
|
@ -91,15 +91,15 @@ fi
|
|||
# static pkg-config linking test
|
||||
echo "[*] Static building with pkg-config..."
|
||||
PKG_CONFIG_FLAGS=`
|
||||
PKG_CONFIG_PATH="${PWD}/r2-static/usr/lib/pkgconfig" \
|
||||
PKG_CONFIG_PATH="${PWD}/rizin-static/usr/lib/pkgconfig" \
|
||||
pkg-config \
|
||||
--define-variable="libdir=${PWD}/r2-static/usr/lib" \
|
||||
--define-variable="prefix=${PWD}/r2-static/usr" \
|
||||
--static --cflags --libs r_core
|
||||
--define-variable="libdir=${PWD}/rizin-static/usr/lib" \
|
||||
--define-variable="prefix=${PWD}/rizin-static/usr" \
|
||||
--static --cflags --libs rz_core
|
||||
`
|
||||
|
||||
set -x
|
||||
${CC} .test.c ${PKG_CONFIG_FLAGS} -o r2-pkgcfg-static
|
||||
${CC} .test.c ${PKG_CONFIG_FLAGS} -o rizin-pkgcfg-static
|
||||
res=$?
|
||||
set +x
|
||||
if [ $res = 0 ]; then
|
||||
|
|
@ -113,9 +113,9 @@ echo "[*] Static building with librz.a..."
|
|||
set -x
|
||||
${CC} .test.c \
|
||||
${CFLAGS} \
|
||||
-I ${PWD}/r2-static/usr/include/librz \
|
||||
-I ${PWD}/r2-static/usr/include/librz/sdb \
|
||||
r2-static/usr/lib/librz.a ${LDFLAGS}
|
||||
-I ${PWD}/rizin-static/usr/include/librz \
|
||||
-I ${PWD}/rizin-static/usr/include/librz/sdb \
|
||||
rizin-static/usr/lib/librz.a ${LDFLAGS}
|
||||
res=$?
|
||||
set +x
|
||||
if [ $res = 0 ]; then
|
||||
|
|
|
|||
|
|
@ -38,3 +38,29 @@ EXPECT=<<EOF
|
|||
C 0x44 add byte [rax], al
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=axjstrencoding
|
||||
FILE=bins/elf/analysis/hello-utf-16
|
||||
CMDS=<<EOF
|
||||
aa
|
||||
e cfg.json.str = base64
|
||||
s sym.imp.wprintf
|
||||
axj~{[1].name}
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
c2VjdGlvbi4uaW5pdCsxNg==
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=axjnumencoding
|
||||
FILE=bins/elf/analysis/hello-utf-16
|
||||
CMDS=<<EOF
|
||||
aa
|
||||
e cfg.json.num = hex
|
||||
s sym.imp.wprintf
|
||||
axj~{[0].addr}
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0x600ff8
|
||||
EOF
|
||||
RUN
|
||||
|
|
@ -4518,3 +4518,38 @@ EXPECT=<<EOF
|
|||
0
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=izjencoding
|
||||
FILE=bins/elf/analysis/hello-utf-16
|
||||
CMDS=<<EOF
|
||||
e cfg.json.str = base64
|
||||
izj~{[0].section}
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
LnJvZGF0YQ==
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
||||
NAME=izjencodinghex
|
||||
FILE=bins/elf/analysis/hello-utf-16
|
||||
CMDS=<<EOF
|
||||
e cfg.json.str = hex
|
||||
izj~{[0].string}
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
48656C6C6F20576F726C64
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
||||
NAME=izjencodingarray
|
||||
FILE=bins/elf/analysis/hello-utf-16
|
||||
CMDS=<<EOF
|
||||
e cfg.json.str = array
|
||||
izj~{[0].type}
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
[117,116,102,049,054,108,101]
|
||||
EOF
|
||||
RUN
|
||||
|
|
@ -551,6 +551,23 @@ static bool test_rz_str_wrap(void) {
|
|||
mu_end;
|
||||
}
|
||||
|
||||
bool test_rz_str_encoded_json(void) {
|
||||
char *invalidJsonString = "This is my \xe2 sample © string\n";
|
||||
size_t len = strlen (invalidJsonString);
|
||||
|
||||
const char *array = rz_str_encoded_json (invalidJsonString, len, PJ_ENCODING_STR_ARRAY);
|
||||
mu_assert_streq (array, "084,104,105,115,032,105,115,032,109,121,032,226,032,115,097,109,112,108,101,032,194,169,032,115,116,114,105,110,103,010", "string as array of uchar");
|
||||
const char *hex = rz_str_encoded_json (invalidJsonString, len, PJ_ENCODING_STR_HEX);
|
||||
mu_assert_streq (hex, "54686973206973206D7920E22073616D706C6520C2A920737472696E670A", "string as hexpairs");
|
||||
const char *b64 = rz_str_encoded_json (invalidJsonString, len, PJ_ENCODING_STR_BASE64);
|
||||
mu_assert_streq (b64, "VGhpcyBpcyBteSDiIHNhbXBsZSDCqSBzdHJpbmcK", "string as base64 encoded");
|
||||
const char *stripped = rz_str_encoded_json (invalidJsonString, len, PJ_ENCODING_STR_STRIP);
|
||||
mu_assert_streq (stripped, "This is my sample © string\\n", "string with bad chars stripped");
|
||||
const char *none = rz_str_encoded_json (invalidJsonString, len, PJ_ENCODING_STR_DEFAULT);
|
||||
mu_assert_streq (none, "This is my \\xe2 sample © string\\n", "default encoding");
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool all_tests () {
|
||||
mu_run_test (test_rz_str_newf);
|
||||
mu_run_test (test_rz_str_replace_char_once);
|
||||
|
|
@ -582,6 +599,7 @@ bool all_tests () {
|
|||
mu_run_test (test_rz_str_format_msvc_argv);
|
||||
mu_run_test (test_rz_str_str_xy);
|
||||
mu_run_test (test_rz_str_wrap);
|
||||
mu_run_test (test_rz_str_encoded_json);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue