Prevent memory leak

```
for (int i = 0; i < arg->family_size; i++) {
    arg->getaddrinfo_entries[i] = allocate_fast_fallback_getaddrinfo_entry();
    if (!(arg->getaddrinfo_entries[i])) rb_syserr_fail(errno, "calloc(3)");
```

If the allocation fails in the second interation, the memory allocated
in the first iteration would be leaked.

This change prevents the memory leak by allocating the memory in
advance.
(The struct name `fast_fallback_getaddrinfo_shared` might no longer be
good.)
This commit is contained in:
Yusuke Endoh 2024-11-25 18:23:39 +09:00
parent 6ab76a6212
commit 92585898fb
Notes: git 2024-11-25 11:19:04 +00:00
3 changed files with 15 additions and 28 deletions

View File

@ -235,31 +235,18 @@ struct fast_fallback_inetsock_arg
};
static struct fast_fallback_getaddrinfo_shared *
allocate_fast_fallback_getaddrinfo_shared(void)
allocate_fast_fallback_getaddrinfo_shared(int family_size)
{
struct fast_fallback_getaddrinfo_shared *shared;
shared = (struct fast_fallback_getaddrinfo_shared *)calloc(
1,
sizeof(struct fast_fallback_getaddrinfo_shared)
sizeof(struct fast_fallback_getaddrinfo_shared) + (family_size == 1 ? 0 : 2) * sizeof(struct fast_fallback_getaddrinfo_entry)
);
return shared;
}
static struct fast_fallback_getaddrinfo_entry *
allocate_fast_fallback_getaddrinfo_entry(void)
{
struct fast_fallback_getaddrinfo_entry *entry;
entry = (struct fast_fallback_getaddrinfo_entry *)calloc(
1,
sizeof(struct fast_fallback_getaddrinfo_entry)
);
return entry;
}
static void
allocate_fast_fallback_getaddrinfo_hints(struct addrinfo *hints, int family, int remote_addrinfo_hints, int additional_flags)
{
@ -604,7 +591,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
hostname_resolution_notifier = pipefd[1];
wait_arg.readfds = &readfds;
arg->getaddrinfo_shared = allocate_fast_fallback_getaddrinfo_shared();
arg->getaddrinfo_shared = allocate_fast_fallback_getaddrinfo_shared(arg->family_size);
if (!arg->getaddrinfo_shared) rb_syserr_fail(errno, "calloc(3)");
arg->getaddrinfo_shared->lock = calloc(1, sizeof(rb_nativethread_lock_t));
@ -659,8 +646,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
arg->getaddrinfo_shared->refcount = arg->family_size + 1;
for (int i = 0; i < arg->family_size; i++) {
arg->getaddrinfo_entries[i] = allocate_fast_fallback_getaddrinfo_entry();
if (!(arg->getaddrinfo_entries[i])) rb_syserr_fail(errno, "calloc(3)");
arg->getaddrinfo_entries[i] = &arg->getaddrinfo_shared->getaddrinfo_entries[i];
arg->getaddrinfo_entries[i]->shared = arg->getaddrinfo_shared;
struct addrinfo getaddrinfo_hints[arg->family_size];

View File

@ -3047,7 +3047,6 @@ free_fast_fallback_getaddrinfo_entry(struct fast_fallback_getaddrinfo_entry **en
freeaddrinfo((*entry)->ai);
(*entry)->ai = NULL;
}
free(*entry);
*entry = NULL;
}

View File

@ -138,6 +138,7 @@
#include "internal.h"
#include "internal/array.h"
#include "internal/compilers.h"
#include "internal/error.h"
#include "internal/gc.h"
#include "internal/io.h"
@ -426,15 +427,6 @@ char *port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr);
# define IPV4_HOSTNAME_RESOLVED '2'
# define SELECT_CANCELLED '3'
struct fast_fallback_getaddrinfo_shared
{
int wait, notify, refcount, connection_attempt_fds_size;
int cancelled;
int *connection_attempt_fds;
char *node, *service;
rb_nativethread_lock_t *lock;
};
struct fast_fallback_getaddrinfo_entry
{
int family, err, refcount;
@ -446,6 +438,16 @@ struct fast_fallback_getaddrinfo_entry
int test_ecode;
};
struct fast_fallback_getaddrinfo_shared
{
int wait, notify, refcount, connection_attempt_fds_size;
int cancelled;
int *connection_attempt_fds;
char *node, *service;
rb_nativethread_lock_t *lock;
struct fast_fallback_getaddrinfo_entry getaddrinfo_entries[FLEX_ARY_LEN];
};
int raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg);
void *do_fast_fallback_getaddrinfo(void *ptr);
void free_fast_fallback_getaddrinfo_entry(struct fast_fallback_getaddrinfo_entry **entry);