mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 23:53:32 +01:00
Fix segfault and logic error in remove_duplicate_orports()
This function tried to modify an array in place, but did it in a pretty confusing and complicated way. I've revised it to follow a much more straightforward approach. Fixes bug #40065.
This commit is contained in:
parent
010387e4bd
commit
fc5fe094b1
@ -186,8 +186,14 @@ describe_relay_port(const port_cfg_t *port)
|
|||||||
static void
|
static void
|
||||||
remove_duplicate_orports(smartlist_t *ports)
|
remove_duplicate_orports(smartlist_t *ports)
|
||||||
{
|
{
|
||||||
|
/* First we'll decide what to remove, then we'll remove it. */
|
||||||
|
bool *removing = tor_calloc(smartlist_len(ports), sizeof(bool));
|
||||||
|
|
||||||
for (int i = 0; i < smartlist_len(ports); ++i) {
|
for (int i = 0; i < smartlist_len(ports); ++i) {
|
||||||
port_cfg_t *current = smartlist_get(ports, i);
|
const port_cfg_t *current = smartlist_get(ports, i);
|
||||||
|
if (removing[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip non ORPorts. */
|
/* Skip non ORPorts. */
|
||||||
if (current->type != CONN_TYPE_OR_LISTENER) {
|
if (current->type != CONN_TYPE_OR_LISTENER) {
|
||||||
@ -195,26 +201,40 @@ remove_duplicate_orports(smartlist_t *ports)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < smartlist_len(ports); ++j) {
|
for (int j = 0; j < smartlist_len(ports); ++j) {
|
||||||
port_cfg_t *next = smartlist_get(ports, j);
|
const port_cfg_t *next = smartlist_get(ports, j);
|
||||||
|
|
||||||
/* Avoid comparing the same object. */
|
/* Avoid comparing the same object. */
|
||||||
if (current == next) {
|
if (current == next) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (removing[j]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
/* Same address family and same port number, we have a match. */
|
/* Same address family and same port number, we have a match. */
|
||||||
if (!current->explicit_addr && next->explicit_addr &&
|
if (!current->explicit_addr && next->explicit_addr &&
|
||||||
tor_addr_family(¤t->addr) == tor_addr_family(&next->addr) &&
|
tor_addr_family(¤t->addr) == tor_addr_family(&next->addr) &&
|
||||||
current->port == next->port) {
|
current->port == next->port) {
|
||||||
/* Remove current because next is explicitly set. */
|
/* Remove current because next is explicitly set. */
|
||||||
smartlist_del_keeporder(ports, i--);
|
removing[i] = true;
|
||||||
char *next_str = tor_strdup(describe_relay_port(next));
|
char *next_str = tor_strdup(describe_relay_port(next));
|
||||||
log_warn(LD_CONFIG, "Configuration port %s superseded by %s",
|
log_warn(LD_CONFIG, "Configuration port %s superseded by %s",
|
||||||
describe_relay_port(current), next_str);
|
describe_relay_port(current), next_str);
|
||||||
tor_free(next_str);
|
tor_free(next_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate over array in reverse order to keep indices valid. */
|
||||||
|
for (int i = smartlist_len(ports)-1; i >= 0; --i) {
|
||||||
|
tor_assert(i < smartlist_len(ports));
|
||||||
|
if (removing[i]) {
|
||||||
|
port_cfg_t *current = smartlist_get(ports, i);
|
||||||
|
smartlist_del_keeporder(ports, i);
|
||||||
port_cfg_free(current);
|
port_cfg_free(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
tor_free(removing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal
|
/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal
|
||||||
|
Loading…
Reference in New Issue
Block a user