Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:freerdp3
User: [email protected]
Usertags: pu

[ Reason ]
Compared with the version currently being reviewed for trixie-pu,
there are a number of new security fixes in freerdp3 package, all
taken from the upstream, namely:

  * security fixes for client from 3.24.0:
    CVE-2026-29774 Heap-buffer-overflow in avc420_yuv_to_rgb via OOB regionRects
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-5q35-hv9x-7794
    CVE-2026-29775 Heap-buffer-overflow in bitmap_cache_put via OOB cacheId
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-h666-rfw3-jhvj
    CVE-2026-29776 Integer Underflow in update_read_cache_bitmap_order
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-c747-x4wf-cqrr
    CVE-2026-31806 Heap Buffer Overflow in nsc_process_message() via Unchecked
      SURFACE_BITS_COMMAND Bitmap Dimensions
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-rrqm-46rj-cmx2
    CVE-2026-31883 `size_t` underflow in ADPCM decoder leads to
      heap-buffer-overflow write
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-85x9-4xxp-xhm5
    CVE-2026-31885 Out-of-bounds read in ADPCM decoders due to
      missing predictor/step_index bounds checks
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-85x9-4xxp-xhm5
    CVE-2026-31884 Division-by-zero in ADPCM decoders when `nBlockAlign` is 0
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-jp7m-94ww-p56r
    CVE-2026-31897 Out-of-bounds read in `freerdp_bitmap_decompress_planar`
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-xgv6-r22m-7c9x
  * security fixes for client from 3.24.2:
    CVE-2026-33952 DoS via WINPR_ASSERT in
      rts_read_auth_verifier_no_checks (rts.c:282)
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-4v4p-9v5x-hc93
    CVE-2026-33977 DoS via WINPR_ASSERT in IMA ADPCM audio decoder (dsp.c:331)
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8f2g-3q27-6xm5
    CVE-2026-33995 double free in kerberos_AcceptSecurityContext
      and kerberos_IntitalizeSecurityContextA
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-mv25-f4p2-5mxx
    CVE-2026-33984 ClearCodec resize_vbar_entry() Heap OOB Write
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8469-2xcx-frf6
    CVE-2026-33983 Progressive Codec Quant BYTE Underflow - UB + CPU DoS
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-4gfm-4p52-h478
    CVE-2026-33985 ClearCodec Glyph Cache Count Desync - Heap OOB Read
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-x6gr-8p7h-5h85
    CVE-2026-33986 H.264 YUV Buffer Dimension Desync - Heap OOB Write
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-h6qw-wxvm-hf97
    CVE-2026-33987 Persistent Cache bmpSize Desync - Heap OOB Write
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-ff8h-p5vc-wcwc
    CVE-2026-33982 Persistent Cache Allocator Mismatch - Heap OOB Read
      https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8jm9-2925-g4v2

All these are relatively minor, but they're security issues anyway
and requires fixing.

[ Tests ]
I did run the resulting binaries (xfreerdp3 & sdl-freerdp3) to connect to
our RDP servers (and this initially revealed an additional issue which I
fixed by picking up a few more changes from the upstream).  The result works
fine.  I didn't try more aggressive testing though.  The result passes all
upstream testing too.

[ Risks ]
The update is large, touching many areas in the codebase, I had to back-port
many changes from current upstream version to the trixie version of freerdp3
package.  So there is a risk to break something.
 
This is why it'd be nice to have this release in trixie-proposed-updates
for a while.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
The changelog entry explain every change in detail.

Thanks,

/mjt

diff -Nru freerdp3-3.15.0+dfsg/debian/changelog 
freerdp3-3.15.0+dfsg/debian/changelog
--- freerdp3-3.15.0+dfsg/debian/changelog       2026-03-28 20:59:33.000000000 
+0300
+++ freerdp3-3.15.0+dfsg/debian/changelog       2026-04-03 18:45:10.000000000 
+0300
@@ -1,3 +1,72 @@
+freerdp3 (3.15.0+dfsg-2.1+deb13u2) trixie; urgency=medium
+
+  * security fixes for client from 3.24.0 (medium):
+
+    CVE-2026-29774 Heap-buffer-overflow in avc420_yuv_to_rgb via OOB 
regionRects
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-5q35-hv9x-7794
+      codec-h264-validate-rectangles-before-use-CVE-2026-29774.patch
+    CVE-2026-29775 Heap-buffer-overflow in bitmap_cache_put via OOB cacheId
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-h666-rfw3-jhvj
+      cache-bitmap-overallocate-bitmap-cache-CVE-2026-29775.patch
+    CVE-2026-29776 Integer Underflow in update_read_cache_bitmap_order
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-c747-x4wf-cqrr
+      core-order-fix-const-correctness.patch
+      core-orders-improve-input-validation-CVE-2026-29776.patch
+    CVE-2026-31806 Heap Buffer Overflow in nsc_process_message() via Unchecked
+      SURFACE_BITS_COMMAND Bitmap Dimensions
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-rrqm-46rj-cmx2
+      codec-nsc-bounds-checks-and-doxygen.patch
+      codec-nsc-log-decoder-function-parameter-issues.patch
+      codec-nsc-fix-use-of-nsc_process_message.patch
+      codec-nsc-limit-copy-area-in-nsc_process_message-CVE-2026-31806.patch
+    CVE-2026-31883 `size_t` underflow in ADPCM decoder leads to
+      heap-buffer-overflow write
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-85x9-4xxp-xhm5
+    CVE-2026-31885 Out-of-bounds read in ADPCM decoders due to
+      missing predictor/step_index bounds checks
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-85x9-4xxp-xhm5
+      codec-dsp-fix-array-bounds-checks-CVE-2026-31883-CVE-2026-31885.patch
+    CVE-2026-31884 Division-by-zero in ADPCM decoders when `nBlockAlign` is 0
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-jp7m-94ww-p56r
+      codec-dsp-add-format-checks-CVE-2026-31884.patch
+    CVE-2026-31897 Out-of-bounds read in `freerdp_bitmap_decompress_planar`
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-xgv6-r22m-7c9x
+      codec-planar-add-early-length-check-to-avoid-oob-rea-CVE-2026-31897.patch
+
+  * security fixes for client from 3.24.2 (medium):
+
+    CVE-2026-33952 DoS via WINPR_ASSERT in
+      rts_read_auth_verifier_no_checks (rts.c:282)
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-4v4p-9v5x-hc93
+      core-gateway-Check-rpcconn_common_hdr_t-auth_length--CVE-2026-33952.patch
+    CVE-2026-33977 DoS via WINPR_ASSERT in IMA ADPCM audio decoder (dsp.c:331)
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8f2g-3q27-6xm5
+      codec-dsp-fix-IMA-ADPCM-sample-clamping-CVE-2026-33977.patch
+    CVE-2026-33995 double free in kerberos_AcceptSecurityContext
+      and kerberos_IntitalizeSecurityContextA
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-mv25-f4p2-5mxx
+      winpr-sspi-Fix-context-nullptr-handling-CVE-2026-33995.patch
+    CVE-2026-33984 ClearCodec resize_vbar_entry() Heap OOB Write
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8469-2xcx-frf6
+      codec-clear-update-CLEAR_VBAR_ENTRY-size-after-alloc-CVE-2026-33984.patch
+    CVE-2026-33983 Progressive Codec Quant BYTE Underflow - UB + CPU DoS
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-4gfm-4p52-h478
+      codec-progressive-Fail-progressive_rfx_quant_sub-on--CVE-2026-33983.patch
+    CVE-2026-33985 ClearCodec Glyph Cache Count Desync - Heap OOB Read
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-x6gr-8p7h-5h85
+      codec-clear-Update-CLEAR_GLYPH_ENTRY-count-after-all-CVE-2026-33985.patch
+    CVE-2026-33986 H.264 YUV Buffer Dimension Desync - Heap OOB Write
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-h6qw-wxvm-hf97
+      codec-h264-update-H264_CONTEXT-width-height-after-al-CVE-2026-33986.patch
+    CVE-2026-33987 Persistent Cache bmpSize Desync - Heap OOB Write
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-ff8h-p5vc-wcwc
+      cache-persistent-update-PERSISTENT_CACHE_ENTRY-size--CVE-2026-33987.patch
+    CVE-2026-33982 Persistent Cache Allocator Mismatch - Heap OOB Read
+      
https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8jm9-2925-g4v2
+      cache-persist-use-winpr_aligned_calloc-CVE-2026-33982.patch
+
+ -- Michael Tokarev <[email protected]>  Fri, 03 Apr 2026 18:45:10 +0300
+
 freerdp3 (3.15.0+dfsg-2.1+deb13u1) trixie; urgency=medium
 
   * two patches from upstream (from 3.16) (Closes: #1112191):
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/cache-bitmap-overallocate-bitmap-cache-CVE-2026-29775.patch
 
freerdp3-3.15.0+dfsg/debian/patches/cache-bitmap-overallocate-bitmap-cache-CVE-2026-29775.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/cache-bitmap-overallocate-bitmap-cache-CVE-2026-29775.patch
     1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/cache-bitmap-overallocate-bitmap-cache-CVE-2026-29775.patch
     2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,31 @@
+From: Armin Novak <[email protected]>
+Date: Sat, 28 Feb 2026 11:38:55 +0100
+Subject: [cache,bitmap] overallocate bitmap cache
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/ffad58fd2b329efd81a3239e9d7e3c927b8e503f
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-h666-rfw3-jhvj
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-29775
+
+---
+ libfreerdp/cache/bitmap.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/libfreerdp/cache/bitmap.c b/libfreerdp/cache/bitmap.c
+index 96607444e..3da912a41 100644
+--- a/libfreerdp/cache/bitmap.c
++++ b/libfreerdp/cache/bitmap.c
+@@ -373,7 +373,10 @@ rdpBitmapCache* bitmap_cache_new(rdpContext* context)
+       const UINT32 BitmapCacheV2NumCells =
+           freerdp_settings_get_uint32(settings, 
FreeRDP_BitmapCacheV2NumCells);
+       bitmapCache->context = context;
+-      bitmapCache->cells = (BITMAP_V2_CELL*)calloc(BitmapCacheV2NumCells, 
sizeof(BITMAP_V2_CELL));
++
++      /* overallocate by 1. older RDP servers do send a off by 1 cache index. 
*/
++      bitmapCache->cells =
++          (BITMAP_V2_CELL*)calloc(BitmapCacheV2NumCells + 1ull, 
sizeof(BITMAP_V2_CELL));
+ 
+       if (!bitmapCache->cells)
+               goto fail;
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/cache-persist-use-winpr_aligned_calloc-CVE-2026-33982.patch
 
freerdp3-3.15.0+dfsg/debian/patches/cache-persist-use-winpr_aligned_calloc-CVE-2026-33982.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/cache-persist-use-winpr_aligned_calloc-CVE-2026-33982.patch
     1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/cache-persist-use-winpr_aligned_calloc-CVE-2026-33982.patch
     2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,46 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 09:57:19 +0100
+Subject: [cache,persist] use winpr_aligned_calloc
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/a48dbde2c8a5b8b70a9d1c045d969a71afd6284c
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8jm9-2925-g4v2
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33982
+
+Consistently use winpr_aligned_* family for allocating/freeing the
+buffers.
+---
+ libfreerdp/cache/persistent.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/libfreerdp/cache/persistent.c b/libfreerdp/cache/persistent.c
+--- a/libfreerdp/cache/persistent.c
++++ b/libfreerdp/cache/persistent.c
+@@ -39,6 +39,7 @@ struct rdp_persistent_cache
+       size_t bmpSize;
+ };
+ 
++static const size_t PERSIST_ALIGN = 32;
+ static const char sig_str[] = "RDP8bmp";
+ 
+ int persistent_cache_get_version(rdpPersistentCache* persistent)
+@@ -155,7 +156,7 @@ static int 
persistent_cache_read_entry_v3(rdpPersistentCache* persistent,
+       {
+               persistent->bmpSize = size;
+               BYTE* bmpData = 
(BYTE*)winpr_aligned_recalloc(persistent->bmpData, persistent->bmpSize,
+-                                                            sizeof(BYTE), 32);
++                                                            sizeof(BYTE), 
PERSIST_ALIGN);
+ 
+               if (!bmpData)
+                       return -1;
+@@ -350,7 +351,7 @@ rdpPersistentCache* persistent_cache_new(void)
+               return NULL;
+ 
+       persistent->bmpSize = 0x4000;
+-      persistent->bmpData = calloc(1, persistent->bmpSize);
++      persistent->bmpData = winpr_aligned_calloc(1, persistent->bmpSize, 
PERSIST_ALIGN);
+ 
+       if (!persistent->bmpData)
+       {
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/cache-persistent-update-PERSISTENT_CACHE_ENTRY-size--CVE-2026-33987.patch
 
freerdp3-3.15.0+dfsg/debian/patches/cache-persistent-update-PERSISTENT_CACHE_ENTRY-size--CVE-2026-33987.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/cache-persistent-update-PERSISTENT_CACHE_ENTRY-size--CVE-2026-33987.patch
       1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/cache-persistent-update-PERSISTENT_CACHE_ENTRY-size--CVE-2026-33987.patch
       2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,52 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 09:41:17 +0100
+Subject: [cache,persistent] update PERSISTENT_CACHE_ENTRY::size after
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/1a890eb43492b5eb707cb3dd6fc908f696e8fc1c
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-ff8h-p5vc-wcwc
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33987
+ realloc
+
+Avoid invalid PERSISTENT_CACHE_ENTRY::size values in case realloc fails.
+---
+ libfreerdp/cache/persistent.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/libfreerdp/cache/persistent.c b/libfreerdp/cache/persistent.c
+--- a/libfreerdp/cache/persistent.c
++++ b/libfreerdp/cache/persistent.c
+@@ -36,7 +36,7 @@ struct rdp_persistent_cache
+       int count;
+       char* filename;
+       BYTE* bmpData;
+-      UINT32 bmpSize;
++      size_t bmpSize;
+ };
+ 
+ static const char sig_str[] = "RDP8bmp";
+@@ -149,12 +149,11 @@ static int 
persistent_cache_read_entry_v3(rdpPersistentCache* persistent,
+       const UINT64 size = 4ull * entry3.width * entry3.height;
+       if (size > UINT32_MAX)
+               return -1;
+-      entry->size = (UINT32)size;
+       entry->flags = 0;
+ 
+-      if (entry->size > persistent->bmpSize)
++      if (size > persistent->bmpSize)
+       {
+-              persistent->bmpSize = entry->size;
++              persistent->bmpSize = size;
+               BYTE* bmpData = 
(BYTE*)winpr_aligned_recalloc(persistent->bmpData, persistent->bmpSize,
+                                                             sizeof(BYTE), 32);
+ 
+@@ -163,6 +162,7 @@ static int 
persistent_cache_read_entry_v3(rdpPersistentCache* persistent,
+ 
+               persistent->bmpData = bmpData;
+       }
++      entry->size = WINPR_ASSERTING_INT_CAST(UINT32, size);
+ 
+       entry->data = persistent->bmpData;
+ 
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-clear-Update-CLEAR_GLYPH_ENTRY-count-after-all-CVE-2026-33985.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-clear-Update-CLEAR_GLYPH_ENTRY-count-after-all-CVE-2026-33985.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-clear-Update-CLEAR_GLYPH_ENTRY-count-after-all-CVE-2026-33985.patch
       1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-clear-Update-CLEAR_GLYPH_ENTRY-count-after-all-CVE-2026-33985.patch
       2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,56 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 09:53:38 +0100
+Subject: [codec,clear] Update CLEAR_GLYPH_ENTRY::count after alloc
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/c49d1ad43b8c7b32794d0250f2623c2dccd7ef25
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-x6gr-8p7h-5h85
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33985
+
+Ensure the value is always properly related to an existing buffer.
+---
+ libfreerdp/codec/clear.c | 22 ++++++++++++++++------
+ 1 file changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
+--- a/libfreerdp/codec/clear.c
++++ b/libfreerdp/codec/clear.c
+@@ -979,20 +979,30 @@ static BOOL clear_decompress_glyph_data(CLEAR_CONTEXT* 
WINPR_RESTRICT clear,
+       {
+               const UINT32 bpp = FreeRDPGetBytesPerPixel(clear->format);
+               CLEAR_GLYPH_ENTRY* glyphEntry = 
&(clear->GlyphCache[glyphIndex]);
+-              glyphEntry->count = nWidth * nHeight;
++              const size_t count = 1ull * nWidth * nHeight;
++              const size_t hlimit = SIZE_MAX / ((nWidth > 0) ? nWidth : 1);
++              if ((nWidth == 0) || (nHeight == 0) || (hlimit < nHeight))
++              {
++                      const char* exceeded = (hlimit < nHeight) ? "within" : 
"outside";
++                      WLog_ERR(TAG,
++                               "CLEARCODEC_FLAG_GLYPH_INDEX: nWidth=%" PRIu32 
", nHeight=%" PRIu32
++                               ", nWidth * nHeight is %s allowed range",
++                               nWidth, nHeight, exceeded);
++                      return FALSE;
++              }
+ 
+-              if (glyphEntry->count > glyphEntry->size)
++              if (count > glyphEntry->size)
+               {
+-                      BYTE* tmp =
+-                          winpr_aligned_recalloc(glyphEntry->pixels, 
glyphEntry->count, 1ull * bpp, 32);
++                      BYTE* tmp = winpr_aligned_recalloc(glyphEntry->pixels, 
count, 1ull * bpp, 32);
+ 
+                       if (!tmp)
+                       {
+-                              WLog_ERR(TAG, "glyphEntry->pixels 
winpr_aligned_recalloc %" PRIu32 " failed!",
+-                                       glyphEntry->count * bpp);
++                              WLog_ERR(TAG, "glyphEntry->pixels 
winpr_aligned_recalloc %" PRIuz " failed!",
++                                       count * bpp);
+                               return FALSE;
+                       }
+ 
++                      glyphEntry->count = WINPR_ASSERTING_INT_CAST(UINT32, 
count);
+                       glyphEntry->size = glyphEntry->count;
+                       glyphEntry->pixels = (UINT32*)tmp;
+               }
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-clear-update-CLEAR_VBAR_ENTRY-size-after-alloc-CVE-2026-33984.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-clear-update-CLEAR_VBAR_ENTRY-size-after-alloc-CVE-2026-33984.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-clear-update-CLEAR_VBAR_ENTRY-size-after-alloc-CVE-2026-33984.patch
       1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-clear-update-CLEAR_VBAR_ENTRY-size-after-alloc-CVE-2026-33984.patch
       2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,34 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 09:48:54 +0100
+Subject: [codec,clear] update CLEAR_VBAR_ENTRY::size after alloc
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/dc7fdb165095139be779a4000199bc1706b06ad5
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8469-2xcx-frf6
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33984
+
+---
+ libfreerdp/codec/clear.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
+--- a/libfreerdp/codec/clear.c
++++ b/libfreerdp/codec/clear.c
+@@ -565,7 +565,6 @@ static BOOL resize_vbar_entry(CLEAR_CONTEXT* 
WINPR_RESTRICT clear,
+               const UINT32 oldPos = vBarEntry->size * bpp;
+               const UINT32 diffSize = (vBarEntry->count - vBarEntry->size) * 
bpp;
+ 
+-              vBarEntry->size = vBarEntry->count;
+               BYTE* tmp =
+                   (BYTE*)winpr_aligned_recalloc(vBarEntry->pixels, 
vBarEntry->count, 1ull * bpp, 32);
+ 
+@@ -578,6 +577,7 @@ static BOOL resize_vbar_entry(CLEAR_CONTEXT* 
WINPR_RESTRICT clear,
+ 
+               memset(&tmp[oldPos], 0, diffSize);
+               vBarEntry->pixels = tmp;
++              vBarEntry->size = vBarEntry->count;
+       }
+ 
+       if (!vBarEntry->pixels && vBarEntry->size)
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-add-format-checks-CVE-2026-31884.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-add-format-checks-CVE-2026-31884.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-add-format-checks-CVE-2026-31884.patch
        1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-add-format-checks-CVE-2026-31884.patch
        2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,274 @@
+From: Armin Novak <[email protected]>
+Date: Tue, 10 Mar 2026 09:57:16 +0100
+Subject: [codec,dsp] add format checks
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/03b48b3601d867afccac1cdc6081de7a275edce7
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-jp7m-94ww-p56r
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-31884
+
+To avoid issues with invalid audio format settings always check before
+use.
+
+Mjt: backport to trixie version
+---
+ libfreerdp/codec/dsp.c | 148 +++++++++++++++++++++++++++++++----------
+ 1 file changed, 112 insertions(+), 36 deletions(-)
+
+diff --git a/libfreerdp/codec/dsp.c b/libfreerdp/codec/dsp.c
+index ae5a76543..969c12ce3 100644
+--- a/libfreerdp/codec/dsp.c
++++ b/libfreerdp/codec/dsp.c
+@@ -362,11 +362,28 @@ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* 
WINPR_RESTRICT adpcm, unsigned
+       return (UINT16)d;
+ }
+ 
++static BOOL valid_ima_adpcm_format(const FREERDP_DSP_CONTEXT* WINPR_RESTRICT 
context)
++{
++      WINPR_ASSERT(context);
++      if (context->common.format.wFormatTag != WAVE_FORMAT_DVI_ADPCM)
++              return FALSE;
++      if (context->common.format.nBlockAlign <= 4ULL)
++              return FALSE;
++      if (context->common.format.nChannels < 1)
++              return FALSE;
++      if (context->common.format.wBitsPerSample == 0)
++              return FALSE;
++      return TRUE;
++}
++
+ static BOOL freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT 
context,
+                                          const BYTE* WINPR_RESTRICT src, 
size_t size,
+                                          wStream* WINPR_RESTRICT out)
+ {
+-      size_t out_size = size * 4;
++      if (!valid_ima_adpcm_format(context))
++              return FALSE;
++
++      size_t out_size = size * 4ull;
+       const UINT32 block_size = context->common.format.nBlockAlign;
+       const UINT32 channels = context->common.format.nChannels;
+ 
+@@ -518,27 +535,38 @@ static BOOL 
freerdp_dsp_encode_gsm610(FREERDP_DSP_CONTEXT* WINPR_RESTRICT contex
+ #endif
+ 
+ #if defined(WITH_LAME)
++static BOOL valid_mp3_format(const FREERDP_DSP_CONTEXT* WINPR_RESTRICT 
context)
++{
++      WINPR_ASSERT(context);
++      if (context->common.format.wFormatTag != WAVE_FORMAT_MPEGLAYER3)
++              return FALSE;
++      if (context->common.format.nChannels < 1)
++              return FALSE;
++      if (context->common.format.wBitsPerSample == 0)
++              return FALSE;
++      if (context->common.format.nSamplesPerSec == 0)
++              return FALSE;
++      return TRUE;
++}
++
+ static BOOL freerdp_dsp_decode_mp3(FREERDP_DSP_CONTEXT* WINPR_RESTRICT 
context,
+                                    const BYTE* WINPR_RESTRICT src, size_t 
size,
+                                    wStream* WINPR_RESTRICT out)
+ {
+-      int rc;
+-      short* pcm_l;
+-      short* pcm_r;
+-      size_t buffer_size;
+-
+       if (!context || !src || !out)
+               return FALSE;
+-
+-      buffer_size = 2 * context->common.format.nChannels * 
context->common.format.nSamplesPerSec;
++      if (!valid_mp3_format(context))
++              return FALSE;
++      const size_t buffer_size =
++          2 * context->common.format.nChannels * 
context->common.format.nSamplesPerSec;
+ 
+       if (!Stream_EnsureCapacity(context->common.buffer, 2 * buffer_size))
+               return FALSE;
+ 
+-      pcm_l = Stream_BufferAs(context->common.buffer, short);
+-      pcm_r = Stream_BufferAs(context->common.buffer, short) + buffer_size;
+-      rc = hip_decode(context->hip, (unsigned char*)/* API is not modifying 
content */ src, size,
+-                      pcm_l, pcm_r);
++      short* pcm_l = Stream_BufferAs(context->common.buffer, short);
++      short* pcm_r = Stream_BufferAs(context->common.buffer, short) + 
buffer_size;
++      const int rc = hip_decode(context->hip, (unsigned char*)/* API is not 
modifying content */ src,
++                                size, pcm_l, pcm_r);
+ 
+       if (rc <= 0)
+               return FALSE;
+@@ -559,13 +587,13 @@ static BOOL freerdp_dsp_encode_mp3(FREERDP_DSP_CONTEXT* 
WINPR_RESTRICT context,
+                                    const BYTE* WINPR_RESTRICT src, size_t 
size,
+                                    wStream* WINPR_RESTRICT out)
+ {
+-      size_t samples_per_channel;
+-      int rc;
+-
+       if (!context || !src || !out)
+               return FALSE;
+ 
+-      samples_per_channel =
++      if (!valid_mp3_format(context))
++              return FALSE;
++
++      size_t samples_per_channel =
+           size / context->common.format.nChannels / 
context->common.format.wBitsPerSample / 8;
+ 
+       /* Ensure worst case buffer size for mp3 stream taken from LAME header 
*/
+@@ -573,8 +601,9 @@ static BOOL freerdp_dsp_encode_mp3(FREERDP_DSP_CONTEXT* 
WINPR_RESTRICT context,
+               return FALSE;
+ 
+       samples_per_channel = size / 2 /* size of a sample */ / 
context->common.format.nChannels;
+-      rc = lame_encode_buffer_interleaved(context->lame, (short*)src, 
samples_per_channel,
+-                                          Stream_Pointer(out), 
Stream_GetRemainingCapacity(out));
++      const int rc =
++          lame_encode_buffer_interleaved(context->lame, (short*)src, 
samples_per_channel,
++                                         Stream_Pointer(out), 
Stream_GetRemainingCapacity(out));
+ 
+       if (rc < 0)
+               return FALSE;
+@@ -834,6 +863,8 @@ static BOOL 
freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT con
+                                          const BYTE* WINPR_RESTRICT src, 
size_t size,
+                                          wStream* WINPR_RESTRICT out)
+ {
++      if (!valid_ima_adpcm_format(context))
++              return FALSE;
+       if (!Stream_EnsureRemainingCapacity(out, size))
+               return FALSE;
+       if (!Stream_EnsureRemainingCapacity(context->common.buffer, size + 64))
+@@ -957,10 +988,26 @@ static INLINE INT16 
freerdp_dsp_decode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adp
+       return (INT16)presample;
+ }
+ 
++static BOOL valid_ms_adpcm_format(const FREERDP_DSP_CONTEXT* WINPR_RESTRICT 
context)
++{
++      WINPR_ASSERT(context);
++      if (context->common.format.wFormatTag != WAVE_FORMAT_ADPCM)
++              return FALSE;
++      if (context->common.format.nBlockAlign <= 4ULL)
++              return FALSE;
++      if (context->common.format.nChannels < 1)
++              return FALSE;
++      if (context->common.format.wBitsPerSample == 0)
++              return FALSE;
++      return TRUE;
++}
++
+ static BOOL freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT 
context,
+                                         const BYTE* WINPR_RESTRICT src, 
size_t size,
+                                         wStream* WINPR_RESTRICT out)
+ {
++      if (!valid_ms_adpcm_format(context))
++              return FALSE;
+       const size_t out_size = size * 4;
+       const UINT32 channels = context->common.format.nChannels;
+       const UINT32 block_size = context->common.format.nBlockAlign;
+@@ -1099,6 +1146,9 @@ static BOOL 
freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT cont
+                                         const BYTE* WINPR_RESTRICT src, 
size_t size,
+                                         wStream* WINPR_RESTRICT out)
+ {
++      if (!valid_ms_adpcm_format(context))
++              return FALSE;
++
+       const size_t step = 8 + ((context->common.format.nChannels > 1) ? 4 : 
0);
+ 
+       if (!Stream_EnsureRemainingCapacity(out, size))
+@@ -1543,21 +1593,44 @@ BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* 
WINPR_RESTRICT context,
+ 
+       context->common.format = *targetFormat;
+ 
+-      if (context->common.format.wFormatTag == WAVE_FORMAT_DVI_ADPCM)
++      switch (context->common.format.wFormatTag)
+       {
+-              size_t min_frame_data = 1ull * 
context->common.format.wBitsPerSample *
+-                                      context->common.format.nChannels * 
FramesPerPacket;
+-              size_t data_per_block =
+-                  (1ULL * context->common.format.nBlockAlign - 4ULL * 
context->common.format.nChannels) *
+-                  8ULL;
+-              size_t nb_block_per_packet = min_frame_data / data_per_block;
+-
+-              if (min_frame_data % data_per_block)
+-                      nb_block_per_packet++;
+-
+-              context->adpcm.ima.packet_size = nb_block_per_packet * 
context->common.format.nBlockAlign;
+-              Stream_EnsureCapacity(context->common.buffer, 
context->adpcm.ima.packet_size);
+-              Stream_SetPosition(context->common.buffer, 0);
++#if defined(WITH_LAME)
++              case WAVE_FORMAT_MPEGLAYER3:
++                      if (!valid_mp3_format(context))
++                              return FALSE;
++                      break;
++#endif
++              case WAVE_FORMAT_ADPCM:
++                      if (!valid_ms_adpcm_format(context))
++                              return FALSE;
++                      break;
++              case WAVE_FORMAT_DVI_ADPCM:
++              {
++                      if (!valid_ima_adpcm_format(context))
++                              return FALSE;
++                      if (FramesPerPacket == 0)
++                              return FALSE;
++
++                      const size_t min_frame_data = 1ull * 
context->common.format.wBitsPerSample *
++                                                    
context->common.format.nChannels * FramesPerPacket;
++                      const size_t data_per_block = (1ULL * 
context->common.format.nBlockAlign -
++                                                     4ULL * 
context->common.format.nChannels) *
++                                                    8ULL;
++                      size_t nb_block_per_packet = min_frame_data / 
data_per_block;
++
++                      if (min_frame_data % data_per_block)
++                              nb_block_per_packet++;
++
++                      context->adpcm.ima.packet_size =
++                          nb_block_per_packet * 
context->common.format.nBlockAlign;
++                      if (!Stream_EnsureCapacity(context->common.buffer, 
context->adpcm.ima.packet_size))
++                              return FALSE;
++                      Stream_SetPosition(context->common.buffer, 0);
++              }
++              break;
++              default:
++                      break;
+       }
+ 
+ #if defined(WITH_OPUS)
+@@ -1600,7 +1673,7 @@ BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* 
WINPR_RESTRICT context,
+ 
+       if (context->common.encoder)
+       {
+-              faacEncConfigurationPtr cfg;
++              faacEncConfigurationPtr cfg = nullptr;
+ 
+               if (context->faac)
+                       faacEncClose(context->faac);
+@@ -1617,20 +1690,23 @@ BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* 
WINPR_RESTRICT context,
+               cfg->mpegVersion = MPEG4;
+               cfg->useTns = 1;
+               cfg->bandWidth = targetFormat->nAvgBytesPerSec;
+-              faacEncSetConfiguration(context->faac, cfg);
++              const int rc = faacEncSetConfiguration(context->faac, cfg);
++              if (rc <= 0)
++                      return FALSE;
+       }
+ 
+ #endif
+ #if defined(WITH_SOXR)
+       {
+               soxr_io_spec_t iospec = soxr_io_spec(SOXR_INT16, SOXR_INT16);
+-              soxr_error_t error;
++              soxr_error_t error = nullptr;
++
+               soxr_delete(context->sox);
+               context->sox =
+                   soxr_create(context->common.format.nSamplesPerSec, 
targetFormat->nSamplesPerSec,
+                               targetFormat->nChannels, &error, &iospec, NULL, 
NULL);
+ 
+-              if (!context->sox || (error != 0))
++              if (!context->sox || (error != nullptr))
+                       return FALSE;
+       }
+ #endif
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-fix-IMA-ADPCM-sample-clamping-CVE-2026-33977.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-fix-IMA-ADPCM-sample-clamping-CVE-2026-33977.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-fix-IMA-ADPCM-sample-clamping-CVE-2026-33977.patch
    1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-fix-IMA-ADPCM-sample-clamping-CVE-2026-33977.patch
    2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,79 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 09:23:18 +0100
+Subject: [codec,dsp] fix IMA ADPCM sample clamping
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/9be3f03d94a50892fd58a9f7dee72b2313c69b47
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-8f2g-3q27-6xm5
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33977
+
+---
+ libfreerdp/codec/dsp.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/libfreerdp/codec/dsp.c b/libfreerdp/codec/dsp.c
+--- a/libfreerdp/codec/dsp.c
++++ b/libfreerdp/codec/dsp.c
+@@ -318,6 +318,17 @@ static const INT16 ima_step_size_table[] = {
+       12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 
32767
+ };
+ 
++static inline void dsp_ima_clamp_step(ADPCM* WINPR_RESTRICT adpcm, unsigned 
int channel)
++{
++      WINPR_ASSERT(adpcm);
++      if (adpcm->ima.last_step[channel] < 0)
++              adpcm->ima.last_step[channel] = 0;
++
++      const size_t size = ARRAYSIZE(ima_step_size_table);
++      if (adpcm->ima.last_step[channel] > size)
++              adpcm->ima.last_step[channel] = size;
++}
++
+ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, 
unsigned int channel,
+                                           BYTE sample)
+ {
+@@ -354,10 +365,7 @@ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* 
WINPR_RESTRICT adpcm, unsigned
+       WINPR_ASSERT(sample < ARRAYSIZE(ima_step_index_table));
+       adpcm->ima.last_step[channel] += ima_step_index_table[sample];
+ 
+-      if (adpcm->ima.last_step[channel] < 0)
+-              adpcm->ima.last_step[channel] = 0;
+-      else if (adpcm->ima.last_step[channel] > 88)
+-              adpcm->ima.last_step[channel] = 88;
++      dsp_ima_clamp_step(adpcm, channel);
+ 
+       return (UINT16)d;
+ }
+@@ -400,6 +408,9 @@ static BOOL 
freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT con
+                       context->adpcm.ima.last_sample[0] =
+                           (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) 
<< 8));
+                       context->adpcm.ima.last_step[0] = (INT16)(*(src + 2));
++
++                      dsp_ima_clamp_step(&context->adpcm, 0);
++
+                       src += 4;
+                       size -= 4;
+                       out_size -= 16;
+@@ -411,6 +422,8 @@ static BOOL 
freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT con
+                               context->adpcm.ima.last_sample[1] =
+                                   (INT16)(((UINT16)(*src)) | (((UINT16)(*(src 
+ 1))) << 8));
+                               context->adpcm.ima.last_step[1] = (INT16)(*(src 
+ 2));
++
++                              dsp_ima_clamp_step(&context->adpcm, 1);
+                               src += 4;
+                               size -= 4;
+                               out_size -= 16;
+@@ -851,10 +864,7 @@ static BYTE dsp_encode_ima_adpcm_sample(ADPCM* 
WINPR_RESTRICT adpcm, size_t chan
+       WINPR_ASSERT(enc < ARRAYSIZE(ima_step_index_table));
+       adpcm->ima.last_step[channel] += ima_step_index_table[enc];
+ 
+-      if (adpcm->ima.last_step[channel] < 0)
+-              adpcm->ima.last_step[channel] = 0;
+-      else if (adpcm->ima.last_step[channel] > 88)
+-              adpcm->ima.last_step[channel] = 88;
++      dsp_ima_clamp_step(adpcm, channel);
+ 
+       return enc;
+ }
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-fix-array-bounds-checks-CVE-2026-31883-CVE-2026-31885.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-fix-array-bounds-checks-CVE-2026-31883-CVE-2026-31885.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-fix-array-bounds-checks-CVE-2026-31883-CVE-2026-31885.patch
   1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-dsp-fix-array-bounds-checks-CVE-2026-31883-CVE-2026-31885.patch
   2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,224 @@
+From: Armin Novak <[email protected]>
+Date: Tue, 10 Mar 2026 10:21:40 +0100
+Subject: [codec,dsp] fix array bounds checks
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/83d9aedea278a74af3e490ff5eeb889c016dbb2b
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-85x9-4xxp-xhm5
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-h23r-3988-3wf3
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-31883
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-31885
+
+* assert array indices where caller value is an internal constant
+* add missing length/bounds checks
+
+Mjt: back-port to debian trixie version
+---
+ libfreerdp/codec/dsp.c | 77 +++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 68 insertions(+), 9 deletions(-)
+
+diff --git a/libfreerdp/codec/dsp.c b/libfreerdp/codec/dsp.c
+index dbd11f1b0..ae5a76543 100644
+--- a/libfreerdp/codec/dsp.c
++++ b/libfreerdp/codec/dsp.c
+@@ -321,7 +321,14 @@ static const INT16 ima_step_size_table[] = {
+ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, 
unsigned int channel,
+                                           BYTE sample)
+ {
+-      const INT32 ss = ima_step_size_table[adpcm->ima.last_step[channel]];
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_step));
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_sample));
++
++      const INT16 offset = adpcm->ima.last_step[channel];
++      WINPR_ASSERT(offset >= 0);
++      WINPR_ASSERT(offset < ARRAYSIZE(ima_step_size_table));
++
++      const INT32 ss = ima_step_size_table[offset];
+       INT32 d = (ss >> 3);
+ 
+       if (sample & 1)
+@@ -344,6 +351,7 @@ static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* 
WINPR_RESTRICT adpcm, unsigned
+               d = 32767;
+ 
+       adpcm->ima.last_sample[channel] = (INT16)d;
++      WINPR_ASSERT(sample < ARRAYSIZE(ima_step_index_table));
+       adpcm->ima.last_step[channel] += ima_step_index_table[sample];
+ 
+       if (adpcm->ima.last_step[channel] < 0)
+@@ -369,6 +377,9 @@ static BOOL 
freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT con
+       {
+               if (size % block_size == 0)
+               {
++                      if (size < 4)
++                              return FALSE;
++
+                       context->adpcm.ima.last_sample[0] =
+                           (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) 
<< 8));
+                       context->adpcm.ima.last_step[0] = (INT16)(*(src + 2));
+@@ -378,6 +389,8 @@ static BOOL 
freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT con
+ 
+                       if (channels > 1)
+                       {
++                              if (size < 4)
++                                      return FALSE;
+                               context->adpcm.ima.last_sample[1] =
+                                   (INT16)(((UINT16)(*src)) | (((UINT16)(*(src 
+ 1))) << 8));
+                               context->adpcm.ima.last_step[1] = (INT16)(*(src 
+ 2));
+@@ -389,6 +402,8 @@ static BOOL 
freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT con
+ 
+               if (channels > 1)
+               {
++                      if (size < 8)
++                              return FALSE;
+                       for (size_t i = 0; i < 8; i++)
+                       {
+                               BYTE* dst = Stream_Pointer(out);
+@@ -417,6 +432,8 @@ static BOOL 
freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT con
+               }
+               else
+               {
++                      if (size < 1)
++                              return FALSE;
+                       BYTE* dst = Stream_Pointer(out);
+                       if (!Stream_SafeSeek(out, 4))
+                               return FALSE;
+@@ -748,7 +765,14 @@ static const struct
+ 
+ static BYTE dsp_encode_ima_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, size_t 
channel, INT16 sample)
+ {
+-      INT32 ss = ima_step_size_table[adpcm->ima.last_step[channel]];
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_step));
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_sample));
++
++      const INT16 offset = adpcm->ima.last_step[channel];
++      WINPR_ASSERT(offset >= 0);
++      WINPR_ASSERT(offset < ARRAYSIZE(ima_step_size_table));
++
++      INT32 ss = ima_step_size_table[offset];
+       INT32 e = sample - adpcm->ima.last_sample[channel];
+       INT32 d = e;
+       INT32 diff = ss >> 3;
+@@ -795,6 +819,7 @@ static BYTE dsp_encode_ima_adpcm_sample(ADPCM* 
WINPR_RESTRICT adpcm, size_t chan
+               diff = 32767;
+ 
+       adpcm->ima.last_sample[channel] = (INT16)diff;
++      WINPR_ASSERT(enc < ARRAYSIZE(ima_step_index_table));
+       adpcm->ima.last_step[channel] += ima_step_index_table[enc];
+ 
+       if (adpcm->ima.last_step[channel] < 0)
+@@ -894,11 +919,22 @@ static const INT32 ms_adpcm_coeffs2[7] = { 0, -256, 0, 
64, 0, -208, -232 };
+ static INLINE INT16 freerdp_dsp_decode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT 
adpcm, BYTE sample,
+                                                        size_t channel)
+ {
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample1));
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample2));
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.delta));
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.predictor));
++
+       const INT8 nibble = (sample & 0x08 ? (INT8)sample - 16 : (INT8)sample);
++      const BYTE predictor = adpcm->ms.predictor[channel];
++      INT32 coeff1 = 0;
++      if (predictor < ARRAYSIZE(ms_adpcm_coeffs1))
++              coeff1 = ms_adpcm_coeffs1[predictor];
++
++      INT32 coeff2 = 0;
++      if (predictor < ARRAYSIZE(ms_adpcm_coeffs2))
++              coeff2 = ms_adpcm_coeffs2[predictor];
+       INT32 presample =
+-          ((adpcm->ms.sample1[channel] * 
ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) +
+-           (adpcm->ms.sample2[channel] * 
ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) /
+-          256;
++          ((adpcm->ms.sample1[channel] * coeff1) + 
(adpcm->ms.sample2[channel] * coeff2)) / 256;
+       presample += nibble * adpcm->ms.delta[channel];
+ 
+       if (presample > 32767)
+@@ -908,7 +944,12 @@ static INLINE INT16 
freerdp_dsp_decode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adp
+ 
+       adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel];
+       adpcm->ms.sample1[channel] = presample;
+-      adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * 
ms_adpcm_adaptation_table[sample] / 256;
++
++      INT32 tableval = 0;
++      if (sample < ARRAYSIZE(ms_adpcm_adaptation_table))
++              tableval = ms_adpcm_adaptation_table[sample];
++
++      adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * tableval / 256;
+ 
+       if (adpcm->ms.delta[channel] < 16)
+               adpcm->ms.delta[channel] = 16;
+@@ -933,6 +974,9 @@ static BOOL 
freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT cont
+               {
+                       if (channels > 1)
+                       {
++                              if (size < 14)
++                                      return FALSE;
++
+                               context->adpcm.ms.predictor[0] = *src++;
+                               context->adpcm.ms.predictor[1] = *src++;
+                               context->adpcm.ms.delta[0] = read_int16(src);
+@@ -955,6 +999,9 @@ static BOOL 
freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT cont
+                       }
+                       else
+                       {
++                              if (size < 7)
++                                      return FALSE;
++
+                               context->adpcm.ms.predictor[0] = *src++;
+                               context->adpcm.ms.delta[0] = read_int16(src);
+                               src += 2;
+@@ -971,6 +1018,8 @@ static BOOL 
freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT cont
+               if (channels > 1)
+               {
+                       {
++                              if (size < 1)
++                                      return FALSE;
+                               const BYTE sample = *src++;
+                               size--;
+                               Stream_Write_INT16(
+@@ -979,6 +1028,8 @@ static BOOL 
freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT cont
+                                   out, 
freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1));
+                       }
+                       {
++                              if (size < 1)
++                                      return FALSE;
+                               const BYTE sample = *src++;
+                               size--;
+                               Stream_Write_INT16(
+@@ -989,6 +1040,8 @@ static BOOL 
freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT cont
+               }
+               else
+               {
++                      if (size < 1)
++                              return FALSE;
+                       const BYTE sample = *src++;
+                       size--;
+                       Stream_Write_INT16(out,
+@@ -1002,8 +1055,13 @@ static BOOL 
freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT cont
+ }
+ 
+ static BYTE freerdp_dsp_encode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, 
INT32 sample,
+-                                               int channel)
++                                               size_t channel)
+ {
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample1));
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample2));
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.delta));
++      WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.predictor));
++
+       INT32 presample =
+           ((adpcm->ms.sample1[channel] * 
ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) +
+            (adpcm->ms.sample2[channel] * 
ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) /
+@@ -1027,8 +1085,9 @@ static BYTE freerdp_dsp_encode_ms_adpcm_sample(ADPCM* 
WINPR_RESTRICT adpcm, INT3
+ 
+       adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel];
+       adpcm->ms.sample1[channel] = presample;
+-      adpcm->ms.delta[channel] =
+-          adpcm->ms.delta[channel] * 
ms_adpcm_adaptation_table[(((BYTE)errordelta) & 0x0F)] / 256;
++      const size_t offset = (((BYTE)errordelta) & 0x0F);
++      WINPR_ASSERT(offset < ARRAYSIZE(ms_adpcm_adaptation_table));
++      adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * 
ms_adpcm_adaptation_table[offset] / 256;
+ 
+       if (adpcm->ms.delta[channel] < 16)
+               adpcm->ms.delta[channel] = 16;
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-h264-update-H264_CONTEXT-width-height-after-al-CVE-2026-33986.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-h264-update-H264_CONTEXT-width-height-after-al-CVE-2026-33986.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-h264-update-H264_CONTEXT-width-height-after-al-CVE-2026-33986.patch
       1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-h264-update-H264_CONTEXT-width-height-after-al-CVE-2026-33986.patch
       2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,39 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 09:45:56 +0100
+Subject: [codec,h264] update H264_CONTEXT::width,height after alloc
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/f6e43e208958140074ae9bb93cd0c9045a371c77
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-h6qw-wxvm-hf97
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33986
+
+Ensure the width/height values are only updated after the buffers were
+successfully allocated.
+---
+ libfreerdp/codec/h264.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c
+--- a/libfreerdp/codec/h264.c
++++ b/libfreerdp/codec/h264.c
+@@ -83,9 +83,6 @@ static BOOL yuv_ensure_buffer(H264_CONTEXT* h264, UINT32 
stride, UINT32 width, U
+                       h264->iStride[2] = (stride + 1) / 2;
+               }
+ 
+-              h264->width = width;
+-              h264->height = height;
+-
+               for (size_t x = 0; x < nPlanes; x++)
+               {
+                       BYTE* tmp1 = winpr_aligned_recalloc(h264->pYUVData[x], 
h264->iStride[x], pheight, 16);
+@@ -98,6 +95,8 @@ static BOOL yuv_ensure_buffer(H264_CONTEXT* h264, UINT32 
stride, UINT32 width, U
+                       if (!tmp1 || !tmp2)
+                               return FALSE;
+               }
++              h264->width = width;
++              h264->height = height;
+       }
+ 
+       return TRUE;
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-h264-validate-rectangles-before-use-CVE-2026-29774.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-h264-validate-rectangles-before-use-CVE-2026-29774.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-h264-validate-rectangles-before-use-CVE-2026-29774.patch
  1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-h264-validate-rectangles-before-use-CVE-2026-29774.patch
  2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,78 @@
+From: Armin Novak <[email protected]>
+Date: Sat, 28 Feb 2026 11:38:23 +0100
+Subject: [codec,h264] validate rectangles before use
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/6482b7a92fff3959582cef052d1967ad6bde3738
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-5q35-hv9x-7794
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-29774
+
+---
+ libfreerdp/codec/h264.c | 38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c
+index 4c09503f8..434d0cfa7 100644
+--- a/libfreerdp/codec/h264.c
++++ b/libfreerdp/codec/h264.c
+@@ -108,6 +108,36 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 
stride, UINT32 width, UINT3
+       return yuv_ensure_buffer(h264, stride, width, height);
+ }
+ 
++static BOOL isRectValid(UINT32 width, UINT32 height, const RECTANGLE_16* rect)
++{
++      WINPR_ASSERT(rect);
++      if (rect->left > width)
++              return FALSE;
++      if (rect->right > width)
++              return FALSE;
++      if (rect->left >= rect->right)
++              return FALSE;
++      if (rect->top > height)
++              return FALSE;
++      if (rect->bottom > height)
++              return FALSE;
++      if (rect->top >= rect->bottom)
++              return FALSE;
++      return TRUE;
++}
++
++static BOOL areRectsValid(UINT32 width, UINT32 height, const RECTANGLE_16* 
rects, UINT32 count)
++{
++      WINPR_ASSERT(rects || (count == 0));
++      for (size_t x = 0; x < count; x++)
++      {
++              const RECTANGLE_16* rect = &rects[x];
++              if (!isRectValid(width, height, rect))
++                      return FALSE;
++      }
++      return TRUE;
++}
++
+ INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 
SrcSize, BYTE* pDstData,
+                         DWORD DstFormat, UINT32 nDstStep, WINPR_ATTR_UNUSED 
UINT32 nDstWidth,
+                         WINPR_ATTR_UNUSED UINT32 nDstHeight, const 
RECTANGLE_16* regionRects,
+@@ -119,6 +149,9 @@ INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* 
pSrcData, UINT32 SrcSize
+       if (!h264 || h264->Compressor)
+               return -1001;
+ 
++      if (!areRectsValid(nDstWidth, nDstHeight, regionRects, numRegionRects))
++              return -1013;
++
+       status = h264->subsystem->Decompress(h264, pSrcData, SrcSize);
+ 
+       if (status == 0)
+@@ -569,6 +602,11 @@ INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, 
const RECTANGLE_16* regionR
+       if (!h264 || !regionRects || !pSrcData || !pDstData || h264->Compressor)
+               return -1001;
+ 
++      if (!areRectsValid(nDstWidth, nDstHeight, regionRects, numRegionRects))
++              return -1013;
++      if (!areRectsValid(nDstWidth, nDstHeight, auxRegionRects, 
numAuxRegionRect))
++              return -1014;
++
+       switch (op)
+       {
+               case 0: /* YUV420 in stream 1
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-bounds-checks-and-doxygen.patch 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-bounds-checks-and-doxygen.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-bounds-checks-and-doxygen.patch   
    1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-bounds-checks-and-doxygen.patch   
    2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,86 @@
+From: Armin Novak <[email protected]>
+Date: Sun, 15 Feb 2026 19:32:38 +0100
+Subject: [codec,nsc] bounds checks and doxygen
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/f4d74c33fd58e9e9e4e52d75b0d1255af8fa4b53
+Forwarded: not-needed
+Comment: preparation for CVE-2026-31806 fix
+
+* Improve doxygen for nsc_process_message
+* Improve bounds checks for nsc_process_message
+---
+ include/freerdp/codec/nsc.h | 22 ++++++++++++++++++++++
+ libfreerdp/codec/nsc.c      | 12 +++++++++---
+ 2 files changed, 31 insertions(+), 3 deletions(-)
+
+diff --git a/include/freerdp/codec/nsc.h b/include/freerdp/codec/nsc.h
+--- a/include/freerdp/codec/nsc.h
++++ b/include/freerdp/codec/nsc.h
+@@ -53,11 +53,33 @@ extern "C"
+       FREERDP_API BOOL nsc_context_set_parameters(NSC_CONTEXT* WINPR_RESTRICT 
context,
+                                                   NSC_PARAMETER what, UINT32 
value);
+ 
++      /** @brief decode a NSC message
++       *
++       *  @param context The context to work on
++       *  @param bpp The bit depth of the data
++       *  @param width The width in pixels of the NSC surface
++       *  @param height The height in pixels of the NSC surface
++       *  @param data The data to decode
++       *  @param length The length of \ref data in bytes
++       *  @param pDstData The destination buffer. Must be at least \n 
nDstStride * nHeight in size.
++       *  @param DstFormat The color format of the destination
++       *  @param nDstStride The number of bytes per destination buffer line. 
Must be larger than
++       * bytes(DstFormat) * nWidth or \0 (in which case it is set to former 
minimum bound)
++       *  @param nXDst The X offset in the destination buffer in pixels
++       *  @param nYDst The Y offset in the destination buffer in pixels
++       *  @param nWidth The width of the destination buffer in pixels
++       *  @param nHeight The height of the destination buffer in pixels
++       *  @param flip Image flipping flags FREERDP_FLIP_NONE et al passed on 
to \ref
++       * freerdp_image_copy
++       *
++       *  @return \b TRUE in case of success, \b FALSE for any error. Check 
WLog for details.
++       */
+       FREERDP_API BOOL nsc_process_message(NSC_CONTEXT* WINPR_RESTRICT 
context, UINT16 bpp,
+                                            UINT32 width, UINT32 height, const 
BYTE* data,
+                                            UINT32 length, BYTE* 
WINPR_RESTRICT pDstData,
+                                            UINT32 DstFormat, UINT32 
nDstStride, UINT32 nXDst,
+                                            UINT32 nYDst, UINT32 nWidth, 
UINT32 nHeight, UINT32 flip);
++
+       FREERDP_API BOOL nsc_compose_message(NSC_CONTEXT* WINPR_RESTRICT 
context,
+                                            wStream* WINPR_RESTRICT s,
+                                            const BYTE* WINPR_RESTRICT 
bmpdata, UINT32 width,
+diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
+--- a/libfreerdp/codec/nsc.c
++++ b/libfreerdp/codec/nsc.c
+@@ -436,19 +436,25 @@ BOOL nsc_process_message(NSC_CONTEXT* WINPR_RESTRICT 
context, UINT16 bpp, UINT32
+                          UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
+                          WINPR_ATTR_UNUSED UINT32 nHeight, UINT32 flip)
+ {
+-      wStream* s = NULL;
+       wStream sbuffer = { 0 };
+       BOOL ret = 0;
+       if (!context || !data || !pDstData)
+               return FALSE;
+ 
+-      s = Stream_StaticConstInit(&sbuffer, data, length);
++      if (nXDst > nWidth)
++              return FALSE;
++      if (nYDst > nHeight)
++              return FALSE;
+ 
++      wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
+       if (!s)
+               return FALSE;
+ 
++      const UINT32 minStride = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
+       if (nDstStride == 0)
+-              nDstStride = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
++              nDstStride = minStride;
++      if (nDstStride < minStride)
++              return FALSE;
+ 
+       switch (bpp)
+       {
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-fix-use-of-nsc_process_message.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-fix-use-of-nsc_process_message.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-fix-use-of-nsc_process_message.patch
  1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-fix-use-of-nsc_process_message.patch
  2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,93 @@
+From: Armin Novak <[email protected]>
+Date: Tue, 17 Feb 2026 08:38:04 +0100
+Subject: [codec,nsc] fix use of nsc_process_message
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/169971607cece48384cb94632b829bd57336af0f
+Forwarded: not-needed
+Comment: preparation for CVE-2026-31806 fix
+
+the second width/height argument should reflect the destination buffer
+pixel size
+---
+ libfreerdp/codec/clear.c | 10 ++++++----
+ libfreerdp/codec/nsc.c   | 12 +++++++-----
+ libfreerdp/gdi/gdi.c     |  5 +++--
+ 3 files changed, 16 insertions(+), 11 deletions(-)
+
+diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
+--- a/libfreerdp/codec/clear.c
++++ b/libfreerdp/codec/clear.c
+@@ -133,7 +133,8 @@ static BOOL convert_color(BYTE* WINPR_RESTRICT dst, UINT32 
nDstStep, UINT32 DstF
+ static BOOL clear_decompress_nscodec(NSC_CONTEXT* WINPR_RESTRICT nsc, UINT32 
width, UINT32 height,
+                                      wStream* WINPR_RESTRICT s, UINT32 
bitmapDataByteCount,
+                                      BYTE* WINPR_RESTRICT pDstData, UINT32 
DstFormat,
+-                                     UINT32 nDstStep, UINT32 nXDstRel, UINT32 
nYDstRel)
++                                     UINT32 nDstStep, UINT32 nXDstRel, UINT32 
nYDstRel,
++                                     UINT32 nDstWidth, UINT32 nDstHeight)
+ {
+       BOOL rc = 0;
+ 
+@@ -141,8 +142,8 @@ static BOOL clear_decompress_nscodec(NSC_CONTEXT* 
WINPR_RESTRICT nsc, UINT32 wid
+               return FALSE;
+ 
+       rc = nsc_process_message(nsc, 32, width, height, Stream_Pointer(s), 
bitmapDataByteCount,
+-                               pDstData, DstFormat, nDstStep, nXDstRel, 
nYDstRel, width, height,
+-                               FREERDP_FLIP_NONE);
++                               pDstData, DstFormat, nDstStep, nXDstRel, 
nYDstRel, nDstWidth,
++                               nDstHeight, FREERDP_FLIP_NONE);
+       Stream_Seek(s, bitmapDataByteCount);
+       return rc;
+ }
+@@ -532,7 +533,8 @@ static BOOL clear_decompress_subcodecs_data(CLEAR_CONTEXT* 
WINPR_RESTRICT clear,
+ 
+                       case 1: /* NSCodec */
+                               if (!clear_decompress_nscodec(clear->nsc, 
width, height, s, bitmapDataByteCount,
+-                                                            pDstData, 
DstFormat, nDstStep, nXDstRel, nYDstRel))
++                                                            pDstData, 
DstFormat, nDstStep, nXDstRel, nYDstRel,
++                                                            nDstWidth, 
nDstHeight))
+                                       return FALSE;
+ 
+                               break;
+diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
+--- a/libfreerdp/codec/nsc.c
++++ b/libfreerdp/codec/nsc.c
+@@ -433,15 +433,17 @@ BOOL nsc_context_set_parameters(NSC_CONTEXT* 
WINPR_RESTRICT context, NSC_PARAMET
+ BOOL nsc_process_message(NSC_CONTEXT* WINPR_RESTRICT context, UINT16 bpp, 
UINT32 width,
+                          UINT32 height, const BYTE* data, UINT32 length,
+                          BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, 
UINT32 nDstStride,
+-                         UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
+-                         WINPR_ATTR_UNUSED UINT32 nHeight, UINT32 flip)
++                         UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 
nHeight, UINT32 flip)
+ {
++      WINPR_ASSERT(context);
++      WINPR_ASSERT(context->priv);
++
+       wStream sbuffer = { 0 };
+       BOOL ret = 0;
+-      if (!context || !data || !pDstData)
++      if (!data || !pDstData)
+       {
+-              WLog_ERR(TAG, "Invalid argument: context=%p, data=%p, 
pDstData=%p", (void*)context,
+-                       (const void*)data, (void*)pDstData);
++              WLog_Print(context->priv->log, WLOG_ERROR, "Invalid argument: 
data=%p, pDstData=%p",
++                         (const void*)data, (void*)pDstData);
+               return FALSE;
+       }
+ 
+diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c
+--- a/libfreerdp/gdi/gdi.c
++++ b/libfreerdp/gdi/gdi.c
+@@ -1144,8 +1144,9 @@ static BOOL gdi_surface_bits(rdpContext* context, const 
SURFACE_BITS_COMMAND* cm
+                       if (!nsc_process_message(
+                               context->codecs->nsc, cmd->bmp.bpp, 
cmd->bmp.width, cmd->bmp.height,
+                               cmd->bmp.bitmapData, cmd->bmp.bitmapDataLength, 
gdi->primary_buffer, format,
+-                              gdi->stride, cmdRect.left, cmdRect.top, 
cmdRect.right - cmdRect.left,
+-                              cmdRect.bottom - cmdRect.top, 
FREERDP_FLIP_VERTICAL))
++                              gdi->stride, cmdRect.left, cmdRect.top,
++                              WINPR_ASSERTING_INT_CAST(UINT32, gdi->width),
++                              WINPR_ASSERTING_INT_CAST(UINT32, gdi->height), 
FREERDP_FLIP_VERTICAL))
+                       {
+                               WLog_ERR(TAG, "Failed to process NSCodec 
message");
+                               goto out;
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-limit-copy-area-in-nsc_process_message-CVE-2026-31806.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-limit-copy-area-in-nsc_process_message-CVE-2026-31806.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-limit-copy-area-in-nsc_process_message-CVE-2026-31806.patch
   1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-limit-copy-area-in-nsc_process_message-CVE-2026-31806.patch
   2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,38 @@
+From: Armin Novak <[email protected]>
+Date: Mon, 9 Mar 2026 08:11:19 +0100
+Subject: [codec,nsc] limit copy area in nsc_process_message
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/83d9aedea278a74af3e490ff5eeb889c016dbb2b
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-rrqm-46rj-cmx2
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-31806
+
+the rectangle decoded might not fit into the destination buffer. Limit
+width and height of the area to copy to the one fitting.
+(Mjt: backport to debian trixie version)
+---
+ libfreerdp/codec/nsc.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
+--- a/libfreerdp/codec/nsc.c
++++ b/libfreerdp/codec/nsc.c
+@@ -504,7 +504,15 @@ BOOL nsc_process_message(NSC_CONTEXT* WINPR_RESTRICT 
context, UINT16 bpp, UINT32
+                       return FALSE;
+       }
+ 
+-      if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStride, 
nXDst, nYDst, width, height,
++      uint32_t cwidth = width;
++      if (1ull * nXDst + width > nWidth)
++              cwidth = nWidth - nXDst;
++
++      uint32_t cheight = height;
++      if (1ull * nYDst + height > nHeight)
++              cheight = nHeight - nYDst;
++
++      if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStride, 
nXDst, nYDst, cwidth, cheight,
+                                          context->BitmapData, 
PIXEL_FORMAT_BGRA32, 0, 0, 0, NULL,
+                                          flip))
+               return FALSE;
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-log-decoder-function-parameter-issues.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-log-decoder-function-parameter-issues.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-log-decoder-function-parameter-issues.patch
   1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-nsc-log-decoder-function-parameter-issues.patch
   2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,54 @@
+From: Armin Novak <[email protected]>
+Date: Tue, 17 Feb 2026 08:17:33 +0100
+Subject: [codec,nsc] log decoder function parameter issues
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/caf6e7f2ecd2d71cd70719956f7d60bcacb1701b
+Forwarded: not-needed
+Comment: preparation for CVE-2026-31806 fix
+
+---
+ libfreerdp/codec/nsc.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
+--- a/libfreerdp/codec/nsc.c
++++ b/libfreerdp/codec/nsc.c
+@@ -439,12 +439,24 @@ BOOL nsc_process_message(NSC_CONTEXT* WINPR_RESTRICT 
context, UINT16 bpp, UINT32
+       wStream sbuffer = { 0 };
+       BOOL ret = 0;
+       if (!context || !data || !pDstData)
++      {
++              WLog_ERR(TAG, "Invalid argument: context=%p, data=%p, 
pDstData=%p", (void*)context,
++                       (const void*)data, (void*)pDstData);
+               return FALSE;
++      }
+ 
+       if (nXDst > nWidth)
++      {
++              WLog_Print(context->priv->log, WLOG_ERROR, "nXDst %" PRIu32 " > 
nWidth %" PRIu32, nXDst,
++                         nWidth);
+               return FALSE;
++      }
+       if (nYDst > nHeight)
++      {
++              WLog_Print(context->priv->log, WLOG_ERROR, "nYDst %" PRIu32 " > 
nHeight %" PRIu32, nYDst,
++                         nHeight);
+               return FALSE;
++      }
+ 
+       wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
+       if (!s)
+@@ -454,7 +466,11 @@ BOOL nsc_process_message(NSC_CONTEXT* WINPR_RESTRICT 
context, UINT16 bpp, UINT32
+       if (nDstStride == 0)
+               nDstStride = minStride;
+       if (nDstStride < minStride)
++      {
++              WLog_Print(context->priv->log, WLOG_ERROR,
++                         "nDstStride %" PRIu32 " < minimum stride %" PRIu32, 
nDstStride, minStride);
+               return FALSE;
++      }
+ 
+       switch (bpp)
+       {
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-planar-add-early-length-check-to-avoid-oob-rea-CVE-2026-31897.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-planar-add-early-length-check-to-avoid-oob-rea-CVE-2026-31897.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-planar-add-early-length-check-to-avoid-oob-rea-CVE-2026-31897.patch
       1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-planar-add-early-length-check-to-avoid-oob-rea-CVE-2026-31897.patch
       2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,32 @@
+From: Armin Novak <[email protected]>
+Date: Tue, 10 Mar 2026 09:17:23 +0100
+Subject: [codec,planar] add early length check to avoid oob read
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/cd27c8faca0eeb0d4309cc5837dfdf3c42eba4e7
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-xgv6-r22m-7c9x
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-31897
+
+Mjt: adjust for debian trixie version
+---
+ libfreerdp/codec/planar.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c
+index 6e2246040..190ad43ca 100644
+--- a/libfreerdp/codec/planar.c
++++ b/libfreerdp/codec/planar.c
+@@ -718,9 +718,9 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* 
WINPR_RESTRICT planar,
+ 
+       const BYTE* srcp = pSrcData;
+ 
+-      if (!pSrcData)
++      if (!pSrcData || (SrcSize < 1))
+       {
+-              WLog_ERR(TAG, "Invalid argument pSrcData=NULL");
++              WLog_ERR(TAG, "Invalid argument pSrcData=%p [size=%" PRIu32 
"]", pSrcData, SrcSize);
+               return FALSE;
+       }
+ 
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/codec-progressive-Fail-progressive_rfx_quant_sub-on--CVE-2026-33983.patch
 
freerdp3-3.15.0+dfsg/debian/patches/codec-progressive-Fail-progressive_rfx_quant_sub-on--CVE-2026-33983.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/codec-progressive-Fail-progressive_rfx_quant_sub-on--CVE-2026-33983.patch
       1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/codec-progressive-Fail-progressive_rfx_quant_sub-on--CVE-2026-33983.patch
       2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,88 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 10:03:56 +0100
+Subject: [codec,progressive] Fail progressive_rfx_quant_sub on invalid values
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/78188ab479c8e6eb9ba2475b3732c76b4bbe5425
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-4gfm-4p52-h478
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33983
+Comment: mjt: back-port to the debian trixie version
+
+---
+ libfreerdp/codec/progressive.c | 41 +++++++++++++++++++++++++++++++---
+ 1 file changed, 38 insertions(+), 3 deletions(-)
+
+diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c
+--- a/libfreerdp/codec/progressive.c
++++ b/libfreerdp/codec/progressive.c
+@@ -108,20 +108,51 @@ static INLINE void 
progressive_rfx_quant_lsub(RFX_COMPONENT_CODEC_QUANT* WINPR_R
+       q->LL3 -= val; /* LL3 */
+ }
+ 
+-static INLINE void progressive_rfx_quant_sub(const RFX_COMPONENT_CODEC_QUANT* 
WINPR_RESTRICT q1,
++static INLINE BOOL progressive_rfx_quant_sub(const RFX_COMPONENT_CODEC_QUANT* 
WINPR_RESTRICT q1,
+                                              const RFX_COMPONENT_CODEC_QUANT* 
WINPR_RESTRICT q2,
+                                              RFX_COMPONENT_CODEC_QUANT* dst)
+ {
++      if (q1->HH1 < q2->HL1)
++              return FALSE;
+       dst->HL1 = q1->HL1 - q2->HL1; /* HL1 */
++
++      if (q1->LH1 < q2->LH1)
++              return FALSE;
+       dst->LH1 = q1->LH1 - q2->LH1; /* LH1 */
++
++      if (q1->HH1 < q2->HH1)
++              return FALSE;
+       dst->HH1 = q1->HH1 - q2->HH1; /* HH1 */
++
++      if (q1->HL2 < q2->HL2)
++              return FALSE;
+       dst->HL2 = q1->HL2 - q2->HL2; /* HL2 */
++
++      if (q1->LH2 < q2->LH2)
++              return FALSE;
+       dst->LH2 = q1->LH2 - q2->LH2; /* LH2 */
++
++      if (q1->HH2 < q2->HH2)
++              return FALSE;
+       dst->HH2 = q1->HH2 - q2->HH2; /* HH2 */
++
++      if (q1->HL3 < q2->HL3)
++              return FALSE;
+       dst->HL3 = q1->HL3 - q2->HL3; /* HL3 */
++
++      if (q1->LH3 < q2->LH3)
++              return FALSE;
+       dst->LH3 = q1->LH3 - q2->LH3; /* LH3 */
++
++      if (q1->HH3 < q2->HH3)
++              return FALSE;
+       dst->HH3 = q1->HH3 - q2->HH3; /* HH3 */
++
++      if (q1->LL3 < q2->LL3)
++              return FALSE;
+       dst->LL3 = q1->LL3 - q2->LL3; /* LL3 */
++
++      return TRUE;
+ }
+ 
+ static INLINE BOOL
+@@ -1360,9 +1392,12 @@ 
progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* WINPR_RESTRICT progress
+       progressive_rfx_quant_add(quantY, quantProgY, &yBitPos);
+       progressive_rfx_quant_add(quantCb, quantProgCb, &cbBitPos);
+       progressive_rfx_quant_add(quantCr, quantProgCr, &crBitPos);
+-      progressive_rfx_quant_sub(&(tile->yBitPos), &yBitPos, &yNumBits);
+-      progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, &cbNumBits);
+-      progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, &crNumBits);
++      if (!progressive_rfx_quant_sub(&(tile->yBitPos), &yBitPos, &yNumBits))
++              goto fail;
++      if (!progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, 
&cbNumBits))
++              goto fail;
++      if (!progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, 
&crNumBits))
++              goto fail;
+       progressive_rfx_quant_add(quantY, quantProgY, &shiftY);
+       progressive_rfx_quant_lsub(&shiftY, 1); /* -6 + 5 = -1 */
+       progressive_rfx_quant_add(quantCb, quantProgCb, &shiftCb);
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/core-gateway-Check-rpcconn_common_hdr_t-auth_length--CVE-2026-33952.patch
 
freerdp3-3.15.0+dfsg/debian/patches/core-gateway-Check-rpcconn_common_hdr_t-auth_length--CVE-2026-33952.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/core-gateway-Check-rpcconn_common_hdr_t-auth_length--CVE-2026-33952.patch
       1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/core-gateway-Check-rpcconn_common_hdr_t-auth_length--CVE-2026-33952.patch
       2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,37 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 09:04:43 +0100
+Subject: [core,gateway] Check rpcconn_common_hdr_t::auth_length is valid
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/4ac0b6467d371a1ad47c1f751c5b305e4c068adb
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-4v4p-9v5x-hc93
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33952
+Comment: mjt: backport to debian trixie version
+
+Do sanity checks for rpcconn_common_hdr_t::auth_length read from
+network, abort if the value is out of range.
+---
+ libfreerdp/core/gateway/rts.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c
+--- a/libfreerdp/core/gateway/rts.c
++++ b/libfreerdp/core/gateway/rts.c
+@@ -254,6 +254,15 @@ BOOL rts_read_common_pdu_header(wStream* s, 
rpcconn_common_hdr_t* header, BOOL i
+                                 header->frag_length, 
sizeof(rpcconn_common_hdr_t));
+               return FALSE;
+       }
++      if (header->auth_length > header->frag_length - 8ull)
++      {
++              if (!ignoreErrors)
++                      WLog_WARN(TAG,
++                                "Invalid header->auth_length(%" PRIu16 ") > 
header->frag_length(%" PRIu16
++                                ") - 8ull",
++                                header->frag_length, header->auth_length);
++              return FALSE;
++      }
+ 
+       if (!ignoreErrors)
+       {
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/core-order-fix-const-correctness.patch 
freerdp3-3.15.0+dfsg/debian/patches/core-order-fix-const-correctness.patch
--- freerdp3-3.15.0+dfsg/debian/patches/core-order-fix-const-correctness.patch  
1970-01-01 03:00:00.000000000 +0300
+++ freerdp3-3.15.0+dfsg/debian/patches/core-order-fix-const-correctness.patch  
2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,33 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 23 Apr 2025 10:08:58 +0200
+Subject: [core,order] fix const correctness
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/b8f5b9c719c269010caf6dbd5929cef684e154b4
+Forwarded: not-needed
+Comment: preparation for CVE-2026-29776 fix
+
+
+diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c
+index 3085765ec..c27b474ae 100644
+--- a/libfreerdp/core/orders.c
++++ b/libfreerdp/core/orders.c
+@@ -268,7 +268,7 @@ static BYTE get_bpp_bmf(UINT32 bpp, BOOL* pValid)
+       }
+ }
+ 
+-static BOOL check_order_activated(wLog* log, rdpSettings* settings, const 
char* orderName,
++static BOOL check_order_activated(wLog* log, const rdpSettings* settings, 
const char* orderName,
+                                   BOOL condition, const char* extendedMessage)
+ {
+       if (!condition)
+@@ -407,7 +407,7 @@ static BOOL check_secondary_order_supported(wLog* log, 
rdpSettings* settings, BY
+       return check_order_activated(log, settings, orderName, condition, 
extendedMessage);
+ }
+ 
+-static BOOL check_primary_order_supported(wLog* log, rdpSettings* settings, 
UINT32 orderType,
++static BOOL check_primary_order_supported(wLog* log, const rdpSettings* 
settings, UINT32 orderType,
+                                           const char* orderName)
+ {
+       const char* extendedMessage = NULL;
+-- 
+2.47.3
+
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/core-orders-improve-input-validation-CVE-2026-29776.patch
 
freerdp3-3.15.0+dfsg/debian/patches/core-orders-improve-input-validation-CVE-2026-29776.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/core-orders-improve-input-validation-CVE-2026-29776.patch
       1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/core-orders-improve-input-validation-CVE-2026-29776.patch
       2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,30 @@
+From: Armin Novak <[email protected]>
+Date: Tue, 3 Mar 2026 13:58:09 +0100
+Subject: [core,orders] improve input validation
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/a9e0abf2eac8c2e370fa155bf1abb9d044c0ca8a
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-c747-x4wf-cqrr
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-29776
+
+check length before subtracting. Might underflow and be cought by the
+next check, but lets be strict.
+---
+ libfreerdp/core/orders.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c
+index 3085765ec..7e7e510ac 100644
+--- a/libfreerdp/core/orders.c
++++ b/libfreerdp/core/orders.c
+@@ -2371,6 +2371,8 @@ static CACHE_BITMAP_ORDER* 
update_read_cache_bitmap_order(rdpUpdate* update, wSt
+                               goto fail;
+ 
+                       Stream_Read(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 
bytes) */
++                      if (cache_bitmap->bitmapLength < 8)
++                              goto fail;
+                       cache_bitmap->bitmapLength -= 8;
+               }
+       }
+-- 
+2.47.3
+
diff -Nru freerdp3-3.15.0+dfsg/debian/patches/series 
freerdp3-3.15.0+dfsg/debian/patches/series
--- freerdp3-3.15.0+dfsg/debian/patches/series  2026-03-28 20:59:33.000000000 
+0300
+++ freerdp3-3.15.0+dfsg/debian/patches/series  2026-04-03 18:45:10.000000000 
+0300
@@ -78,3 +78,25 @@
 codec-clear-fix-missing-destination-boundary-checks-CVE-2026-26955.patch
 codec-clear-fix-destination-checks-CVE-2026-26955.patch
 codec-planar-fix-missing-destination-bounds-checks-CVE-2026-26965.patch
+# 3.24.0:
+codec-h264-validate-rectangles-before-use-CVE-2026-29774.patch
+cache-bitmap-overallocate-bitmap-cache-CVE-2026-29775.patch
+core-order-fix-const-correctness.patch
+core-orders-improve-input-validation-CVE-2026-29776.patch
+codec-nsc-bounds-checks-and-doxygen.patch
+codec-nsc-log-decoder-function-parameter-issues.patch
+codec-nsc-fix-use-of-nsc_process_message.patch
+codec-nsc-limit-copy-area-in-nsc_process_message-CVE-2026-31806.patch
+codec-dsp-fix-array-bounds-checks-CVE-2026-31883-CVE-2026-31885.patch
+codec-dsp-add-format-checks-CVE-2026-31884.patch
+codec-planar-add-early-length-check-to-avoid-oob-rea-CVE-2026-31897.patch
+# 3.24.2:
+core-gateway-Check-rpcconn_common_hdr_t-auth_length--CVE-2026-33952.patch
+codec-dsp-fix-IMA-ADPCM-sample-clamping-CVE-2026-33977.patch
+winpr-sspi-Fix-context-nullptr-handling-CVE-2026-33995.patch
+codec-clear-update-CLEAR_VBAR_ENTRY-size-after-alloc-CVE-2026-33984.patch
+codec-progressive-Fail-progressive_rfx_quant_sub-on--CVE-2026-33983.patch
+codec-clear-Update-CLEAR_GLYPH_ENTRY-count-after-all-CVE-2026-33985.patch
+codec-h264-update-H264_CONTEXT-width-height-after-al-CVE-2026-33986.patch
+cache-persistent-update-PERSISTENT_CACHE_ENTRY-size--CVE-2026-33987.patch
+cache-persist-use-winpr_aligned_calloc-CVE-2026-33982.patch
diff -Nru 
freerdp3-3.15.0+dfsg/debian/patches/winpr-sspi-Fix-context-nullptr-handling-CVE-2026-33995.patch
 
freerdp3-3.15.0+dfsg/debian/patches/winpr-sspi-Fix-context-nullptr-handling-CVE-2026-33995.patch
--- 
freerdp3-3.15.0+dfsg/debian/patches/winpr-sspi-Fix-context-nullptr-handling-CVE-2026-33995.patch
    1970-01-01 03:00:00.000000000 +0300
+++ 
freerdp3-3.15.0+dfsg/debian/patches/winpr-sspi-Fix-context-nullptr-handling-CVE-2026-33995.patch
    2026-04-03 18:45:10.000000000 +0300
@@ -0,0 +1,159 @@
+From: Armin Novak <[email protected]>
+Date: Wed, 25 Mar 2026 14:00:28 +0100
+Subject: [winpr,sspi] Fix context nullptr handling
+Origin: upstream, 
https://github.com/FreeRDP/FreeRDP/commit/8078b8af1359055972e4fb2f509f543b69169391
+Forwarded: not-needed
+Bug: https://github.com/FreeRDP/FreeRDP/security/advisories/GHSA-mv25-f4p2-5mxx
+Bug: https://security-tracker.debian.org/tracker/CVE-2026-33995
+Comment: mjt: backport to debian trixie version
+
+Unify reset of PCredHandle and PCtxtHandle in all
+DeleteSecurityContext and FreeCredentialsHandle implementations.
+
+---
+ winpr/libwinpr/sspi/CredSSP/credssp.c     |  7 +++----
+ winpr/libwinpr/sspi/Kerberos/kerberos.c   |  5 ++++-
+ winpr/libwinpr/sspi/NTLM/ntlm.c           |  3 ++-
+ winpr/libwinpr/sspi/Negotiate/negotiate.c |  7 ++++---
+ winpr/libwinpr/sspi/Schannel/schannel.c   | 11 +++++------
+ 5 files changed, 18 insertions(+), 15 deletions(-)
+
+diff --git a/winpr/libwinpr/sspi/CredSSP/credssp.c 
b/winpr/libwinpr/sspi/CredSSP/credssp.c
+--- a/winpr/libwinpr/sspi/CredSSP/credssp.c
++++ b/winpr/libwinpr/sspi/CredSSP/credssp.c
+@@ -194,13 +194,12 @@ static SECURITY_STATUS SEC_ENTRY 
credssp_QueryCredentialsAttributesA(
+ 
+ static SECURITY_STATUS SEC_ENTRY credssp_FreeCredentialsHandle(PCredHandle 
phCredential)
+ {
+-      SSPI_CREDENTIALS* credentials = NULL;
+-
+       if (!phCredential)
+               return SEC_E_INVALID_HANDLE;
+ 
+-      credentials = 
(SSPI_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
+-
++      SSPI_CREDENTIALS* credentials =
++          (SSPI_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
++      sspi_SecureHandleInvalidate(phCredential);
+       if (!credentials)
+               return SEC_E_INVALID_HANDLE;
+ 
+diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.c 
b/winpr/libwinpr/sspi/Kerberos/kerberos.c
+--- a/winpr/libwinpr/sspi/Kerberos/kerberos.c
++++ b/winpr/libwinpr/sspi/Kerberos/kerberos.c
+@@ -540,12 +540,12 @@ static SECURITY_STATUS SEC_ENTRY 
kerberos_FreeCredentialsHandle(PCredHandle phCr
+ {
+ #ifdef WITH_KRB5
+       KRB_CREDENTIALS* credentials = 
sspi_SecureHandleGetLowerPointer(phCredential);
++      sspi_SecureHandleInvalidate(phCredential);
+       if (!credentials)
+               return SEC_E_INVALID_HANDLE;
+ 
+       credentials_unref(credentials);
+ 
+-      sspi_SecureHandleInvalidate(phCredential);
+       return SEC_E_OK;
+ #else
+       return SEC_E_UNSUPPORTED_FUNCTION;
+@@ -1212,6 +1212,7 @@ cleanup:
+                               break;
+                       default:
+                               kerberos_ContextFree(context, TRUE);
++                              sspi_SecureHandleInvalidate(phNewContext);
+                               break;
+               }
+       }
+@@ -1501,6 +1502,7 @@ cleanup:
+                               break;
+                       default:
+                               kerberos_ContextFree(context, TRUE);
++                              sspi_SecureHandleInvalidate(phNewContext);
+                               break;
+               }
+       }
+@@ -1550,6 +1552,7 @@ static SECURITY_STATUS SEC_ENTRY 
kerberos_DeleteSecurityContext(PCtxtHandle phCo
+ {
+ #ifdef WITH_KRB5
+       KRB_CONTEXT* context = get_context(phContext);
++      sspi_SecureHandleInvalidate(phContext);
+       if (!context)
+               return SEC_E_INVALID_HANDLE;
+ 
+diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c
+--- a/winpr/libwinpr/sspi/NTLM/ntlm.c
++++ b/winpr/libwinpr/sspi/NTLM/ntlm.c
+@@ -450,7 +450,7 @@ static SECURITY_STATUS SEC_ENTRY 
ntlm_FreeCredentialsHandle(PCredHandle phCreden
+ 
+       SSPI_CREDENTIALS* credentials =
+           (SSPI_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
+-
++      sspi_SecureHandleInvalidate(phCredential);
+       if (!credentials)
+               return SEC_E_INVALID_HANDLE;
+ 
+@@ -761,6 +761,7 @@ static SECURITY_STATUS SEC_ENTRY 
ntlm_InitializeSecurityContextA(
+ static SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle 
phContext)
+ {
+       NTLM_CONTEXT* context = 
(NTLM_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
++      sspi_SecureHandleInvalidate(phContext);
+       ntlm_ContextFree(context);
+       return SEC_E_OK;
+ }
+diff --git a/winpr/libwinpr/sspi/Negotiate/negotiate.c 
b/winpr/libwinpr/sspi/Negotiate/negotiate.c
+--- a/winpr/libwinpr/sspi/Negotiate/negotiate.c
++++ b/winpr/libwinpr/sspi/Negotiate/negotiate.c
+@@ -1224,10 +1224,10 @@ static SECURITY_STATUS SEC_ENTRY 
negotiate_CompleteAuthToken(PCtxtHandle phConte
+ 
+ static SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle 
phContext)
+ {
+-      NEGOTIATE_CONTEXT* context = NULL;
+       SECURITY_STATUS status = SEC_E_OK;
+-      context = 
(NEGOTIATE_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
++      NEGOTIATE_CONTEXT* context = 
(NEGOTIATE_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
++      sspi_SecureHandleInvalidate(phContext);
+       const SecPkg* pkg = NULL;
+ 
+       if (!context)
+               return SEC_E_INVALID_HANDLE;
+@@ -1507,6 +1507,7 @@ static SECURITY_STATUS SEC_ENTRY 
negotiate_FreeCredentialsHandle(PCredHandle phC
+       MechCred* creds = NULL;
+ 
+       creds = sspi_SecureHandleGetLowerPointer(phCredential);
++      sspi_SecureHandleInvalidate(phCredential);
+       if (!creds)
+               return SEC_E_INVALID_HANDLE;
+ 
+diff --git a/winpr/libwinpr/sspi/Schannel/schannel.c 
b/winpr/libwinpr/sspi/Schannel/schannel.c
+--- a/winpr/libwinpr/sspi/Schannel/schannel.c
++++ b/winpr/libwinpr/sspi/Schannel/schannel.c
+@@ -183,13 +183,12 @@ static SECURITY_STATUS SEC_ENTRY 
schannel_AcquireCredentialsHandleA(
+ 
+ static SECURITY_STATUS SEC_ENTRY schannel_FreeCredentialsHandle(PCredHandle 
phCredential)
+ {
+-      SCHANNEL_CREDENTIALS* credentials = NULL;
+-
+       if (!phCredential)
+               return SEC_E_INVALID_HANDLE;
+ 
+-      credentials = 
(SCHANNEL_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
+-
++      SCHANNEL_CREDENTIALS* credentials =
++          
(SCHANNEL_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
++      sspi_SecureHandleInvalidate(phCredential);
+       if (!credentials)
+               return SEC_E_INVALID_HANDLE;
+ 
+@@ -289,8 +288,8 @@ static SECURITY_STATUS SEC_ENTRY 
schannel_AcceptSecurityContext(
+ 
+ static SECURITY_STATUS SEC_ENTRY schannel_DeleteSecurityContext(PCtxtHandle 
phContext)
+ {
+-      SCHANNEL_CONTEXT* context = NULL;
+-      context = 
(SCHANNEL_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
++      SCHANNEL_CONTEXT* context = 
(SCHANNEL_CONTEXT*)sspi_SecureHandleGetLowerPointer(phContext);
++      sspi_SecureHandleInvalidate(phContext);
+ 
+       if (!context)
+               return SEC_E_INVALID_HANDLE;
+-- 
+2.47.3
+


Reply via email to