From patchwork Thu Nov 12 19:38:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 103922 Received: from mta-65-226.siemens.flowmailer.net (mta-65-226.siemens.flowmailer.net [185.136.65.226]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.4547.1794512429352775362 for ; Thu, 12 Nov 2026 11:40:31 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=InIkPr3a; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.226, mailfrom: fm-256628-20261112194030cc751b7a9b00020790-er_otf@rts-flowmailer.siemens.com) Received: by mta-65-226.siemens.flowmailer.net with ESMTPSA id 20261112194030cc751b7a9b00020790 for ; Thu, 12 Nov 2026 20:40:30 +0100 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc; bh=Im2QHxzT5an7KmYrGcir/mMTzOGaudjPC4dym+Tcyjk=; b=InIkPr3aTsTgWnS6IVot1bEGZTmOWDAreKavwdjXMa9PIoLCJp2506FSkD6JIo3Qwxtt9l soRc0SGEvlXLjGpg6fllhZzhSw9fE4sFbd2GpKMdlkg4FytS/0BCDfSMkdQrj+oeZGQinn8o ZfEUfzM/mEUnfmLDZIwvYVWFRO7bUIuk0LTEMT4fY6a0Ip1ksA0ObCxE1wkd1SFcVgeNlAjq VFq66HzYif1TQtKmCywFpdSOQcv3DmZedldOwKuksKKbmp8uyFPcrkSgil7QGwYxr/1XNMdm Hy+SxYnDjpwnbEyILGjyzKl3HaYQDlc5VZNuxdw/aiXYVnTUbCOjCuAg==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 1/3] libsndfile1: patch CVE-2024-50613 Date: Thu, 12 Nov 2026 20:38:21 +0100 Message-ID: <20261112193823.982149-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Thu, 12 Nov 2026 19:40:32 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250124 From: Peter Marko Pick patch from [1] which linked this CVE. [1] https://github.com/libsndfile/libsndfile/pull/1198 Signed-off-by: Peter Marko --- .../libsndfile1/CVE-2024-50613.patch | 348 ++++++++++++++++++ .../libsndfile/libsndfile1_1.2.2.bb | 1 + 2 files changed, 349 insertions(+) create mode 100644 meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2024-50613.patch diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2024-50613.patch b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2024-50613.patch new file mode 100644 index 00000000000..9b7302b2316 --- /dev/null +++ b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2024-50613.patch @@ -0,0 +1,348 @@ +From ecbccc2f23de6cefd2d97842fc0333bb742a0625 Mon Sep 17 00:00:00 2001 +From: Capsize Security +Date: Mon, 26 Oct 2026 17:28:12 -0600 +Subject: [PATCH] mpeg: sanitize float/double input to LAME ieee entry points + +Crafted files can deliver NaNs, infinities, or huge finite values through sf_writef_float / sf_writef_double into the MP3 encoder. Passing those straight to LAME trips assertions inside LAME (psymodel.c: calc_energy: `el >= 0') and aborts the host application. + +Clamp encoder input to the [-1, 1] range LAME's ieee_float / ieee_double entry points document ("data must be scaled to +/- 1 full scale", lame/lame.h); non-finite samples become silence. All four float/double x mono/stereo paths funnel through the sanitizing normalize_float / normalize_double helpers, including the non-normalized paths via a 1/0x8000 pre-scale (the stereo path already did this). The mono non-normalized path previously used lame_encode_buffer_float; routing it through the scaled ieee_float entry instead changes its gain by ~0.003% (1 part in 32768). + +Note: clamping to +/-1 intentionally changes output for valid slightly-over-full-scale input (e.g. a constant 2.0), which LAME's ieee entries never accepted in-contract; in-range audio passes through unchanged. + +CVE-2024-50613 Issue: https://github.com/libsndfile/libsndfile/issues/1034 + +Signed-off-by: Capsize Security + +CVE: CVE-2024-50613 +Upstream-Status: Backport [https://github.com/libsndfile/libsndfile/commit/ecbccc2f23de6cefd2d97842fc0333bb742a0625] +Signed-off-by: Peter Marko +--- + src/mpeg_l3_encode.c | 91 ++++++++++++++++++------- + tests/mpeg_test.c | 158 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 226 insertions(+), 23 deletions(-) + +diff --git a/src/mpeg_l3_encode.c b/src/mpeg_l3_encode.c +index aba22394..c712e6e7 100644 +--- a/src/mpeg_l3_encode.c ++++ b/src/mpeg_l3_encode.c +@@ -596,22 +596,77 @@ mpeg_l3_encode_write_int_stereo (SF_PRIVATE *psf, const int *ptr, sf_count_t len + } + + ++/* LAME's ieee_float / ieee_double entry points require input samples in the ++** range [-1.0, +1.0] ("data must be scaled to +/- 1 full scale", lame/lame.h). ++** Crafted input files can deliver NaNs, infinities, or huge finite values ++** through the public sf_writef_float / sf_writef_double API ; passing those ++** straight to LAME trips assertions inside LAME (psymodel.c : calc_energy : ++** `el >= 0') and aborts the host application (CVE-2024-50613, ++** https://github.com/libsndfile/libsndfile/issues/1034). Clamp here so the ++** encoder only ever sees in-contract input. Samples already in range pass ++** through unchanged. ++*/ ++ ++static inline float ++sanitize_float_sample (float x) ++{ if (!isfinite (x)) ++ return 0.0f ; ++ if (x > 1.0f) ++ return 1.0f ; ++ if (x < -1.0f) ++ return -1.0f ; ++ return x ; ++} /* sanitize_float_sample */ ++ ++static inline double ++sanitize_double_sample (double x) ++{ if (!isfinite (x)) ++ return 0.0 ; ++ if (x > 1.0) ++ return 1.0 ; ++ if (x < -1.0) ++ return -1.0 ; ++ return x ; ++} /* sanitize_double_sample */ ++ ++static inline void ++normalize_float (float *dest, const float *src, sf_count_t count, float norm_fact) ++{ while (--count >= 0) ++ dest [count] = sanitize_float_sample (src [count] * norm_fact) ; ++} /* normalize_float */ ++ ++static inline void ++normalize_double (double *dest, const double *src, sf_count_t count, double norm_fact) ++{ while (--count >= 0) ++ dest [count] = sanitize_double_sample (src [count] * norm_fact) ; ++} /* normalize_double */ ++ ++ + static sf_count_t + mpeg_l3_encode_write_float_mono (SF_PRIVATE *psf, const float *ptr, sf_count_t len) +-{ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; ++{ BUF_UNION ubuf ; ++ MPEG_L3_ENC_PRIVATE *pmpeg = (MPEG_L3_ENC_PRIVATE*) psf->codec_data ; + sf_count_t total = 0 ; + int nbytes, writecount, writen ; + + if ((psf->error = mpeg_l3_encoder_construct (psf))) + return 0 ; + ++ const sf_count_t max_samples = SF_MIN (ARRAY_LEN (ubuf.fbuf), pmpeg->frame_samples) ; + while (len) +- { writecount = SF_MIN (len, (sf_count_t) pmpeg->frame_samples) ; ++ { writecount = SF_MIN (len, max_samples) ; + + if (psf->norm_float) +- nbytes = lame_encode_buffer_ieee_float (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; ++ { normalize_float (ubuf.fbuf, ptr + total, writecount, 1.0f) ; ++ nbytes = lame_encode_buffer_ieee_float (pmpeg->lamef, ubuf.fbuf, NULL, writecount, pmpeg->block, pmpeg->block_len) ; ++ } + else +- nbytes = lame_encode_buffer_float (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; ++ { /* Lame lacks a non-normalized mono float write, so scale to ++ ** ieee full scale here, mirroring the stereo path below. ++ */ ++ normalize_float (ubuf.fbuf, ptr + total, writecount, 1.0 / (float) 0x8000) ; ++ nbytes = lame_encode_buffer_ieee_float (pmpeg->lamef, ubuf.fbuf, NULL, writecount, pmpeg->block, pmpeg->block_len) ; ++ } + if (nbytes < 0) + { psf_log_printf (psf, "lame_encode_buffer returned %d\n", nbytes) ; + break ; +@@ -632,14 +687,6 @@ mpeg_l3_encode_write_float_mono (SF_PRIVATE *psf, const float *ptr, sf_count_t l + } + + +-static inline void +-normalize_float (float *dest, const float *src, sf_count_t count, float norm_fact) +-{ while (--count >= 0) +- { dest [count] = src [count] * norm_fact ; +- } ; +-} +- +- + static sf_count_t + mpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t len) + { BUF_UNION ubuf ; +@@ -655,7 +702,9 @@ mpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t + { writecount = SF_MIN (len, max_samples) ; + + if (psf->norm_float) +- nbytes = lame_encode_buffer_interleaved_ieee_float (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; ++ { normalize_float (ubuf.fbuf, ptr + total, writecount, 1.0f) ; ++ nbytes = lame_encode_buffer_interleaved_ieee_float (pmpeg->lamef, ubuf.fbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; ++ } + else + { /* Lame lacks a non-normalized interleaved float write. Bummer. */ + normalize_float (ubuf.fbuf, ptr + total, writecount, 1.0 / (float) 0x8000) ; +@@ -682,14 +731,6 @@ mpeg_l3_encode_write_float_stereo (SF_PRIVATE *psf, const float *ptr, sf_count_t + } + + +-static inline void +-normalize_double (double *dest, const double *src, sf_count_t count, double norm_fact) +-{ while (--count >= 0) +- { dest [count] = src [count] * norm_fact ; +- } ; +-} +- +- + static sf_count_t + mpeg_l3_encode_write_double_mono (SF_PRIVATE *psf, const double *ptr, sf_count_t len) + { BUF_UNION ubuf ; +@@ -705,7 +746,9 @@ mpeg_l3_encode_write_double_mono (SF_PRIVATE *psf, const double *ptr, sf_count_t + { writecount = SF_MIN (len, max_samples) ; + + if (psf->norm_double) +- nbytes = lame_encode_buffer_ieee_double (pmpeg->lamef, ptr + total, NULL, writecount, pmpeg->block, pmpeg->block_len) ; ++ { normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0) ; ++ nbytes = lame_encode_buffer_ieee_double (pmpeg->lamef, ubuf.dbuf, NULL, writecount, pmpeg->block, pmpeg->block_len) ; ++ } + else + { /* Lame lacks non-normalized double writing */ + normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0 / (double) 0x8000) ; +@@ -747,7 +790,9 @@ mpeg_l3_encode_write_double_stereo (SF_PRIVATE *psf, const double *ptr, sf_count + { writecount = SF_MIN (len, max_samples) ; + + if (psf->norm_double) +- nbytes = lame_encode_buffer_interleaved_ieee_double (pmpeg->lamef, ptr + total, writecount / 2, pmpeg->block, pmpeg->block_len) ; ++ { normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0) ; ++ nbytes = lame_encode_buffer_interleaved_ieee_double (pmpeg->lamef, ubuf.dbuf, writecount / 2, pmpeg->block, pmpeg->block_len) ; ++ } + else + { /* Lame lacks interleaved non-normalized double writing */ + normalize_double (ubuf.dbuf, ptr + total, writecount, 1.0 / (double) 0x8000) ; +diff --git a/tests/mpeg_test.c b/tests/mpeg_test.c +index fe7f53d1..87adf2ac 100644 +--- a/tests/mpeg_test.c ++++ b/tests/mpeg_test.c +@@ -258,6 +258,162 @@ mpeg_double_test (void) + unlink (filename) ; + } /* mpeg_double_test */ + ++/* Hostile input (CVE-2024-50613) : NaNs, infinities and huge finite values ++** must be sanitized before reaching LAME, not abort it. One helper covers ++** mono and stereo (channels == 2 exercises the interleaved_ieee paths), ++** with float normalization on or off. ++*/ ++static void ++mpeg_hostile_float_case (int channels, int normalize) ++{ char filename [64] ; ++ SNDFILE * file ; ++ SF_INFO sfinfo ; ++ unsigned k ; ++ size_t samples = ARRAY_LEN (data_out.f) ; ++ ++ snprintf (filename, sizeof (filename), "mpeg_hostile_float_%dch_%s.mp3", ++ channels, normalize ? "norm" : "nonorm") ; ++ ++ print_test_name ("mpeg_hostile_float_test", filename) ; ++ ++ if (channels == 1) ++ { gen_windowed_sine_float (data_out.f, samples, normalize ? 0.95 : 1.0 * 0x7F00) ; ++ } ++ else ++ { /* Interleave two mirrored channels. data_in.f is scratch here ; ++ ** it is overwritten by the read-back below. ++ */ ++ gen_windowed_sine_float (data_in.f, samples / 2, normalize ? 0.95 : 1.0 * 0x7F00) ; ++ for (k = 0 ; k < samples / 2 ; k++) ++ { data_out.f [2 * k] = data_in.f [k] ; ++ data_out.f [2 * k + 1] = data_in.f [samples / 2 - k - 1] ; ++ } ; ++ } ; ++ ++ data_out.f [0] = NAN ; ++ data_out.f [1] = INFINITY ; ++ data_out.f [2] = -INFINITY ; ++ data_out.f [3] = 1.0e30f ; ++ data_out.f [4] = -1.0e30f ; ++ ++ memset (&sfinfo, 0, sizeof (sfinfo)) ; ++ ++ /* Set up output file type. */ ++ sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; ++ sfinfo.channels = channels ; ++ sfinfo.samplerate = SAMPLE_RATE ; ++ ++ /* Write the output file. */ ++ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; ++ if (! normalize) ++ sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ; ++ test_write_float_or_die (file, 0, data_out.f, samples, __LINE__) ; ++ sf_close (file) ; ++ ++ /* Read the file in again. */ ++ memset (&sfinfo, 0, sizeof (sfinfo)) ; ++ ++ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; ++ test_read_float_or_die (file, 0, data_in.f, samples, __LINE__) ; ++ sf_close (file) ; ++ ++ /* The decoded output must be finite and within a sane range. MP3 is ++ ** lossy so decoded peaks may overshoot the encoder's +/-1 clamp ++ ** slightly ; a generous bound catches scale errors without ++ ** false-failing on codec noise. Explicit checks (no assert.h ++ ** dependency) match the surrounding test style. ++ */ ++ for (k = 0 ; k < samples ; k++) ++ if (! isfinite (data_in.f [k]) || fabsf (data_in.f [k]) > 4.0f) ++ { printf ("\n\nLine %d : bad decoded sample at index %u : %f.\n\n", __LINE__, k, data_in.f [k]) ; ++ exit (1) ; ++ } ; ++ ++ puts ("ok") ; ++ ++ unlink (filename) ; ++} /* mpeg_hostile_float_case */ ++ ++static void ++mpeg_hostile_float_test (void) ++{ mpeg_hostile_float_case (1, SF_TRUE) ; ++ mpeg_hostile_float_case (1, SF_FALSE) ; ++ mpeg_hostile_float_case (2, SF_TRUE) ; ++ mpeg_hostile_float_case (2, SF_FALSE) ; ++} /* mpeg_hostile_float_test */ ++ ++/* Double-precision version of the helper above. */ ++static void ++mpeg_hostile_double_case (int channels, int normalize) ++{ char filename [64] ; ++ SNDFILE * file ; ++ SF_INFO sfinfo ; ++ unsigned k ; ++ size_t samples = ARRAY_LEN (data_out.d) ; ++ ++ snprintf (filename, sizeof (filename), "mpeg_hostile_double_%dch_%s.mp3", ++ channels, normalize ? "norm" : "nonorm") ; ++ ++ print_test_name ("mpeg_hostile_double_test", filename) ; ++ ++ if (channels == 1) ++ { gen_windowed_sine_double (data_out.d, samples, normalize ? 0.95 : 1.0 * 0x7F00) ; ++ } ++ else ++ { gen_windowed_sine_double (data_in.d, samples / 2, normalize ? 0.95 : 1.0 * 0x7F00) ; ++ for (k = 0 ; k < samples / 2 ; k++) ++ { data_out.d [2 * k] = data_in.d [k] ; ++ data_out.d [2 * k + 1] = data_in.d [samples / 2 - k - 1] ; ++ } ; ++ } ; ++ ++ data_out.d [0] = NAN ; ++ data_out.d [1] = INFINITY ; ++ data_out.d [2] = -INFINITY ; ++ data_out.d [3] = 1.0e300 ; ++ data_out.d [4] = -1.0e300 ; ++ ++ memset (&sfinfo, 0, sizeof (sfinfo)) ; ++ ++ /* Set up output file type. */ ++ sfinfo.format = SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III ; ++ sfinfo.channels = channels ; ++ sfinfo.samplerate = SAMPLE_RATE ; ++ ++ /* Write the output file. */ ++ file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ; ++ if (! normalize) ++ sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ; ++ test_write_double_or_die (file, 0, data_out.d, samples, __LINE__) ; ++ sf_close (file) ; ++ ++ /* Read the file in again. */ ++ memset (&sfinfo, 0, sizeof (sfinfo)) ; ++ ++ file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ; ++ test_read_double_or_die (file, 0, data_in.d, samples, __LINE__) ; ++ sf_close (file) ; ++ ++ /* Finite and sane, as above. */ ++ for (k = 0 ; k < samples ; k++) ++ if (! isfinite (data_in.d [k]) || fabs (data_in.d [k]) > 4.0) ++ { printf ("\n\nLine %d : bad decoded sample at index %u : %f.\n\n", __LINE__, k, data_in.d [k]) ; ++ exit (1) ; ++ } ; ++ ++ puts ("ok") ; ++ ++ unlink (filename) ; ++} /* mpeg_hostile_double_case */ ++ ++static void ++mpeg_hostile_double_test (void) ++{ mpeg_hostile_double_case (1, SF_TRUE) ; ++ mpeg_hostile_double_case (1, SF_FALSE) ; ++ mpeg_hostile_double_case (2, SF_TRUE) ; ++ mpeg_hostile_double_case (2, SF_FALSE) ; ++} /* mpeg_hostile_double_test */ ++ + + static void + mpeg_stereo_seek_test (const char * filename, int format) +@@ -338,6 +494,8 @@ main (void) + mpeg_int_test () ; + mpeg_float_test () ; + mpeg_double_test () ; ++ mpeg_hostile_float_test () ; ++ mpeg_hostile_double_test () ; + + mpeg_stereo_seek_test ("mpeg_seek.mp3", SF_FORMAT_MPEG | SF_FORMAT_MPEG_LAYER_III) ; + } diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb b/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb index 5d2a2c256b0..b22f5b1e503 100644 --- a/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb +++ b/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb @@ -14,6 +14,7 @@ SRC_URI = "${GITHUB_BASE_URI}/download/${PV}/libsndfile-${PV}.tar.xz \ file://CVE-2025-56226-01.patch \ file://CVE-2025-56226-02.patch \ file://CVE-2026-37555.patch \ + file://CVE-2024-50613.patch \ " GITHUB_BASE_URI = "https://github.com/libsndfile/libsndfile/releases/" From patchwork Thu Nov 12 19:38:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 103923 Received: from mta-65-225.siemens.flowmailer.net (mta-65-225.siemens.flowmailer.net [185.136.65.225]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4505.1794512442554154375 for ; Thu, 12 Nov 2026 11:40:42 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=pXjuLceV; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.65.225, mailfrom: fm-256628-20261112194040a3febf34cd0002070e-mo4cqw@rts-flowmailer.siemens.com) Received: by mta-65-225.siemens.flowmailer.net with ESMTPSA id 20261112194040a3febf34cd0002070e for ; Thu, 12 Nov 2026 20:40:40 +0100 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=2H2iuTP4v2oFwd8H3Vp9Uj4HpN+G4BUUfmG27kyaJco=; b=pXjuLceVZGVGn8hkdjjIhht++Jujj6fLu8VRkGlzgwqK1pHiAhNb5UJJU3expvxCa1gnVp dlgbx8j0pmf6hulRfkaJ8jQH8WymQnPphsaoRIiPT3Uc1cuTW5qQj1NFUZs5UA5h/qXomnfB f99B0LKlbSE6TzGUZyz6QvdGJjw/5PeYbbA0wntHvoJXKfv9/fDf4i/YFTms+oVTrynhglrF v0DkJJmddfsIO4K3kK8jyrmLlcHfyr0RITYpGj5XaxIOJ+wV1s4RGVCuFvcpwIroX5jWkvDN s5qdCMDcDpHgZ9DRcaNJlnyNL7Qrm03gKhuGqSPSN87Kcg73DOti2pdw==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 2/3] libsndfile1: patch CVE-2025-52194 Date: Thu, 12 Nov 2026 20:38:22 +0100 Message-ID: <20261112193823.982149-2-peter.marko@siemens.com> In-Reply-To: <20261112193823.982149-1-peter.marko@siemens.com> References: <20261112193823.982149-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Thu, 12 Nov 2026 19:40:52 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250125 From: Peter Marko Pick patch references by [1] references in CVE report. [1] https://github.com/libsndfile/libsndfile/issues/1082#issuecomment-6442050313 Signed-off-by: Peter Marko --- .../libsndfile1/CVE-2025-52194.patch | 27 +++++++++++++++++++ .../libsndfile/libsndfile1_1.2.2.bb | 1 + 2 files changed, 28 insertions(+) create mode 100644 meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2025-52194.patch diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2025-52194.patch b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2025-52194.patch new file mode 100644 index 00000000000..ec5da0b731e --- /dev/null +++ b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2025-52194.patch @@ -0,0 +1,27 @@ +From 7ff854d1e0bd9a751a9ff52ed980c62afced91fe Mon Sep 17 00:00:00 2001 +From: Saddam +Date: Tue, 21 Jul 2026 20:49:11 +0530 +Subject: [PATCH] ircam: use psf_lrintf when reading samplerate + +The IRCAM header sample rate is a float read straight from the file. (int) samplerate is undefined when the value is out of int range or non-finite; psf_lrintf matches mat4/mat5 which convert a file sample rate the same way. + +CVE: CVE-2025-52194 +Upstream-Status: Backport [https://github.com/libsndfile/libsndfile/commit/7ff854d1e0bd9a751a9ff52ed980c62afced91fe] +Signed-off-by: Peter Marko +--- + src/ircam.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ircam.c b/src/ircam.c +index 3d73ba44..d0780d8a 100644 +--- a/src/ircam.c ++++ b/src/ircam.c +@@ -161,7 +161,7 @@ ircam_read_header (SF_PRIVATE *psf) + + psf_log_printf (psf, "marker: 0x%X\n", marker) ; + +- psf->sf.samplerate = (int) samplerate ; ++ psf->sf.samplerate = psf_lrintf (samplerate) ; + + psf_log_printf (psf, " Sample Rate : %d\n" + " Channels : %d\n" diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb b/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb index b22f5b1e503..37f852d5c38 100644 --- a/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb +++ b/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb @@ -15,6 +15,7 @@ SRC_URI = "${GITHUB_BASE_URI}/download/${PV}/libsndfile-${PV}.tar.xz \ file://CVE-2025-56226-02.patch \ file://CVE-2026-37555.patch \ file://CVE-2024-50613.patch \ + file://CVE-2025-52194.patch \ " GITHUB_BASE_URI = "https://github.com/libsndfile/libsndfile/releases/" From patchwork Thu Nov 12 19:38:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Marko X-Patchwork-Id: 103924 Received: from mta-64-227.siemens.flowmailer.net (mta-64-227.siemens.flowmailer.net [185.136.64.227]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.4508.1794512448001257857 for ; Thu, 12 Nov 2026 11:40:48 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=peter.marko@siemens.com header.s=fm1 header.b=LBVnmGKy; spf=pass (domain: rts-flowmailer.siemens.com, ip: 185.136.64.227, mailfrom: fm-256628-20261112194046b6b16e675d0002070a-xep5jc@rts-flowmailer.siemens.com) Received: by mta-64-227.siemens.flowmailer.net with ESMTPSA id 20261112194046b6b16e675d0002070a for ; Thu, 12 Nov 2026 20:40:46 +0100 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=fm1; d=siemens.com; i=peter.marko@siemens.com; h=Date:From:Subject:To:Message-ID:MIME-Version:Content-Type:Content-Transfer-Encoding:Cc:References:In-Reply-To; bh=aBJ4RlMwl7Qk1WDarpBG676OujOP5XgSEIWJCkKEOW0=; b=LBVnmGKyleQFitsoVFyYsoqWlL24nPYUmTKoeu41HZgsd0mHbrjHlM7PFSrgaqHzqYYNQH v4SpCbKLjr9FCN947ClLJcMYJIBkTikrrkURGf4xbycoilHkNGADVBjm/Tk3f9blF/5Z36PH 1tSCj25sTon64BvvSdOOb7Gj6I3bWeZ1hWhaLCirXd0kkAz1EYToLChFHc/o999XMfVwXaQL j0Fax8riw9cvUclhvaZeqlZrlmOccquVSy/ZxVRbG/aUVMWNCAUi9Sd3N/J54dIshwBTXHpM tBt//4DNQJwa8c+VeYMkVBwdsNaqGh83AZ9VODejRa5u+tHXTCxZ3egA==; From: Peter Marko To: openembedded-core@lists.openembedded.org Cc: Peter Marko Subject: [scarthgap][PATCH 3/3] libsndfile1: patch CVE-2026-109828 Date: Thu, 12 Nov 2026 20:38:24 +0100 Message-ID: <20261112193823.982149-4-peter.marko@siemens.com> In-Reply-To: <20261112193823.982149-1-peter.marko@siemens.com> References: <20261112193823.982149-1-peter.marko@siemens.com> MIME-Version: 1.0 X-Flowmailer-Platform: Siemens Feedback-ID: 519:519-256628:519-21489:flowmailer List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Thu, 12 Nov 2026 19:40:52 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/250126 From: Peter Marko Pick patch from [1] which clsed [2] linked from [3]. Also pick a refactoring commit which is required for a clean cherry-pick. [1] https://github.com/libsndfile/libsndfile/pull/1170 [2] https://github.com/libsndfile/libsndfile/issues/1169 [3] https://nvd.nist.gov/vuln/detail/cve-2026-109828 Signed-off-by: Peter Marko --- .../libsndfile1/CVE-2026-109828-01.patch | 234 ++++++++++++++++++ .../libsndfile1/CVE-2026-109828-02.patch | 26 ++ .../libsndfile/libsndfile1_1.2.2.bb | 2 + 3 files changed, 262 insertions(+) create mode 100644 meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2026-109828-01.patch create mode 100644 meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2026-109828-02.patch diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2026-109828-01.patch b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2026-109828-01.patch new file mode 100644 index 00000000000..61acc37c2dc --- /dev/null +++ b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2026-109828-01.patch @@ -0,0 +1,234 @@ +From 59babedce8fa8eb1000ecb3c87a5dd4a1190ad9e Mon Sep 17 00:00:00 2001 +From: iceray-Li <108821718+iceray00@users.noreply.github.com> +Date: Tue, 22 Sep 2026 06:05:03 +0000 +Subject: [PATCH] aiff, wav, wavlike: index the cue array through a pointer + +The cue array of an SF_CUES struct is allocated with room for the actual cue +count (SF_CUES_VAR_SIZE()), but the public SF_CUES type declares it with a +fixed length of 100 (SF_CUES_VAR (100)). Compilers therefore assume that +cue_points [] holds 100 elements, and UBSan's array-bounds check flags every +access beyond that even though the allocation is larger: + + src/aiff.c:823:8: runtime error: index 100 out of bounds for type 'SF_CUE_POINT [100]' + src/aiff.c:943:38: runtime error: index 100 out of bounds for type 'SF_CUE_POINT [100]' + src/wav.c:524:8: runtime error: index 100 out of bounds for type 'SF_CUE_POINT [100]' + +The declared bound is also the reason the CVE-2022-33064 report (issue #832) +is still open. The accesses themselves are inside the allocation: the cue +count is capped at 2500 by wav.c and aiff.c, psf_cues_alloc() reserves +cue_count * sizeof (SF_CUE_POINT) bytes, and the same inputs are clean under +ASan, so no validation of the file can make the diagnostic disappear. + +Add psf_cues_points(), which hands out the first element of the array as an +ordinary pointer, and use it at every place that subscripts cue_points []. +The layout of the public SF_CUES struct, the API it exposes and the file +handling are unchanged. + +Tested with ossfuzz/sndfile_fuzzer and ossfuzz/sndfile_alt_fuzzer built with +-fsanitize=address,undefined: the crafted AIFF and WAV inputs abort in +src/aiff.c and src/wav.c before the change and are clean after it. + +CVE: CVE-2026-109828 +Upstream-Status: Backport [https://github.com/libsndfile/libsndfile/commit/59babedce8fa8eb1000ecb3c87a5dd4a1190ad9e] +Signed-off-by: Peter Marko +--- + src/aiff.c | 36 ++++++++++++++++++++---------------- + src/common.h | 10 ++++++++++ + src/wav.c | 23 +++++++++++++---------- + src/wavlike.c | 5 +++-- + 4 files changed, 46 insertions(+), 28 deletions(-) + +diff --git a/src/aiff.c b/src/aiff.c +index e36b21e0..39c3221d 100644 +--- a/src/aiff.c ++++ b/src/aiff.c +@@ -403,6 +403,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) + int k, found_chunk = 0, done = 0, error = 0 ; + char *cptr ; + int instr_found = 0, mark_found = 0 ; ++ SF_CUE_POINT *cue_points = NULL ; + + if (psf->filelength > 0xFFFFFFFFLL) + psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ; +@@ -813,6 +814,8 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) + if ((psf->cues = psf_cues_alloc (mark_count)) == NULL) + return SFE_MALLOC_FAILED ; + ++ cue_points = psf_cues_points (psf->cues) ; ++ + for (n = 0 ; n < mark_count && bytesread < chunk_size ; n++) + { uint32_t pstr_len ; + uint8_t ch ; +@@ -820,12 +823,12 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) + bytesread += psf_binheader_readf (psf, "E241", &mark_id, &position, &ch) ; + psf_log_printf (psf, " Mark ID : %u\n Position : %u\n", mark_id, position) ; + +- psf->cues->cue_points [n].indx = mark_id ; +- psf->cues->cue_points [n].position = 0 ; +- psf->cues->cue_points [n].fcc_chunk = MAKE_MARKER ('d', 'a', 't', 'a') ; /* always data */ +- psf->cues->cue_points [n].chunk_start = 0 ; +- psf->cues->cue_points [n].block_start = 0 ; +- psf->cues->cue_points [n].sample_offset = position ; ++ cue_points [n].indx = mark_id ; ++ cue_points [n].position = 0 ; ++ cue_points [n].fcc_chunk = MAKE_MARKER ('d', 'a', 't', 'a') ; /* always data */ ++ cue_points [n].chunk_start = 0 ; ++ cue_points [n].block_start = 0 ; ++ cue_points [n].sample_offset = position ; + + pstr_len = (ch & 1) ? ch : ch + 1 ; + +@@ -841,7 +844,7 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) + + psf_log_printf (psf, " Name : %s\n", ubuf.scbuf) ; + +- psf_strlcpy (psf->cues->cue_points [n].name, sizeof (psf->cues->cue_points [n].name), ubuf.cbuf) ; ++ psf_strlcpy (cue_points [n].name, sizeof (cue_points [n].name), ubuf.cbuf) ; + + paiff->markstr [n].markerID = mark_id ; + paiff->markstr [n].position = position ; +@@ -940,14 +943,14 @@ aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) + + for (j = 0 ; j < psf->cues->cue_count - (uint32_t) (psf->instrument->loop_count * 2) ; j ++) + { /* This simply copies the information in cues above loop positions and writes it at current count instead */ +- psf->cues->cue_points [j].indx = psf->cues->cue_points [j + psf->instrument->loop_count * 2].indx ; +- psf->cues->cue_points [j].position = psf->cues->cue_points [j + psf->instrument->loop_count * 2].position ; +- psf->cues->cue_points [j].fcc_chunk = psf->cues->cue_points [j + psf->instrument->loop_count * 2].fcc_chunk ; +- psf->cues->cue_points [j].chunk_start = psf->cues->cue_points [j + psf->instrument->loop_count * 2].chunk_start ; +- psf->cues->cue_points [j].block_start = psf->cues->cue_points [j + psf->instrument->loop_count * 2].block_start ; +- psf->cues->cue_points [j].sample_offset = psf->cues->cue_points [j + psf->instrument->loop_count * 2].sample_offset ; ++ cue_points [j].indx = cue_points [j + psf->instrument->loop_count * 2].indx ; ++ cue_points [j].position = cue_points [j + psf->instrument->loop_count * 2].position ; ++ cue_points [j].fcc_chunk = cue_points [j + psf->instrument->loop_count * 2].fcc_chunk ; ++ cue_points [j].chunk_start = cue_points [j + psf->instrument->loop_count * 2].chunk_start ; ++ cue_points [j].block_start = cue_points [j + psf->instrument->loop_count * 2].block_start ; ++ cue_points [j].sample_offset = cue_points [j + psf->instrument->loop_count * 2].sample_offset ; + for (str_index = 0 ; str_index < 256 ; str_index++) +- psf->cues->cue_points [j].name [str_index] = psf->cues->cue_points [j + psf->instrument->loop_count * 2].name [str_index] ; ++ cue_points [j].name [str_index] = cue_points [j + psf->instrument->loop_count * 2].name [str_index] ; + } ; + psf->cues->cue_count -= psf->instrument->loop_count * 2 ; + } else +@@ -1461,10 +1464,11 @@ aiff_write_header (SF_PRIVATE *psf, int calc_length) + { /* There are cues but no loops */ + uint32_t idx ; + int totalStringLength = 0, stringLength ; ++ SF_CUE_POINT *cue_points = psf_cues_points (psf->cues) ; + + /* Here we count how many bytes will the pascal strings need */ + for (idx = 0 ; idx < psf->cues->cue_count ; idx++) +- { stringLength = strlen (psf->cues->cue_points [idx].name) + 1 ; /* We'll count the first byte also of every pascal string */ ++ { stringLength = strlen (cue_points [idx].name) + 1 ; /* We'll count the first byte also of every pascal string */ + totalStringLength += stringLength + (stringLength % 2 == 0 ? 0 : 1) ; + } ; + +@@ -1472,7 +1476,7 @@ aiff_write_header (SF_PRIVATE *psf, int calc_length) + BHWm (MARK_MARKER), BHW4 (2 + psf->cues->cue_count * (2 + 4) + totalStringLength), BHW2 (psf->cues->cue_count)) ; + + for (idx = 0 ; idx < psf->cues->cue_count ; idx++) +- psf_binheader_writef (psf, "E24p", BHW2 (psf->cues->cue_points [idx].indx), BHW4 (psf->cues->cue_points [idx].sample_offset), BHWp (psf->cues->cue_points [idx].name)) ; ++ psf_binheader_writef (psf, "E24p", BHW2 (cue_points [idx].indx), BHW4 (cue_points [idx].sample_offset), BHWp (cue_points [idx].name)) ; + } ; + + if (psf->strings.flags & SF_STR_LOCATE_START) +diff --git a/src/common.h b/src/common.h +index 01f6ae09..ee6844b8 100644 +--- a/src/common.h ++++ b/src/common.h +@@ -989,6 +989,16 @@ SF_CUES * psf_cues_dup (const void * ptr, size_t datasize) ; + SF_CUES * psf_cues_alloc (uint32_t cue_count) ; + void psf_get_cues (SF_PRIVATE * psf, void * data, size_t datasize) ; + ++/* The cue array is allocated with room for the actual cue count (see ++** psf_cues_alloc()), but the public SF_CUES type declares it with a fixed ++** length of 100. Index it through a pointer so that compilers do not flag ++** accesses to the longer, correctly allocated array (issue #832). ++*/ ++static inline SF_CUE_POINT * ++psf_cues_points (SF_CUES *cues) ++{ return cues->cue_points ; ++} /* psf_cues_points */ ++ + SF_INSTRUMENT * psf_instrument_alloc (void) ; + + void psf_sanitize_string (char * cptr, int len) ; +diff --git a/src/wav.c b/src/wav.c +index 80dda4e1..f206bc34 100644 +--- a/src/wav.c ++++ b/src/wav.c +@@ -484,6 +484,7 @@ wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) + + { uint32_t thisread, bytesread, cue_count, position, offset ; + int id, chunk_id, chunk_start, block_start, cue_index ; ++ SF_CUE_POINT *cue_points ; + + bytesread = psf_binheader_readf (psf, "4", &cue_count) ; + psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ; +@@ -504,6 +505,7 @@ wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) + if ((psf->cues = psf_cues_alloc (cue_count)) == NULL) + return SFE_MALLOC_FAILED ; + ++ cue_points = psf_cues_points (psf->cues) ; + cue_index = 0 ; + + while (cue_count) +@@ -521,13 +523,13 @@ wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) + else if (cue_index == 10) + psf_log_printf (psf, " (Skipping)\n") ; + +- psf->cues->cue_points [cue_index].indx = id ; +- psf->cues->cue_points [cue_index].position = position ; +- psf->cues->cue_points [cue_index].fcc_chunk = chunk_id ; +- psf->cues->cue_points [cue_index].chunk_start = chunk_start ; +- psf->cues->cue_points [cue_index].block_start = block_start ; +- psf->cues->cue_points [cue_index].sample_offset = offset ; +- psf->cues->cue_points [cue_index].name [0] = '\0' ; ++ cue_points [cue_index].indx = id ; ++ cue_points [cue_index].position = position ; ++ cue_points [cue_index].fcc_chunk = chunk_id ; ++ cue_points [cue_index].chunk_start = chunk_start ; ++ cue_points [cue_index].block_start = block_start ; ++ cue_points [cue_index].sample_offset = offset ; ++ cue_points [cue_index].name [0] = '\0' ; + cue_count -- ; + cue_index ++ ; + } ; +@@ -1210,13 +1212,14 @@ wav_write_header (SF_PRIVATE *psf, int calc_length) + + if (psf->cues != NULL) + { uint32_t k ; ++ SF_CUE_POINT *cue_points = psf_cues_points (psf->cues) ; + + psf_binheader_writef (psf, "em44", BHWm (cue_MARKER), BHW4 (4 + psf->cues->cue_count * 6 * 4), BHW4 (psf->cues->cue_count)) ; + + for (k = 0 ; k < psf->cues->cue_count ; k++) +- psf_binheader_writef (psf, "e44m444", BHW4 (psf->cues->cue_points [k].indx), BHW4 (psf->cues->cue_points [k].position), +- BHWm (psf->cues->cue_points [k].fcc_chunk), BHW4 (psf->cues->cue_points [k].chunk_start), +- BHW4 (psf->cues->cue_points [k].block_start), BHW4 (psf->cues->cue_points [k].sample_offset)) ; ++ psf_binheader_writef (psf, "e44m444", BHW4 (cue_points [k].indx), BHW4 (cue_points [k].position), ++ BHWm (cue_points [k].fcc_chunk), BHW4 (cue_points [k].chunk_start), ++ BHW4 (cue_points [k].block_start), BHW4 (cue_points [k].sample_offset)) ; + } ; + + if (psf->instrument != NULL) +diff --git a/src/wavlike.c b/src/wavlike.c +index 05691323..0c3577a8 100644 +--- a/src/wavlike.c ++++ b/src/wavlike.c +@@ -1060,13 +1060,14 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length) + + if (psf->cues) + { unsigned int i = 0 ; ++ SF_CUE_POINT *cue_points = psf_cues_points (psf->cues) ; + + /* find id to store label */ +- while (i < psf->cues->cue_count && psf->cues->cue_points [i].indx != mark_id) ++ while (i < psf->cues->cue_count && cue_points [i].indx != mark_id) + i++ ; + + if (i < psf->cues->cue_count) +- memcpy (psf->cues->cue_points [i].name, buffer, sizeof (psf->cues->cue_points [i].name)) ; ++ memcpy (cue_points [i].name, buffer, sizeof (cue_points [i].name)) ; + } ; + } ; + break ; diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2026-109828-02.patch b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2026-109828-02.patch new file mode 100644 index 00000000000..dab12f04ace --- /dev/null +++ b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2026-109828-02.patch @@ -0,0 +1,26 @@ +From 1ccd2a18826722c3aa9ed54122ebff20e3b92b10 Mon Sep 17 00:00:00 2001 +From: Ilias Aberkane +Date: Fri, 25 Sep 2026 13:38:54 +0200 +Subject: [PATCH] wavlike: copy only the labl bytes actually read into cue + names + +CVE: CVE-2026-109828 +Upstream-Status: Backport [https://github.com/libsndfile/libsndfile/commit/1ccd2a18826722c3aa9ed54122ebff20e3b92b10] +Signed-off-by: Peter Marko +--- + src/wavlike.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/wavlike.c b/src/wavlike.c +index 0c3577a8..9d99b74a 100644 +--- a/src/wavlike.c ++++ b/src/wavlike.c +@@ -1067,7 +1067,7 @@ wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length) + i++ ; + + if (i < psf->cues->cue_count) +- memcpy (cue_points [i].name, buffer, sizeof (cue_points [i].name)) ; ++ psf_strlcpy (cue_points [i].name, sizeof (cue_points [i].name), buffer) ; + } ; + } ; + break ; diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb b/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb index 37f852d5c38..bb8c666de70 100644 --- a/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb +++ b/meta/recipes-multimedia/libsndfile/libsndfile1_1.2.2.bb @@ -16,6 +16,8 @@ SRC_URI = "${GITHUB_BASE_URI}/download/${PV}/libsndfile-${PV}.tar.xz \ file://CVE-2026-37555.patch \ file://CVE-2024-50613.patch \ file://CVE-2025-52194.patch \ + file://CVE-2026-109828-01.patch \ + file://CVE-2026-109828-02.patch \ " GITHUB_BASE_URI = "https://github.com/libsndfile/libsndfile/releases/"