From 7a89e47334b8c2f259e9cb0d7c7aa9c8b2926674 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 28 May 2025 09:43:39 +0200 Subject: [PATCH] [core,transport] only free userContext if userContextSize > 0 --- include/freerdp/transport_io.h | 6 +++++- libfreerdp/core/transport.c | 22 +++++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/include/freerdp/transport_io.h b/include/freerdp/transport_io.h index fd13dc1b1..6a5726ebf 100644 --- a/include/freerdp/transport_io.h +++ b/include/freerdp/transport_io.h @@ -148,8 +148,12 @@ extern "C" /** * @brief Create new transport layer instance + * + * @bug Before 3.16.0 the rdpTransportLayer::userContext was freed unconditionally + * * @param transport A pointer to the transport instance to use - * @param contextSize The size of the context to use + * @param contextSize The size of the context to use. If \b 0 no rdpTransportLayer::userContext + * is allocated or freed. * @return A new transport layer instance or \b NULL in case of failure * @since version 3.9.0 */ diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 2ca146f65..21523f2ae 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -97,6 +97,12 @@ struct rdp_transport BOOL earlyUserAuth; }; +typedef struct +{ + rdpTransportLayer pub; + void* userContextShadowPtr; +} rdpTransportLayerInt; + static void transport_ssl_cb(const SSL* ssl, int where, int ret) { if (where & SSL_CB_ALERT) @@ -1911,31 +1917,33 @@ void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode) rdpTransportLayer* transport_layer_new(WINPR_ATTR_UNUSED rdpTransport* transport, size_t contextSize) { - rdpTransportLayer* layer = (rdpTransportLayer*)calloc(1, sizeof(rdpTransportLayer)); + rdpTransportLayerInt* layer = (rdpTransportLayerInt*)calloc(1, sizeof(rdpTransportLayerInt)); if (!layer) return NULL; if (contextSize) { - layer->userContext = calloc(1, contextSize); - if (!layer->userContext) + layer->userContextShadowPtr = calloc(1, contextSize); + if (!layer->userContextShadowPtr) { free(layer); return NULL; } } + layer->pub.userContext = layer->userContextShadowPtr; - return layer; + return &layer->pub; } void transport_layer_free(rdpTransportLayer* layer) { + rdpTransportLayerInt* intern = (rdpTransportLayerInt*)layer; if (!layer) return; - IFCALL(layer->Close, layer->userContext); - free(layer->userContext); - free(layer); + IFCALL(intern->pub.Close, intern->pub.userContext); + free(intern->userContextShadowPtr); + free(intern); } static int transport_layer_bio_write(BIO* bio, const char* buf, int size)