From d93d3f377063c8cc935a5e76deb1380e4d3a429d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Sat, 6 Feb 2021 12:10:43 +0100 Subject: [PATCH] Move Serialization Helpers to Global API (#522) --- librz/analysis/serialize_analysis.c | 188 +++++++++++++-------------- librz/core/project.c | 6 +- librz/core/serialize_core.c | 12 +- librz/flag/serialize_flag.c | 42 +++--- librz/include/rz_util/rz_serialize.h | 99 +++++++++++++- librz/io/serialize_io.c | 4 +- librz/util/serialize_helper.h | 56 -------- librz/util/serialize_spaces.c | 14 +- 8 files changed, 225 insertions(+), 196 deletions(-) delete mode 100644 librz/util/serialize_helper.h diff --git a/librz/analysis/serialize_analysis.c b/librz/analysis/serialize_analysis.c index 3f8ccf21e8..897316d465 100644 --- a/librz/analysis/serialize_analysis.c +++ b/librz/analysis/serialize_analysis.c @@ -3,8 +3,6 @@ #include #include -#include "../util/serialize_helper.h" - #include /* @@ -96,20 +94,20 @@ enum { }; RZ_API RzSerializeAnalDiffParser rz_serialize_analysis_diff_parser_new(void) { - RzSerializeAnalDiffParser parser = key_parser_new(); + RzSerializeAnalDiffParser parser = rz_key_parser_new(); if (!parser) { return NULL; } - key_parser_add(parser, "type", DIFF_FIELD_TYPE); - key_parser_add(parser, "addr", DIFF_FIELD_ADDR); - key_parser_add(parser, "dist", DIFF_FIELD_DIST); - key_parser_add(parser, "name", DIFF_FIELD_NAME); - key_parser_add(parser, "size", DIFF_FIELD_SIZE); + rz_key_parser_add(parser, "type", DIFF_FIELD_TYPE); + rz_key_parser_add(parser, "addr", DIFF_FIELD_ADDR); + rz_key_parser_add(parser, "dist", DIFF_FIELD_DIST); + rz_key_parser_add(parser, "name", DIFF_FIELD_NAME); + rz_key_parser_add(parser, "size", DIFF_FIELD_SIZE); return parser; } RZ_API void rz_serialize_analysis_diff_parser_free(RzSerializeAnalDiffParser parser) { - key_parser_free(parser); + rz_key_parser_free(parser); } RZ_API RZ_NULLABLE RzAnalysisDiff *rz_serialize_analysis_diff_load(RZ_NONNULL RzSerializeAnalDiffParser parser, RZ_NONNULL const RJson *json) { @@ -120,7 +118,7 @@ RZ_API RZ_NULLABLE RzAnalysisDiff *rz_serialize_analysis_diff_load(RZ_NONNULL Rz if (!diff) { return NULL; } - KEY_PARSER_JSON(parser, json, child, { + RZ_KEY_PARSER_JSON(parser, json, child, { case DIFF_FIELD_TYPE: if (child->type != RZ_JSON_STRING) { break; @@ -340,7 +338,7 @@ enum { typedef struct { RzAnalysis *analysis; - KeyParser *parser; + RzKeyParser *parser; RzSerializeAnalDiffParser diff_parser; } BlockLoadCtx; @@ -364,7 +362,7 @@ static bool block_load_cb(void *user, const char *k, const char *v) { proto.parent_stackptr = INT_MAX; proto.cmpval = UT64_MAX; size_t fingerprint_size = SIZE_MAX; - KEY_PARSER_JSON(ctx->parser, json, child, { + RZ_KEY_PARSER_JSON(ctx->parser, json, child, { case BLOCK_FIELD_SIZE: if (child->type != RZ_JSON_INTEGER) { break; @@ -529,29 +527,29 @@ error: } RZ_API bool rz_serialize_analysis_blocks_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RzSerializeAnalDiffParser diff_parser, RZ_NULLABLE RzSerializeResultInfo *res) { - BlockLoadCtx ctx = { analysis, key_parser_new(), diff_parser }; + BlockLoadCtx ctx = { analysis, rz_key_parser_new(), diff_parser }; if (!ctx.parser) { - SERIALIZE_ERR("parser init failed"); + RZ_SERIALIZE_ERR(res, "parser init failed"); return false; } - key_parser_add(ctx.parser, "size", BLOCK_FIELD_SIZE); - key_parser_add(ctx.parser, "jump", BLOCK_FIELD_JUMP); - key_parser_add(ctx.parser, "fail", BLOCK_FIELD_FAIL); - key_parser_add(ctx.parser, "traced", BLOCK_FIELD_TRACED); - key_parser_add(ctx.parser, "colorize", BLOCK_FIELD_COLORIZE); - key_parser_add(ctx.parser, "fingerprint", BLOCK_FIELD_FINGERPRINT); - key_parser_add(ctx.parser, "diff", BLOCK_FIELD_DIFF); - key_parser_add(ctx.parser, "switch_op", BLOCK_FIELD_SWITCH_OP); - key_parser_add(ctx.parser, "ninstr", BLOCK_FIELD_NINSTR); - key_parser_add(ctx.parser, "op_pos", BLOCK_FIELD_OP_POS); - key_parser_add(ctx.parser, "stackptr", BLOCK_FIELD_STACKPTR); - key_parser_add(ctx.parser, "parent_stackptr", BLOCK_FIELD_PARENT_STACKPTR); - key_parser_add(ctx.parser, "cmpval", BLOCK_FIELD_CMPVAL); - key_parser_add(ctx.parser, "cmpreg", BLOCK_FIELD_CMPREG); + rz_key_parser_add(ctx.parser, "size", BLOCK_FIELD_SIZE); + rz_key_parser_add(ctx.parser, "jump", BLOCK_FIELD_JUMP); + rz_key_parser_add(ctx.parser, "fail", BLOCK_FIELD_FAIL); + rz_key_parser_add(ctx.parser, "traced", BLOCK_FIELD_TRACED); + rz_key_parser_add(ctx.parser, "colorize", BLOCK_FIELD_COLORIZE); + rz_key_parser_add(ctx.parser, "fingerprint", BLOCK_FIELD_FINGERPRINT); + rz_key_parser_add(ctx.parser, "diff", BLOCK_FIELD_DIFF); + rz_key_parser_add(ctx.parser, "switch_op", BLOCK_FIELD_SWITCH_OP); + rz_key_parser_add(ctx.parser, "ninstr", BLOCK_FIELD_NINSTR); + rz_key_parser_add(ctx.parser, "op_pos", BLOCK_FIELD_OP_POS); + rz_key_parser_add(ctx.parser, "stackptr", BLOCK_FIELD_STACKPTR); + rz_key_parser_add(ctx.parser, "parent_stackptr", BLOCK_FIELD_PARENT_STACKPTR); + rz_key_parser_add(ctx.parser, "cmpval", BLOCK_FIELD_CMPVAL); + rz_key_parser_add(ctx.parser, "cmpreg", BLOCK_FIELD_CMPREG); bool ret = sdb_foreach(db, block_load_cb, &ctx); - key_parser_free(ctx.parser); + rz_key_parser_free(ctx.parser); if (!ret) { - SERIALIZE_ERR("basic blocks parsing failed"); + RZ_SERIALIZE_ERR(res, "basic blocks parsing failed"); } return ret; } @@ -637,24 +635,24 @@ enum { }; RZ_API RzSerializeAnalVarParser rz_serialize_analysis_var_parser_new(void) { - RzSerializeAnalDiffParser parser = key_parser_new(); + RzSerializeAnalDiffParser parser = rz_key_parser_new(); if (!parser) { return NULL; } - key_parser_add(parser, "name", VAR_FIELD_NAME); - key_parser_add(parser, "type", VAR_FIELD_TYPE); - key_parser_add(parser, "kind", VAR_FIELD_KIND); - key_parser_add(parser, "arg", VAR_FIELD_ARG); - key_parser_add(parser, "delta", VAR_FIELD_DELTA); - key_parser_add(parser, "reg", VAR_FIELD_REG); - key_parser_add(parser, "cmt", VAR_FIELD_COMMENT); - key_parser_add(parser, "accs", VAR_FIELD_ACCS); - key_parser_add(parser, "constrs", VAR_FIELD_CONSTRS); + rz_key_parser_add(parser, "name", VAR_FIELD_NAME); + rz_key_parser_add(parser, "type", VAR_FIELD_TYPE); + rz_key_parser_add(parser, "kind", VAR_FIELD_KIND); + rz_key_parser_add(parser, "arg", VAR_FIELD_ARG); + rz_key_parser_add(parser, "delta", VAR_FIELD_DELTA); + rz_key_parser_add(parser, "reg", VAR_FIELD_REG); + rz_key_parser_add(parser, "cmt", VAR_FIELD_COMMENT); + rz_key_parser_add(parser, "accs", VAR_FIELD_ACCS); + rz_key_parser_add(parser, "constrs", VAR_FIELD_CONSTRS); return parser; } RZ_API void rz_serialize_analysis_var_parser_free(RzSerializeAnalVarParser parser) { - key_parser_free(parser); + rz_key_parser_free(parser); } RZ_API RZ_NULLABLE RzAnalysisVar *rz_serialize_analysis_var_load(RZ_NONNULL RzAnalysisFunction *fcn, RZ_NONNULL RzSerializeAnalVarParser parser, RZ_NONNULL const RJson *json) { @@ -675,7 +673,7 @@ RZ_API RZ_NULLABLE RzAnalysisVar *rz_serialize_analysis_var_load(RZ_NONNULL RzAn RzAnalysisVar *ret = NULL; - KEY_PARSER_JSON(parser, json, child, { + RZ_KEY_PARSER_JSON(parser, json, child, { case VAR_FIELD_NAME: if (child->type != RZ_JSON_STRING) { break; @@ -968,7 +966,7 @@ enum { typedef struct { RzAnalysis *analysis; - KeyParser *parser; + RzKeyParser *parser; RzSerializeAnalDiffParser diff_parser; RzSerializeAnalVarParser var_parser; } FunctionLoadCtx; @@ -992,7 +990,7 @@ static bool function_load_cb(void *user, const char *k, const char *v) { function->bp_off = 0; // 0 if not specified bool noreturn = false; RJson *vars_json = NULL; - KEY_PARSER_JSON(ctx->parser, json, child, { + RZ_KEY_PARSER_JSON(ctx->parser, json, child, { case FUNCTION_FIELD_NAME: if (child->type != RZ_JSON_STRING) { break; @@ -1190,39 +1188,39 @@ beach: RZ_API bool rz_serialize_analysis_functions_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RzSerializeAnalDiffParser diff_parser, RZ_NULLABLE RzSerializeResultInfo *res) { FunctionLoadCtx ctx = { .analysis = analysis, - .parser = key_parser_new(), + .parser = rz_key_parser_new(), .diff_parser = diff_parser, .var_parser = rz_serialize_analysis_var_parser_new() }; bool ret; if (!ctx.parser || !ctx.var_parser) { - SERIALIZE_ERR("parser init failed"); + RZ_SERIALIZE_ERR(res, "parser init failed"); ret = false; goto beach; } - key_parser_add(ctx.parser, "name", FUNCTION_FIELD_NAME); - key_parser_add(ctx.parser, "bits", FUNCTION_FIELD_BITS); - key_parser_add(ctx.parser, "type", FUNCTION_FIELD_TYPE); - key_parser_add(ctx.parser, "cc", FUNCTION_FIELD_CC); - key_parser_add(ctx.parser, "stack", FUNCTION_FIELD_STACK); - key_parser_add(ctx.parser, "maxstack", FUNCTION_FIELD_MAXSTACK); - key_parser_add(ctx.parser, "ninstr", FUNCTION_FIELD_NINSTR); - key_parser_add(ctx.parser, "pure", FUNCTION_FIELD_PURE); - key_parser_add(ctx.parser, "bp_frame", FUNCTION_FIELD_BP_FRAME); - key_parser_add(ctx.parser, "bp_off", FUNCTION_FIELD_BP_OFF); - key_parser_add(ctx.parser, "noreturn", FUNCTION_FIELD_NORETURN); - key_parser_add(ctx.parser, "fingerprint", FUNCTION_FIELD_FINGERPRINT); - key_parser_add(ctx.parser, "diff", FUNCTION_FIELD_DIFF); - key_parser_add(ctx.parser, "bbs", FUNCTION_FIELD_BBS); - key_parser_add(ctx.parser, "imports", FUNCTION_FIELD_IMPORTS); - key_parser_add(ctx.parser, "vars", FUNCTION_FIELD_VARS); - key_parser_add(ctx.parser, "labels", FUNCTION_FIELD_LABELS); + rz_key_parser_add(ctx.parser, "name", FUNCTION_FIELD_NAME); + rz_key_parser_add(ctx.parser, "bits", FUNCTION_FIELD_BITS); + rz_key_parser_add(ctx.parser, "type", FUNCTION_FIELD_TYPE); + rz_key_parser_add(ctx.parser, "cc", FUNCTION_FIELD_CC); + rz_key_parser_add(ctx.parser, "stack", FUNCTION_FIELD_STACK); + rz_key_parser_add(ctx.parser, "maxstack", FUNCTION_FIELD_MAXSTACK); + rz_key_parser_add(ctx.parser, "ninstr", FUNCTION_FIELD_NINSTR); + rz_key_parser_add(ctx.parser, "pure", FUNCTION_FIELD_PURE); + rz_key_parser_add(ctx.parser, "bp_frame", FUNCTION_FIELD_BP_FRAME); + rz_key_parser_add(ctx.parser, "bp_off", FUNCTION_FIELD_BP_OFF); + rz_key_parser_add(ctx.parser, "noreturn", FUNCTION_FIELD_NORETURN); + rz_key_parser_add(ctx.parser, "fingerprint", FUNCTION_FIELD_FINGERPRINT); + rz_key_parser_add(ctx.parser, "diff", FUNCTION_FIELD_DIFF); + rz_key_parser_add(ctx.parser, "bbs", FUNCTION_FIELD_BBS); + rz_key_parser_add(ctx.parser, "imports", FUNCTION_FIELD_IMPORTS); + rz_key_parser_add(ctx.parser, "vars", FUNCTION_FIELD_VARS); + rz_key_parser_add(ctx.parser, "labels", FUNCTION_FIELD_LABELS); ret = sdb_foreach(db, function_load_cb, &ctx); if (!ret) { - SERIALIZE_ERR("functions parsing failed"); + RZ_SERIALIZE_ERR(res, "functions parsing failed"); } beach: - key_parser_free(ctx.parser); + rz_key_parser_free(ctx.parser); rz_serialize_analysis_var_parser_free(ctx.var_parser); return ret; } @@ -1326,7 +1324,7 @@ error: RZ_API bool rz_serialize_analysis_xrefs_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res) { bool ret = sdb_foreach(db, xrefs_load_cb, analysis); if (!ret) { - SERIALIZE_ERR("xrefs parsing failed"); + RZ_SERIALIZE_ERR(res, "xrefs parsing failed"); } return ret; } @@ -1556,7 +1554,7 @@ error: RZ_API bool rz_serialize_analysis_meta_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res) { Sdb *spaces_db = sdb_ns(db, "spaces", false); if (!spaces_db) { - SERIALIZE_ERR("missing meta spaces namespace"); + RZ_SERIALIZE_ERR(res, "missing meta spaces namespace"); return false; } if (!rz_serialize_spaces_load(spaces_db, &analysis->meta_spaces, false, res)) { @@ -1564,7 +1562,7 @@ RZ_API bool rz_serialize_analysis_meta_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAna } bool ret = sdb_foreach(db, meta_load_cb, analysis); if (!ret) { - SERIALIZE_ERR("meta parsing failed"); + RZ_SERIALIZE_ERR(res, "meta parsing failed"); } return ret; } @@ -1739,7 +1737,7 @@ enum { typedef struct { RzAnalysis *analysis; - KeyParser *parser; + RzKeyParser *parser; } HintsLoadCtx; static bool hints_load_cb(void *user, const char *k, const char *v) { @@ -1762,7 +1760,7 @@ static bool hints_load_cb(void *user, const char *k, const char *v) { return false; } - KEY_PARSER_JSON(ctx->parser, json, child, { + RZ_KEY_PARSER_JSON(ctx->parser, json, child, { case HINTS_FIELD_ARCH: rz_analysis_hint_set_arch(analysis, addr, child->type == RZ_JSON_STRING ? child->str_value : NULL); break; @@ -1878,38 +1876,38 @@ static bool hints_load_cb(void *user, const char *k, const char *v) { RZ_API bool rz_serialize_analysis_hints_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res) { HintsLoadCtx ctx = { .analysis = analysis, - .parser = key_parser_new(), + .parser = rz_key_parser_new(), }; bool ret; if (!ctx.parser) { - SERIALIZE_ERR("parser init failed"); + RZ_SERIALIZE_ERR(res, "parser init failed"); ret = false; goto beach; } - key_parser_add(ctx.parser, "arch", HINTS_FIELD_ARCH); - key_parser_add(ctx.parser, "bits", HINTS_FIELD_BITS); - key_parser_add(ctx.parser, "immbase", HINTS_FIELD_IMMBASE); - key_parser_add(ctx.parser, "jump", HINTS_FIELD_JUMP); - key_parser_add(ctx.parser, "fail", HINTS_FIELD_FAIL); - key_parser_add(ctx.parser, "frame", HINTS_FIELD_STACKFRAME); - key_parser_add(ctx.parser, "ptr", HINTS_FIELD_PTR); - key_parser_add(ctx.parser, "nword", HINTS_FIELD_NWORD); - key_parser_add(ctx.parser, "ret", HINTS_FIELD_RET); - key_parser_add(ctx.parser, "newbits", HINTS_FIELD_NEW_BITS); - key_parser_add(ctx.parser, "size", HINTS_FIELD_SIZE); - key_parser_add(ctx.parser, "syntax", HINTS_FIELD_SYNTAX); - key_parser_add(ctx.parser, "optype", HINTS_FIELD_OPTYPE); - key_parser_add(ctx.parser, "opcode", HINTS_FIELD_OPCODE); - key_parser_add(ctx.parser, "toff", HINTS_FIELD_TYPE_OFFSET); - key_parser_add(ctx.parser, "esil", HINTS_FIELD_ESIL); - key_parser_add(ctx.parser, "high", HINTS_FIELD_HIGH); - key_parser_add(ctx.parser, "val", HINTS_FIELD_VAL); + rz_key_parser_add(ctx.parser, "arch", HINTS_FIELD_ARCH); + rz_key_parser_add(ctx.parser, "bits", HINTS_FIELD_BITS); + rz_key_parser_add(ctx.parser, "immbase", HINTS_FIELD_IMMBASE); + rz_key_parser_add(ctx.parser, "jump", HINTS_FIELD_JUMP); + rz_key_parser_add(ctx.parser, "fail", HINTS_FIELD_FAIL); + rz_key_parser_add(ctx.parser, "frame", HINTS_FIELD_STACKFRAME); + rz_key_parser_add(ctx.parser, "ptr", HINTS_FIELD_PTR); + rz_key_parser_add(ctx.parser, "nword", HINTS_FIELD_NWORD); + rz_key_parser_add(ctx.parser, "ret", HINTS_FIELD_RET); + rz_key_parser_add(ctx.parser, "newbits", HINTS_FIELD_NEW_BITS); + rz_key_parser_add(ctx.parser, "size", HINTS_FIELD_SIZE); + rz_key_parser_add(ctx.parser, "syntax", HINTS_FIELD_SYNTAX); + rz_key_parser_add(ctx.parser, "optype", HINTS_FIELD_OPTYPE); + rz_key_parser_add(ctx.parser, "opcode", HINTS_FIELD_OPCODE); + rz_key_parser_add(ctx.parser, "toff", HINTS_FIELD_TYPE_OFFSET); + rz_key_parser_add(ctx.parser, "esil", HINTS_FIELD_ESIL); + rz_key_parser_add(ctx.parser, "high", HINTS_FIELD_HIGH); + rz_key_parser_add(ctx.parser, "val", HINTS_FIELD_VAL); ret = sdb_foreach(db, hints_load_cb, &ctx); if (!ret) { - SERIALIZE_ERR("hints parsing failed"); + RZ_SERIALIZE_ERR(res, "hints parsing failed"); } beach: - key_parser_free(ctx.parser); + rz_key_parser_free(ctx.parser); return ret; } @@ -1919,7 +1917,7 @@ RZ_API void rz_serialize_analysis_classes_save(RZ_NONNULL Sdb *db, RZ_NONNULL Rz RZ_API bool rz_serialize_analysis_classes_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis *analysis, RZ_NULLABLE RzSerializeResultInfo *res) { if (!sdb_ns(db, "attrs", false)) { - SERIALIZE_ERR("missing attrs namespace"); + RZ_SERIALIZE_ERR(res, "missing attrs namespace"); return false; } sdb_reset(analysis->sdb_classes); @@ -1948,7 +1946,7 @@ RZ_API bool rz_serialize_analysis_sign_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAna sdb_copy(db, analysis->sdb_zigns); Sdb *spaces_db = sdb_ns(db, "spaces", false); if (!spaces_db) { - SERIALIZE_ERR("missing spaces namespace"); + RZ_SERIALIZE_ERR(res, "missing spaces namespace"); return false; } if (!rz_serialize_spaces_load(spaces_db, &analysis->zign_spaces, false, res)) { @@ -2016,7 +2014,7 @@ RZ_API bool rz_serialize_analysis_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzAnalysis rz_analysis_purge(analysis); Sdb *subdb; -#define SUB(ns, call) SUB_DO(ns, call, goto beach;) +#define SUB(ns, call) RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, goto beach;) SUB("xrefs", rz_serialize_analysis_xrefs_load(subdb, analysis, res)); SUB("blocks", rz_serialize_analysis_blocks_load(subdb, analysis, diff_parser, res)); diff --git a/librz/core/project.c b/librz/core/project.c index c4b30e1ba9..da950928d9 100644 --- a/librz/core/project.c +++ b/librz/core/project.c @@ -2,8 +2,6 @@ #include -#include "../util/serialize_helper.h" - #define RZ_DB_KEY_TYPE "type" #define RZ_DB_KEY_VERSION "version" @@ -75,7 +73,7 @@ RZ_API RzProjectErr rz_project_load(RzCore *core, RzProject *prj, bool load_bin_ Sdb *core_db = sdb_ns(prj, "core", false); if (!core_db) { - SERIALIZE_ERR("missing core namespace"); + RZ_SERIALIZE_ERR(res, "missing core namespace"); return RZ_PROJECT_ERR_INVALID_CONTENTS; } if (!rz_serialize_core_load(core_db, core, load_bin_io, file, res)) { @@ -93,7 +91,7 @@ RZ_API RzProjectErr rz_project_load_file(RzCore *core, const char *file, bool lo return RZ_PROJECT_ERR_UNKNOWN; } if (!sdb_text_load(prj, file)) { - SERIALIZE_ERR("failed to read database file"); + RZ_SERIALIZE_ERR(res, "failed to read database file"); return RZ_PROJECT_ERR_FILE; } RzProjectErr ret = rz_project_load(core, prj, load_bin_io, file, res); diff --git a/librz/core/serialize_core.c b/librz/core/serialize_core.c index 30ed7b3aa6..062292f5f5 100644 --- a/librz/core/serialize_core.c +++ b/librz/core/serialize_core.c @@ -3,8 +3,6 @@ #include #include -#include "../util/serialize_helper.h" - /* * SDB Format: * @@ -49,7 +47,7 @@ RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE const char *prj_file, RZ_NULLABLE RzSerializeResultInfo *res) { Sdb *subdb; -#define SUB(ns, call) SUB_DO(ns, call, return false;) +#define SUB(ns, call) RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, return false;) if (load_bin_io) { SUB("file", file_load(subdb, core, prj_file, res)); @@ -60,14 +58,14 @@ RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, const char *str = sdb_get(db, "offset", 0); if (!str || !*str) { - SERIALIZE_ERR("missing offset in core"); + RZ_SERIALIZE_ERR(res, "missing offset in core"); return false; } core->offset = strtoull(str, NULL, 0); str = sdb_get(db, "blocksize", 0); if (!str || !*str) { - SERIALIZE_ERR("missing blocksize in core"); + RZ_SERIALIZE_ERR(res, "missing blocksize in core"); return false; } ut64 bs = strtoull(str, NULL, 0); @@ -182,7 +180,7 @@ static FileRet try_load_file(RZ_NONNULL RzCore *core, const char *file, RZ_NULLA RzCoreFile *fh = rz_core_file_open(core, file, RZ_PERM_RX, 0); if (!fh) { - SERIALIZE_ERR("failed re-open file \"%s\" referenced by project", file); + RZ_SERIALIZE_ERR(res, "failed re-open file \"%s\" referenced by project", file); return FILE_LOAD_FAIL; } rz_core_bin_load(core, file, UT64_MAX); @@ -229,6 +227,6 @@ static bool file_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core, RZ_NULLABLE c return r == FILE_SUCCESS; } - SERIALIZE_ERR("failed to re-locate file referenced by project"); + RZ_SERIALIZE_ERR(res, "failed to re-locate file referenced by project"); return false; } diff --git a/librz/flag/serialize_flag.c b/librz/flag/serialize_flag.c index d468e7dd3c..37f9b74531 100644 --- a/librz/flag/serialize_flag.c +++ b/librz/flag/serialize_flag.c @@ -3,8 +3,6 @@ #include #include -#include "../util/serialize_helper.h" - #if RZ_FLAG_ZONE_USE_SDB #error "RZ_FLAG_ZONE_USE_SDB not supported by rz_serialize" #endif @@ -89,7 +87,7 @@ RZ_API bool rz_serialize_flag_zones_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzList / rz_list_purge(zones); bool r = sdb_foreach(db, zone_load_cb, zones); if (!r) { - SERIALIZE_ERR("failed to parse a flag zone json"); + RZ_SERIALIZE_ERR(res, "failed to parse a flag zone json"); } return r; } @@ -151,7 +149,7 @@ typedef enum { typedef struct { RzFlag *flag; - KeyParser *parser; + RzKeyParser *parser; } FlagLoadCtx; static bool flag_load_cb(void *user, const char *k, const char *v) { @@ -171,7 +169,7 @@ static bool flag_load_cb(void *user, const char *k, const char *v) { bool offset_set = false; bool size_set = false; - KEY_PARSER_JSON(ctx->parser, json, child, { + RZ_KEY_PARSER_JSON(ctx->parser, json, child, { case FLAG_FIELD_REALNAME: if (child->type != RZ_JSON_STRING) { break; @@ -255,20 +253,20 @@ beach: } static bool load_flags(RZ_NONNULL Sdb *flags_db, RZ_NONNULL RzFlag *flag) { - FlagLoadCtx ctx = { flag, key_parser_new() }; + FlagLoadCtx ctx = { flag, rz_key_parser_new() }; if (!ctx.parser) { return false; } - key_parser_add(ctx.parser, "realname", FLAG_FIELD_REALNAME); - key_parser_add(ctx.parser, "demangled", FLAG_FIELD_DEMANGLED); - key_parser_add(ctx.parser, "offset", FLAG_FIELD_OFFSET); - key_parser_add(ctx.parser, "size", FLAG_FIELD_SIZE); - key_parser_add(ctx.parser, "space", FLAG_FIELD_SPACE); - key_parser_add(ctx.parser, "color", FLAG_FIELD_COLOR); - key_parser_add(ctx.parser, "comment", FLAG_FIELD_COMMENT); - key_parser_add(ctx.parser, "alias", FLAG_FIELD_ALIAS); + rz_key_parser_add(ctx.parser, "realname", FLAG_FIELD_REALNAME); + rz_key_parser_add(ctx.parser, "demangled", FLAG_FIELD_DEMANGLED); + rz_key_parser_add(ctx.parser, "offset", FLAG_FIELD_OFFSET); + rz_key_parser_add(ctx.parser, "size", FLAG_FIELD_SIZE); + rz_key_parser_add(ctx.parser, "space", FLAG_FIELD_SPACE); + rz_key_parser_add(ctx.parser, "color", FLAG_FIELD_COLOR); + rz_key_parser_add(ctx.parser, "comment", FLAG_FIELD_COMMENT); + rz_key_parser_add(ctx.parser, "alias", FLAG_FIELD_ALIAS); bool r = sdb_foreach(flags_db, flag_load_cb, &ctx); - key_parser_free(ctx.parser); + rz_key_parser_free(ctx.parser); return r; } @@ -277,21 +275,21 @@ RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag, const char *str = sdb_const_get(db, "base", NULL); if (!str) { - SERIALIZE_ERR("flag base key is missing"); + RZ_SERIALIZE_ERR(res, "flag base key is missing"); return false; } flag->base = strtoll(str, NULL, 0); str = sdb_const_get(db, "realnames", 0); if (!str) { - SERIALIZE_ERR("flag realnames key is missing"); + RZ_SERIALIZE_ERR(res, "flag realnames key is missing"); return false; } flag->realnames = strtoul(str, NULL, 0) ? true : false; Sdb *spaces_db = sdb_ns(db, "spaces", false); if (!spaces_db) { - SERIALIZE_ERR("missing spaces namespace"); + RZ_SERIALIZE_ERR(res, "missing spaces namespace"); return false; } if (!rz_serialize_spaces_load(spaces_db, &flag->spaces, false, res)) { @@ -300,14 +298,14 @@ RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag, Sdb *tags_db = sdb_ns(db, "tags", false); if (!tags_db) { - SERIALIZE_ERR("missing tags namespace"); + RZ_SERIALIZE_ERR(res, "missing tags namespace"); return false; } sdb_copy(tags_db, flag->tags); Sdb *zones_db = sdb_ns(db, "zones", false); if (!zones_db) { - SERIALIZE_ERR("missing zones namespace"); + RZ_SERIALIZE_ERR(res, "missing zones namespace"); return false; } rz_flag_zone_reset(flag); @@ -317,11 +315,11 @@ RZ_API bool rz_serialize_flag_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzFlag *flag, Sdb *flags_db = sdb_ns(db, "flags", false); if (!flags_db) { - SERIALIZE_ERR("missing flags sub-namespace"); + RZ_SERIALIZE_ERR(res, "missing flags sub-namespace"); return false; } if (!load_flags(flags_db, flag)) { - SERIALIZE_ERR("failed to parse a flag json"); + RZ_SERIALIZE_ERR(res, "failed to parse a flag json"); return false; } diff --git a/librz/include/rz_util/rz_serialize.h b/librz/include/rz_util/rz_serialize.h index ba1c6f0073..ea8071475f 100644 --- a/librz/include/rz_util/rz_serialize.h +++ b/librz/include/rz_util/rz_serialize.h @@ -1,4 +1,4 @@ -/* rizin - LGPL - Copyright 2020 - thestr4ng3r */ +// SPDX-License-Identifier: LGPL-3.0-only #ifndef RZ_SERIALIZE_H #define RZ_SERIALIZE_H @@ -6,12 +6,109 @@ #include #include +/** + * \brief Detailed info about a (de)serialization result + * + * This is currently just a list of strings which may be warnings + * or detailed error messages. + */ typedef RzList RzSerializeResultInfo; + static inline RzSerializeResultInfo *rz_serialize_result_info_new(void) { return rz_list_newf(free); } + static inline void rz_serialize_result_info_free(RzSerializeResultInfo *info) { rz_list_free(info); } +// Common helpers for writing (de)serialization code + +/** + * \brief Push an error to the local RzSerializeResultInfo + * \res RzSerializeInfoResult * + * \param ... printf-style arguments to be pushed as the error to res + */ +#define RZ_SERIALIZE_ERR(res, ...) \ + do { \ + if (res) { \ + rz_list_push(res, rz_str_newf(__VA_ARGS__)); \ + } \ + } while (0) + +/** + * \brief Hashtable-based key parser to prevent strcmp chains + * + * This enables string values to be used in a switch/case-like + * fashion. + */ +typedef HtPP RzKeyParser; + +static inline RzKeyParser *rz_key_parser_new(void) { + return ht_pp_new0(); +} + +static inline void rz_key_parser_free(RzKeyParser *parser) { + ht_pp_free(parser); +} + +static inline void rz_key_parser_add(RzKeyParser *parser, const char *key, int val) { + ht_pp_insert(parser, key, (void *)(size_t)val); +} + +#define RZ_KEY_PARSER_UNKNOWN -1 + +/** + * \brief switch-like macro over RzKeyParser values + * \param parser RzKeyParser * + * \param key const char * + */ +#define RZ_KEY_PARSER_SWITCH(parser, key) \ + bool key_parser_found = false; \ + int key_parser_v = (int)(size_t)ht_pp_find(parser, key, &key_parser_found); \ + if (!key_parser_found) { \ + key_parser_v = RZ_KEY_PARSER_UNKNOWN; \ + } \ + switch (key_parser_v) + +/** + * \brief Iterate over all keys in a json object and call RZ_KEY_PARSER_SWITCH on each + * \param parser RzKeyParser * + * \param json RzJson * + * \param child var name for the `RzJson *child` + * \param body code block with cases + */ +#define RZ_KEY_PARSER_JSON(parser, json, child, body) \ + if (json->type == RZ_JSON_OBJECT) { \ + for (RJson *child = json->children.first; child; child = child->next) { \ + RZ_KEY_PARSER_SWITCH(parser, child->key) { body } \ + } \ + } + +/** + * \brief Get an sdb sub-namespace and evaluate `call` or fail + * \param db Sdb * the Sdb from which to take the sub-namespace + * \param subdb Sdb * where to put the sub-namespace + * \param res RzSerializeResult * where to push an error on failure + * \param ns const char * + * \param call function call + * \param rip code to execute if the function failed + * + * Example: + * + * Sdb *subdb; + * RZ_SERIALIZE_SUB_DO(db, subdb, res, "files", + * rz_serialize_io_files_load(subdb, io, res), return false;) + * + */ +#define RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, rip) \ + subdb = sdb_ns(db, ns, false); \ + if (!subdb) { \ + RZ_SERIALIZE_ERR(res, "missing " ns " namespace"); \ + rip \ + } \ + if (!(call)) { \ + rip \ + } + #endif //RZ_SERIALIZE_H diff --git a/librz/io/serialize_io.c b/librz/io/serialize_io.c index 6dbba7f5dd..d32adeccf2 100644 --- a/librz/io/serialize_io.c +++ b/librz/io/serialize_io.c @@ -3,8 +3,6 @@ #include #include -#include "../util/serialize_helper.h" - #include /* @@ -103,7 +101,7 @@ RZ_API bool rz_serialize_io_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzIO *io, RZ_NUL // TODO: purge RzIO? bool ret = false; Sdb *subdb; -#define SUB(ns, call) SUB_DO(ns, call, goto beach;) +#define SUB(ns, call) RZ_SERIALIZE_SUB_DO(db, subdb, res, ns, call, goto beach;) SUB("files", rz_serialize_io_files_load(subdb, io, res)); #undef SUB ret = true; diff --git a/librz/util/serialize_helper.h b/librz/util/serialize_helper.h deleted file mode 100644 index 4c66b819fb..0000000000 --- a/librz/util/serialize_helper.h +++ /dev/null @@ -1,56 +0,0 @@ - -#ifndef RZ_SERIALIZE_UTIL_H -#define RZ_SERIALIZE_UTIL_H - -#include - -#define SERIALIZE_ERR(...) \ - do { \ - if (res) { \ - rz_list_push(res, rz_str_newf(__VA_ARGS__)); \ - } \ - } while (0) - -// Hashtable-based key parser to prevent strcmp chains -typedef HtPP KeyParser; - -static inline KeyParser *key_parser_new(void) { - return ht_pp_new0(); -} - -static inline void key_parser_free(KeyParser *parser) { - ht_pp_free(parser); -} - -static inline void key_parser_add(KeyParser *parser, const char *key, int val) { - ht_pp_insert(parser, key, (void *)(size_t)val); -} - -#define KEY_PARSER_UNKNOWN -1 - -#define KEY_PARSER_SWITCH(parser, key) \ - bool key_parser_found = false; \ - int key_parser_v = (int)(size_t)ht_pp_find(parser, key, &key_parser_found); \ - if (!key_parser_found) { \ - key_parser_v = KEY_PARSER_UNKNOWN; \ - } \ - switch (key_parser_v) - -#define KEY_PARSER_JSON(parser, json, child, body) \ - if (json->type == RZ_JSON_OBJECT) { \ - for (RJson *child = json->children.first; child; child = child->next) { \ - KEY_PARSER_SWITCH(parser, child->key) { body } \ - } \ - } - -#define SUB_DO(ns, call, rip) \ - subdb = sdb_ns(db, ns, false); \ - if (!subdb) { \ - SERIALIZE_ERR("missing " ns " namespace"); \ - rip \ - } \ - if (!(call)) { \ - rip \ - } - -#endif //RZ_SERIALIZE_UTIL_H diff --git a/librz/util/serialize_spaces.c b/librz/util/serialize_spaces.c index ac83bad971..7deee4a101 100644 --- a/librz/util/serialize_spaces.c +++ b/librz/util/serialize_spaces.c @@ -2,8 +2,6 @@ #include #include -#include "../util/serialize_helper.h" - /* * SDB Format: * @@ -57,7 +55,7 @@ RZ_API bool rz_serialize_spaces_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzSpaces *sp spaces->name = sdb_get(db, KEY_NAME, NULL); if (!spaces->name) { spaces->name = old_name; - SERIALIZE_ERR("failed to get spaces name from db"); + RZ_SERIALIZE_ERR(res, "failed to get spaces name from db"); return false; } free(old_name); @@ -67,33 +65,33 @@ RZ_API bool rz_serialize_spaces_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzSpaces *sp Sdb *db_spaces = sdb_ns(db, KEY_SPACES, false); if (!db_spaces) { - SERIALIZE_ERR("failed to get spaces sub-namespace"); + RZ_SERIALIZE_ERR(res, "failed to get spaces sub-namespace"); return false; } sdb_foreach(db_spaces, foreach_space_cb, spaces); char *stack_json_str = sdb_get(db, KEY_SPACESTACK, NULL); if (!stack_json_str) { - SERIALIZE_ERR("spacestack is missing"); + RZ_SERIALIZE_ERR(res, "spacestack is missing"); return false; } bool ret = true; RJson *stack_json = rz_json_parse(stack_json_str); if (!stack_json) { - SERIALIZE_ERR("failed to parse stackspace json"); + RZ_SERIALIZE_ERR(res, "failed to parse stackspace json"); ret = false; goto beach; } if (stack_json->type != RZ_JSON_ARRAY) { - SERIALIZE_ERR("stackspace json is not an array"); + RZ_SERIALIZE_ERR(res, "stackspace json is not an array"); ret = false; goto beach; } RJson *stack_element; for (stack_element = stack_json->children.first; stack_element; stack_element = stack_element->next) { if (stack_element->type != RZ_JSON_STRING) { - SERIALIZE_ERR("stackspace element is not a string"); + RZ_SERIALIZE_ERR(res, "stackspace element is not a string"); ret = false; goto beach; }