Package: freerdp3-sdl
Version: 3.15.0+dfsg-2.1+deb13u3
Severity: important
Tags: patch upstream fixed-upstream

Version: freerdp3-sdl 3.15.0+dfsg-2.1+deb13u3 (trixie), libsdl3 3.2.10, 
libsdl3-ttf 3.2.2.

Description

In 3.15.0, `SdlWidget::render_text()` in 
`client/SDL/SDL3/dialogs/sdl_widget.cpp` (lines 100-101) creates a text
engine with `TTF_CreateRendererTextEngine()` but frees it with 
`TTF_DestroySurfaceTextEngine()`. These are two
different engine types, so the renderer engine and its glyph atlas texture are 
never freed. `render_text()` runs for
every widget on every redraw of the NLA credentials dialog, so the memory grows 
with each key press and mouse move.

Impact

On our diskless thin clients with limited RAM, the machine freezes after a few 
characters are typed in the credentials
dialog. We measured the following with a software renderer 
(`SDL_RENDER_DRIVER=software`):

- RSS is 499 MB at start, then grows by about 154 MB per key press and 36 MB 
per mouse move.
- A held key with auto-repeat adds about 3.9 GB in 2 s.

Upstream status

Upstream fixed this in the 3.16.0 release:

- 34232d0972 "[client,sdl] refactor sdl dialogs" (2025-05-06) moved the engine 
into a `SdlWidget` member that is
  created once per widget.
- cf36d437b0 "[client,sdl] fix leak with SDL_ttf usage" (2025-05-09) changed 
that member's deleter to
  `TTF_DestroyRendererTextEngine`.

cf36d437b0 does not apply to 3.15.0 on its own because it relies on that 
refactoring. The minimal equivalent for 3.15.0
is the same one-line deleter fix, applied in `render_text()`:

```diff
--- a/client/SDL/SDL3/dialogs/sdl_widget.cpp
+++ b/client/SDL/SDL3/dialogs/sdl_widget.cpp
@@ -97,8 +97,8 @@
                return nullptr;
        }

-       std::unique_ptr<TTF_TextEngine, 
decltype(&TTF_DestroySurfaceTextEngine)> engine(
-           TTF_CreateRendererTextEngine(renderer), 
TTF_DestroySurfaceTextEngine);
+       std::unique_ptr<TTF_TextEngine, 
decltype(&TTF_DestroyRendererTextEngine)> engine(
+           TTF_CreateRendererTextEngine(renderer), 
TTF_DestroyRendererTextEngine);
        if (!engine)
        {
                widget_log_error(false, "TTF_CreateRendererTextEngine");
```

Testing

With this patch applied to 3.15.0, RSS stayed at 62 MB at start and did not 
grow with 12 key
presses, 6 mouse moves or a 3 s held key. A standalone SDL3/SDL3_ttf test 
program that repeats these calls each frame
shows the same behaviour: RSS goes from 121 to 607 MB over 120 redraws with 
`TTF_DestroySurfaceTextEngine`, and stays
at about 126 MB with `TTF_DestroyRendererTextEngine`.

Could this go into a trixie point release (or a deb13uN security/stable update)?

Upstream issue for a remaining minor case: 
https://github.com/FreeRDP/FreeRDP/issues/13858

Reply via email to