Fix undefined behaviour in RVector, RPVector, RInterval and container_of ##fix

* All those basic primites were based on wrong assumptions
* Added more return_if preconditions on several anal functions
This commit is contained in:
pancake 2022-03-21 11:29:19 +01:00 committed by pancake
parent 69815e22e4
commit ad2df6a14c
5 changed files with 40 additions and 26 deletions

View File

@ -1436,10 +1436,12 @@ beach:
}
R_API int r_anal_function_bb(RAnal *anal, RAnalFunction *fcn, ut64 addr, int depth) {
r_return_val_if_fail (anal && fcn, -1);
return fcn_recurse (anal, fcn, addr, anal->opt.bb_max_size, depth - 1);
}
R_API bool r_anal_check_fcn(RAnal *anal, ut8 *buf, ut16 bufsz, ut64 addr, ut64 low, ut64 high) {
r_return_val_if_fail (anal && buf, false);
RAnalOp op = {
0
};
@ -1480,6 +1482,7 @@ R_API bool r_anal_check_fcn(RAnal *anal, ut8 *buf, ut16 bufsz, ut64 addr, ut64 l
}
R_API void r_anal_trim_jmprefs(RAnal *anal, RAnalFunction *fcn) {
r_return_if_fail (anal && fcn);
RAnalRef *ref;
RList *refs = r_anal_function_get_refs (fcn);
RListIter *iter;
@ -1495,6 +1498,7 @@ R_API void r_anal_trim_jmprefs(RAnal *anal, RAnalFunction *fcn) {
}
R_API void r_anal_del_jmprefs(RAnal *anal, RAnalFunction *fcn) {
r_return_if_fail (anal && fcn);
RAnalRef *ref;
RList *refs = r_anal_function_get_refs (fcn);
RListIter *iter;
@ -1509,21 +1513,24 @@ R_API void r_anal_del_jmprefs(RAnal *anal, RAnalFunction *fcn) {
/* Does NOT invalidate read-ahead cache. */
R_API int r_anal_function(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut64 len, int reftype) {
RPVector *metas = r_meta_get_all_in(anal, addr, R_META_TYPE_ANY);
void **it;
r_pvector_foreach (metas, it) {
RAnalMetaItem *meta = ((RIntervalNode *)*it)->data;
switch (meta->type) {
case R_META_TYPE_DATA:
case R_META_TYPE_STRING:
case R_META_TYPE_FORMAT:
r_pvector_free (metas);
return 0;
default:
break;
r_return_val_if_fail (anal && fcn, 0);
RPVector *metas = r_meta_get_all_in (anal, addr, R_META_TYPE_ANY);
if (metas) {
void **it;
r_pvector_foreach (metas, it) {
RAnalMetaItem *meta = ((RIntervalNode *)*it)->data;
switch (meta->type) {
case R_META_TYPE_DATA:
case R_META_TYPE_STRING:
case R_META_TYPE_FORMAT:
r_pvector_free (metas);
return 0;
default:
break;
}
}
r_pvector_free (metas);
}
r_pvector_free (metas);
if (anal->opt.norevisit) {
if (!anal->visited) {
anal->visited = set_u_new ();

View File

@ -257,14 +257,18 @@ R_API void r_anal_function_delete_vars_by_kind(RAnalFunction *fcn, RAnalVarKind
}
R_API void r_anal_function_delete_all_vars(RAnalFunction *fcn) {
void **it;
r_pvector_foreach (&fcn->vars, it) {
var_free (*it);
r_return_if_fail (fcn);
if (fcn->vars.v.len > 0) {
void **it;
r_pvector_foreach (&fcn->vars, it) {
var_free (*it);
}
}
r_pvector_clear (&fcn->vars);
}
R_API void r_anal_function_delete_unused_vars(RAnalFunction *fcn) {
r_return_if_fail (fcn);
void **v;
RPVector *vars_clone = (RPVector *)r_vector_clone ((RVector *)&fcn->vars);
r_pvector_foreach (vars_clone, v) {
@ -283,6 +287,7 @@ R_API void r_anal_function_delete_var(RAnalFunction *fcn, RAnalVar *var) {
}
R_API RList *r_anal_var_deserialize(const char *ser) {
r_return_val_if_fail (ser, NULL);
RList *ret = r_list_newf ((RListFree)r_anal_var_proto_free);
while (*ser) {
RAnalVarProt *v = R_NEW0 (RAnalVarProt);
@ -381,6 +386,7 @@ static inline void sanitize_var_serial(char *name, bool colon) {
}
static inline bool serialize_single_var(RAnalVarProt *vp, RStrBuf *sb) {
r_return_val_if_fail (vp && sb, false);
// shouldn't have special chars in them anyways, so replace in place
sanitize_var_serial (vp->name, false);
sanitize_var_serial (vp->type, true);
@ -1364,11 +1370,13 @@ static RList *var_generate_list(RAnal *a, RAnalFunction *fcn, int kind) {
if (kind < 1) {
kind = R_ANAL_VAR_KIND_BPV; // by default show vars
}
void **it;
r_pvector_foreach (&fcn->vars, it) {
RAnalVar *var = *it;
if (var->kind == kind) {
r_list_push (list, var);
if (fcn->vars.v.len > 0) {
void **it;
r_pvector_foreach (&fcn->vars, it) {
RAnalVar *var = *it;
if (var->kind == kind) {
r_list_push (list, var);
}
}
}
return list;

View File

@ -722,11 +722,7 @@ static inline void r_run_call10(void *fcn, void *arg1, void *arg2, void *arg3, v
}
#ifndef container_of
# ifdef _MSC_VER
# define container_of(ptr, type, member) ((type *)((char *)(ptr) - offsetof(type, member)))
# else
# define container_of(ptr, type, member) ((type *)((char *)(__typeof__(((type *)0)->member) *){ptr} - offsetof(type, member)))
# endif
#define container_of(ptr, type, member) (ptr? ((type *)((char *)(ptr) - r_offsetof(type, member))): NULL)
#endif
// reference counter

View File

@ -294,10 +294,12 @@ static inline void **r_pvector_flush(RPVector *vec) {
* }
*/
#define r_pvector_foreach(vec, it) \
if ((vec)->v.len > 0) \
for (it = (void **)(vec)->v.a; it != (void **)(vec)->v.a + (vec)->v.len; it++)
// like r_pvector_foreach() but inverse
#define r_pvector_foreach_prev(vec, it) \
if ((vec)->v.len > 0) \
for (it = ((vec)->v.len == 0 ? NULL : (void **)(vec)->v.a + (vec)->v.len - 1); it != NULL && it != (void **)(vec)->v.a - 1; it--)
/*

View File

@ -168,6 +168,7 @@ R_API bool r_interval_tree_resize(RIntervalTree *tree, RIntervalNode *node, ut64
// This must always return the topmost node that matches start!
// Otherwise r_interval_tree_first_at will break!!!
R_API RIntervalNode *r_interval_tree_node_at(RIntervalTree *tree, ut64 start) {
r_return_val_if_fail (tree, NULL);
RIntervalNode *node = tree->root;
while (node) {
if (start < node->start) {