mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
Use actual pointers in dispatch_cfg.c.
Previously, I had used integers encoded as pointers. This introduced a flaw: NULL represented both the integer zero, and the absence of a setting. This in turn made the checks in cfg_msg_set_{type,chan}() not actually check for an altered value if the previous value had been set to zero. Also, I had previously kept a pointer to a dispatch_fypefns_t rather than making a copy of it. This meant that if the dispatch_typefns_t were changed between defining the typefns and creating the dispatcher, we'd get the modified version. Found while investigating coverage in pubsub_add_{pub,sub}_()
This commit is contained in:
parent
8d70f21717
commit
47de9c7b0a
@ -37,9 +37,6 @@ dcfg_new(void)
|
||||
return cfg;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
#define ID_TO_VOID(id) ((void*)(uintptr_t)(id))
|
||||
|
||||
/**
|
||||
* Associate a message with a datatype. Return 0 on success, -1 if a
|
||||
* different type was previously associated with the message ID.
|
||||
@ -49,11 +46,12 @@ dcfg_msg_set_type(dispatch_cfg_t *cfg, message_id_t msg,
|
||||
msg_type_id_t type)
|
||||
{
|
||||
smartlist_grow(cfg->type_by_msg, msg+1);
|
||||
void *oldval = smartlist_get(cfg->type_by_msg, msg);
|
||||
if (oldval != NULL && oldval != ID_TO_VOID(type)) {
|
||||
msg_type_id_t *oldval = smartlist_get(cfg->type_by_msg, msg);
|
||||
if (oldval != NULL && *oldval != type) {
|
||||
return -1;
|
||||
}
|
||||
smartlist_set(cfg->type_by_msg, msg, ID_TO_VOID(type));
|
||||
if (!oldval)
|
||||
smartlist_set(cfg->type_by_msg, msg, tor_memdup(&type, sizeof(type)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -66,11 +64,12 @@ dcfg_msg_set_chan(dispatch_cfg_t *cfg, message_id_t msg,
|
||||
channel_id_t chan)
|
||||
{
|
||||
smartlist_grow(cfg->chan_by_msg, msg+1);
|
||||
void *oldval = smartlist_get(cfg->chan_by_msg, msg);
|
||||
if (oldval != NULL && oldval != ID_TO_VOID(chan)) {
|
||||
channel_id_t *oldval = smartlist_get(cfg->chan_by_msg, msg);
|
||||
if (oldval != NULL && *oldval != chan) {
|
||||
return -1;
|
||||
}
|
||||
smartlist_set(cfg->chan_by_msg, msg, ID_TO_VOID(chan));
|
||||
if (!oldval)
|
||||
smartlist_set(cfg->chan_by_msg, msg, tor_memdup(&chan, sizeof(chan)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -87,7 +86,8 @@ dcfg_type_set_fns(dispatch_cfg_t *cfg, msg_type_id_t type,
|
||||
if (oldfns && (oldfns->free_fn != fns->free_fn ||
|
||||
oldfns->fmt_fn != fns->fmt_fn))
|
||||
return -1;
|
||||
smartlist_set(cfg->fns_by_type, type, (dispatch_typefns_t *) fns);
|
||||
if (!oldfns)
|
||||
smartlist_set(cfg->fns_by_type, type, tor_memdup(fns, sizeof(*fns)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -123,6 +123,9 @@ dcfg_free_(dispatch_cfg_t *cfg)
|
||||
if (!cfg)
|
||||
return;
|
||||
|
||||
SMARTLIST_FOREACH(cfg->type_by_msg, msg_type_id_t *, id, tor_free(id));
|
||||
SMARTLIST_FOREACH(cfg->chan_by_msg, channel_id_t *, id, tor_free(id));
|
||||
SMARTLIST_FOREACH(cfg->fns_by_type, dispatch_typefns_t *, f, tor_free(f));
|
||||
smartlist_free(cfg->type_by_msg);
|
||||
smartlist_free(cfg->chan_by_msg);
|
||||
smartlist_free(cfg->fns_by_type);
|
||||
|
@ -17,32 +17,36 @@
|
||||
#include "lib/dispatch/dispatch_cfg.h"
|
||||
#include "lib/dispatch/dispatch_cfg_st.h"
|
||||
|
||||
#include "lib/cc/ctassert.h"
|
||||
#include "lib/intmath/cmp.h"
|
||||
#include "lib/malloc/malloc.h"
|
||||
#include "lib/log/util_bug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/** Convert a void* in a smartlist to the corresponding integer. */
|
||||
#define VOID_TO_ID(p) ((intptr_t)(p))
|
||||
|
||||
/** Given a smartlist full of void* fields encoding intptr_t values,
|
||||
* return the largest intptr_t, or dflt if the list is empty. */
|
||||
static intptr_t
|
||||
max_in_sl(const smartlist_t *sl, intptr_t dflt)
|
||||
/** Given a smartlist full of (possibly NULL) pointers to uint16_t values,
|
||||
* return the largest value, or dflt if the list is empty. */
|
||||
static int
|
||||
max_in_sl(const smartlist_t *sl, int dflt)
|
||||
{
|
||||
if (!smartlist_len(sl))
|
||||
return dflt;
|
||||
void *as_ptr = smartlist_get(sl, 0);
|
||||
intptr_t max = VOID_TO_ID(as_ptr);
|
||||
SMARTLIST_FOREACH_BEGIN(sl, void *, p) {
|
||||
intptr_t i = VOID_TO_ID(p);
|
||||
if (i > max)
|
||||
max = i;
|
||||
} SMARTLIST_FOREACH_END(p);
|
||||
return max;
|
||||
uint16_t *maxptr = NULL;
|
||||
SMARTLIST_FOREACH_BEGIN(sl, uint16_t *, u) {
|
||||
if (!maxptr)
|
||||
maxptr = u;
|
||||
else if (*u > *maxptr)
|
||||
maxptr = u;
|
||||
} SMARTLIST_FOREACH_END(u);
|
||||
|
||||
return maxptr ? *maxptr : dflt;
|
||||
}
|
||||
|
||||
/* The above function is only safe to call if we are sure that channel_id_t
|
||||
* and msg_type_id_t are really uint16_t. They should be so defined in
|
||||
* msgtypes.h, but let's be extra cautious.
|
||||
*/
|
||||
CTASSERT(sizeof(uint16_t) == sizeof(msg_type_id_t));
|
||||
CTASSERT(sizeof(uint16_t) == sizeof(channel_id_t));
|
||||
|
||||
/** Helper: Format an unformattable message auxiliary data item: just return a
|
||||
* copy of the string <>. */
|
||||
static char *
|
||||
@ -156,14 +160,14 @@ dispatch_new(const dispatch_cfg_t *cfg)
|
||||
|
||||
/* Fill in the empty entries in the dispatch tables:
|
||||
* types and channels for each message. */
|
||||
SMARTLIST_FOREACH_BEGIN(cfg->type_by_msg, smartlist_t *, type) {
|
||||
SMARTLIST_FOREACH_BEGIN(cfg->type_by_msg, msg_type_id_t *, type) {
|
||||
if (d->table[type_sl_idx])
|
||||
d->table[type_sl_idx]->type = VOID_TO_ID(type);
|
||||
d->table[type_sl_idx]->type = *type;
|
||||
} SMARTLIST_FOREACH_END(type);
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(cfg->chan_by_msg, smartlist_t *, chan) {
|
||||
SMARTLIST_FOREACH_BEGIN(cfg->chan_by_msg, channel_id_t *, chan) {
|
||||
if (d->table[chan_sl_idx])
|
||||
d->table[chan_sl_idx]->channel = VOID_TO_ID(chan);
|
||||
d->table[chan_sl_idx]->channel = *chan;
|
||||
} SMARTLIST_FOREACH_END(chan);
|
||||
|
||||
return d;
|
||||
|
Loading…
Reference in New Issue
Block a user