From 92585898fb369c79e7f711465e5934ff4c1879f9 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Mon, 25 Nov 2024 18:23:39 +0900 Subject: [PATCH] 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.) --- ext/socket/ipsocket.c | 22 ++++------------------ ext/socket/raddrinfo.c | 1 - ext/socket/rubysocket.h | 20 +++++++++++--------- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c index 1cba38bd75..9ad24f42b9 100644 --- a/ext/socket/ipsocket.c +++ b/ext/socket/ipsocket.c @@ -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]; diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index e18e7ca699..b5926d2e71 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -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; } diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h index 9e2d7d66e3..3b62dd370a 100644 --- a/ext/socket/rubysocket.h +++ b/ext/socket/rubysocket.h @@ -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);