Add cfg.json.* encoding options (#17681) ##json

This commit is contained in:
Hex 2020-10-27 10:46:27 +00:00 committed by Florian Märkl
parent 7c86add0dc
commit afb8b7bd1f
21 changed files with 419 additions and 53 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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

View file

@ -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[]);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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';

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}