From 5df5469cc23fae59cbee358f4d21fcbefdde457f Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 14:49:19 -0400 Subject: [PATCH 01/19] leansdr : Fix undefined shift behavior in GF(2^N) arithmetic The gf2n implementation used a left shift on a potentially negative value when masking field elements: (~(Te)0) << N This can result in undefined behavior for signed integer types and was reported by static analysis (cppcheck). Require the field element type to be unsigned and replace the mask generation with an explicit N-bit mask constructed from the element type. Also make the overflow check use the element type to avoid implicit signed integer operations. Add comments documenting the packed polynomial representation and the GF(2^N) reduction steps to clarify the intent of the bit operations. Fixes static analysis warning about shifting negative values. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/leansdr/discrmath.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demoddatv/leansdr/discrmath.h b/plugins/channelrx/demoddatv/leansdr/discrmath.h index de3835713..ff276c296 100644 --- a/plugins/channelrx/demoddatv/leansdr/discrmath.h +++ b/plugins/channelrx/demoddatv/leansdr/discrmath.h @@ -24,6 +24,7 @@ #pragma GCC diagnostic ignored "-Wshift-negative-value" #include +#include namespace leansdr { @@ -223,6 +224,11 @@ bitvect operator*(bitvect a, const bitvect &b) template struct gf2n { + // Field elements are represented as packed polynomial coefficients: + // bit i corresponds to the coefficient of X^i. Unsigned storage is + // required so bit operations have well-defined behavior. + static_assert(std::is_unsigned_v, "Te must be unsigned"); + typedef Te element; static const Te alpha = ALPHA; gf2n() @@ -236,9 +242,14 @@ struct gf2n lut_exp[i] = alpha_i; // ALPHA^i lut_exp[((1 << N) - 1) + i] = alpha_i; // Wrap to avoid modulo 2^N-1 lut_log[alpha_i] = i; - bool overflow = alpha_i & (1 << (N - 1)); + // Multiplication by ALPHA=[X] shifts the polynomial left by one. + // If the X^(N-1) coefficient was set, the shift will overflow and + // the generator polynomial must be applied modulo P(X). + bool overflow = alpha_i & (static_cast(1) << (N - 1)); alpha_i *= 2; // Multiply by alpha=[X] i.e. increase degrees - alpha_i &= ~((~(Te)0) << N); // In case Te is wider than N bits + // Keep only the lowest N bits. This removes the X^N term and + // higher bits before applying the generator polynomial reduction. + alpha_i &= static_cast((static_cast(1) << N) - 1); if (overflow) alpha_i ^= TRUNCP; // Modulo P iteratively } From 742746dc7b443e2ebc90abc45490b8fc271becc2 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 14:58:12 -0400 Subject: [PATCH 02/19] Fix undefined shift in SimpleDeserializer::readS32 The signed integer deserialization code used a signed temporary value while assembling bytes: tmp = (tmp << 8) | byte; For negative values, tmp was initialized to -1 for sign extension, causing a left shift of a negative value, which is undefined behavior in C++. Use an unsigned temporary while constructing the 32-bit representation and convert to qint32 only after all bytes have been assembled. This preserves the existing two's complement sign handling while avoiding undefined signed shifts. Fixes static analysis (cppcheck) warning about shifting a negative value. Signed-off-by: Robin Getz --- sdrbase/util/simpleserializer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdrbase/util/simpleserializer.cpp b/sdrbase/util/simpleserializer.cpp index 77857b021..822e74382 100644 --- a/sdrbase/util/simpleserializer.cpp +++ b/sdrbase/util/simpleserializer.cpp @@ -340,7 +340,7 @@ setInvalid: bool SimpleDeserializer::readS32(quint32 id, qint32* result, qint32 def) const { uint readOfs; - qint32 tmp; + quint32 tmp; Elements::const_iterator it = m_elements.constFind(id); if(it == m_elements.constEnd()) goto returnDefault; @@ -354,10 +354,10 @@ bool SimpleDeserializer::readS32(quint32 id, qint32* result, qint32 def) const for(uint i = 0; i < it->length; i++) { quint8 byte = readByte(&readOfs); if((i == 0) && (byte & 0x80)) - tmp = -1; + tmp = 0xFFFFFFFF; tmp = (tmp << 8) | byte; } - *result = tmp; + *result = static_cast(tmp); return true; returnDefault: From 1330a0639d2496db0a65ed43b52a8c99bff9ed92 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 15:10:48 -0400 Subject: [PATCH 03/19] Fix undefined left shift in SimpleDeserializer::readS64 The signed 64-bit deserialization code used a signed temporary value while assembling bytes: tmp = (tmp << 8) | byte; For negative values, tmp was initialized to -1 for sign extension. Left-shifting this negative value is undefined behavior in C++. Use an unsigned temporary while constructing the 64-bit representation and convert to qint64 after all bytes have been assembled. This preserves the existing two's complement sign handling while avoiding undefined behavior. Fixes static analysis warning about shifting a negative value. Signed-off-by: Robin Getz --- sdrbase/util/simpleserializer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdrbase/util/simpleserializer.cpp b/sdrbase/util/simpleserializer.cpp index 822e74382..0ced52faa 100644 --- a/sdrbase/util/simpleserializer.cpp +++ b/sdrbase/util/simpleserializer.cpp @@ -392,7 +392,7 @@ returnDefault: bool SimpleDeserializer::readS64(quint32 id, qint64* result, qint64 def) const { uint readOfs; - qint64 tmp; + quint64 tmp; Elements::const_iterator it = m_elements.constFind(id); if(it == m_elements.constEnd()) goto returnDefault; @@ -406,10 +406,10 @@ bool SimpleDeserializer::readS64(quint32 id, qint64* result, qint64 def) const for(uint i = 0; i < it->length; i++) { quint8 byte = readByte(&readOfs); if((i == 0) && (byte & 0x80)) - tmp = -1; + tmp = 0xFFFFFFFFFFFFFFFFULL; tmp = (tmp << 8) | byte; } - *result = tmp; + *result = static_cast(tmp); return true; returnDefault: From 11be1bb1e712a7f5281589e40d1844946e208055 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 16:44:34 -0400 Subject: [PATCH 04/19] deviceapi: Avoid invalid iterator erase in removeBuddy In std::vector::erase, The iterator pos must be valid and dereferenceable. Thus the end() iterator (which is valid, but is not dereferenceable) cannot be used as a value for pos. Protect against that by checking the result of std::find() before erasing a buddy entry. The buddy should always be present when removeBuddy() is called, but avoid undefined behavior if that assumption is violated. Signed-off-by: Robin Getz --- sdrbase/device/deviceapi.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/sdrbase/device/deviceapi.cpp b/sdrbase/device/deviceapi.cpp index 9e08b0723..d969272ba 100644 --- a/sdrbase/device/deviceapi.cpp +++ b/sdrbase/device/deviceapi.cpp @@ -774,13 +774,25 @@ void DeviceAPI::removeBuddy(DeviceAPI* buddy) { switch(buddy->m_streamType) { case StreamSingleRx: - m_sourceBuddies.erase(std::find(m_sourceBuddies.begin(), m_sourceBuddies.end(), buddy)); + { + auto it = std::find(m_sourceBuddies.begin(), m_sourceBuddies.end(), buddy); + if (it != m_sourceBuddies.end()) + { + m_sourceBuddies.erase(it); + } break; + } case StreamSingleTx: - m_sinkBuddies.erase(std::find(m_sinkBuddies.begin(), m_sinkBuddies.end(), buddy)); + { + auto it = std::find(m_sinkBuddies.begin(), m_sinkBuddies.end(), buddy); + if (it != m_sinkBuddies.end()) + { + m_sinkBuddies.erase(it); + } break; + } default: - qDebug("DeviceAPI::removeSourceBuddy: buddy %s(%s) is not of single Rx or Tx type", + qDebug("DeviceAPI::removeBuddy: buddy %s(%s) is not of single Rx or Tx type", qPrintable(buddy->getHardwareId()), qPrintable(buddy->getSamplingDeviceSerial())); return; From 0928de3b7becb2c03c3e57464a33ab640efbc7fe Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 17:06:39 -0400 Subject: [PATCH 05/19] deviceapi: Avoid iterator invalidation when clearing buddy lists Fix cppcheck warning: Using iterator to member container 'm_sinkBuddies' that may be invalid clearBuddiesLists() was iterating directly over m_sourceBuddies and m_sinkBuddies while calling removeBuddy(), which modifies the buddy relationship lists. This could invalidate the active iterator and result in undefined behavior. The issue could lead to intermittent failures during buddy cleanup operations, such as device removal, device reload, or application shutdown, depending on container state and timing. Iterate over copies of the buddy lists so that removing relationships does not affect the iterators used for traversal. Signed-off-by: Robin Getz --- sdrbase/device/deviceapi.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sdrbase/device/deviceapi.cpp b/sdrbase/device/deviceapi.cpp index d969272ba..9f6cd2921 100644 --- a/sdrbase/device/deviceapi.cpp +++ b/sdrbase/device/deviceapi.cpp @@ -801,32 +801,35 @@ void DeviceAPI::removeBuddy(DeviceAPI* buddy) void DeviceAPI::clearBuddiesLists() { - auto itSource = m_sourceBuddies.begin(); - auto itSink = m_sinkBuddies.begin(); + // Make copies before iterating because removeBuddy() modifies the buddy + // relationship lists. Iterating directly over m_sourceBuddies/m_sinkBuddies + // could invalidate iterators while the relationships are being removed. + auto sourceCopy = m_sourceBuddies; + auto sinkCopy = m_sinkBuddies; bool leaderElected = false; - for (;itSource != m_sourceBuddies.end(); ++itSource) + for (auto* buddy : sourceCopy) { if (isBuddyLeader() && !leaderElected) { - (*itSource)->setBuddyLeader(true); + buddy->setBuddyLeader(true); leaderElected = true; } - (*itSource)->removeBuddy(this); + buddy->removeBuddy(this); } m_sourceBuddies.clear(); - for (;itSink != m_sinkBuddies.end(); ++itSink) + for (auto* buddy : sinkCopy) { if (isBuddyLeader() && !leaderElected) { - (*itSink)->setBuddyLeader(true); + buddy->setBuddyLeader(true); leaderElected = true; } - (*itSink)->removeBuddy(this); + buddy->removeBuddy(this); } m_sinkBuddies.clear(); From fe22e92c29b056b70bdfe02cdbf9cac210c325fd Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 17:26:51 -0400 Subject: [PATCH 06/19] leansdr: Properly initialize QPSK hist buffer Replace raw memset() initialization of hist with C++ value initialization. This avoids bypassing std::complex object initialization and ensures the history buffer contains valid constructed objects when HIST_FLOAT is enabled. The previous memset() relied on the in-memory representation of std::complex and could leave non-trivial objects improperly initialized. While this typically behaved as expected with common implementations, it was not valid C++ object initialization. pointed out by cppcheck as: Using 'memset' on struct that contains a 'std::complex' Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/leansdr/sdr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/channelrx/demoddatv/leansdr/sdr.h b/plugins/channelrx/demoddatv/leansdr/sdr.h index 42f555ee3..d35dcbd70 100644 --- a/plugins/channelrx/demoddatv/leansdr/sdr.h +++ b/plugins/channelrx/demoddatv/leansdr/sdr.h @@ -1472,6 +1472,7 @@ struct fast_qpsk_receiver : runnable meas_decimation(1048576), pll_adjustment(1.0), allow_drift(false), + hist{}, in(_in), out(_out, chunk_size), mu(0), @@ -1482,7 +1483,6 @@ struct fast_qpsk_receiver : runnable set_freq(0); freq_out = _freq_out ? new pipewriter(*_freq_out) : nullptr; cstln_out = _cstln_out ? new pipewriter>(*_cstln_out) : nullptr; - memset(hist, 0, sizeof(hist)); init_lookup_tables(); } From bdf0fa0202e7285deaf373669d89c7dbb4ef5013 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 18:05:44 -0400 Subject: [PATCH 07/19] valuedialz: Fix signed/unsigned conversion when editing negative values Fix a signed/unsigned arithmetic issue in ValueDialZ::keyPressEvent() reported by cppcheck. The digit editing code used quint64 intermediates together with a signed sign value: int sign = m_value < 0 ? -1 : 1; setValue(sign * v); When editing negative values, the signed -1 was converted to an unsigned value before multiplication, causing the result to wrap instead of producing a negative value. Use qint64 intermediates for the digit manipulation and apply the existing sign explicitly when updating the value. This preserves correct behavior when editing negative values and avoids the unintended unsigned conversion. Signed-off-by: Robin Getz --- sdrgui/gui/valuedialz.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sdrgui/gui/valuedialz.cpp b/sdrgui/gui/valuedialz.cpp index 2b81257f6..161307797 100644 --- a/sdrgui/gui/valuedialz.cpp +++ b/sdrgui/gui/valuedialz.cpp @@ -647,14 +647,13 @@ void ValueDialZ::keyPressEvent(QKeyEvent* value) } int d = c.toLatin1() - '0'; - quint64 e = findExponent(m_cursor); - quint64 value = abs(m_value); - int sign = m_value < 0 ? -1 : 1; - quint64 v = (value / e) % 10; + qint64 e = static_cast(findExponent(m_cursor)); + qint64 value = qAbs(m_value); + qint64 v = (value / e) % 10; v = value - v * e; v += d * e; - setValue(sign*v); + setValue(m_value < 0 ? -v : v); m_cursor++; if ((m_text[m_cursor] == m_groupSeparator) || (m_text[m_cursor] == m_decSeparator)) { From 1a85082dac73769e6d9429c3b11a607d9e061dcc Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:30:42 -0400 Subject: [PATCH 08/19] ldpctool: Remove VLAs from MinSumAlgorithm Replace variable length arrays in MinSumAlgorithm::finalp() with a std::vector buffers. Variable length arrays are a compiler extension and are not part of standard C++. The replacement preserves the existing contiguous memory layout while avoiding non-standard stack allocations. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index d2af4620c..d44a9b8c9 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -23,6 +23,8 @@ Copyright 2018 Ahmet Inan #ifndef GENERIC_HH #define GENERIC_HH +#include + #include "exclusive_reduce.h" namespace ldpctool { @@ -66,13 +68,15 @@ struct MinSumAlgorithm } static void finalp(TYPE *links, int cnt) { - TYPE mags[cnt], mins[cnt]; + std::vector mags(cnt); + std::vector mins(cnt); + std::vector signs(cnt); + for (int i = 0; i < cnt; ++i) mags[i] = std::abs(links[i]); - CODE::exclusive_reduce(mags, mins, cnt, min); - TYPE signs[cnt]; - CODE::exclusive_reduce(links, signs, cnt, sign); + CODE::exclusive_reduce(mags.data(), mins.data(), cnt, min); + CODE::exclusive_reduce(links, signs.data(), cnt, sign); for (int i = 0; i < cnt; ++i) links[i] = sign(mins[i], signs[i]); From bef0b8184ea273c168e8a7165d2435764af3617f Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 19:16:31 -0400 Subject: [PATCH 09/19] vorlocalizer: Fix round robin plan sorting comparator The channel count comparison in getChannelsByDevice() accidentally used the first plan's channel count for both operands. This caused the comparator to always treat the channel counts as equal and sort only by bandwidth. Use the second plan's channel count when comparing RRTurnPlans so plans are ordered correctly by number of channels before applying the bandwidth tie-breaker. Signed-off-by: Robin Getz --- plugins/feature/vorlocalizer/vorlocalizerworker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/feature/vorlocalizer/vorlocalizerworker.cpp b/plugins/feature/vorlocalizer/vorlocalizerworker.cpp index f2deb09a3..e12cf071b 100644 --- a/plugins/feature/vorlocalizer/vorlocalizerworker.cpp +++ b/plugins/feature/vorlocalizer/vorlocalizerworker.cpp @@ -652,7 +652,7 @@ void VorLocalizerWorker::getChannelsByDevice( bool operator()(const RRTurnPlan& a, const RRTurnPlan& b) { unsigned int nbChannelsA = a.m_channels.size(); - unsigned int nbChannelsB = a.m_channels.size(); + unsigned int nbChannelsB = b.m_channels.size(); if (nbChannelsA == nbChannelsB) { return a.m_bandwidth > b.m_bandwidth; From a1391d52a2303eeb41dccbe0b8bb96ecb150daaa Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:37:39 -0400 Subject: [PATCH 10/19] ldpctool: Remove VLAs from MinSumAlgorithm Replace variable length arrays in the float specialization of MinSumAlgorithm::finalp() with std::vector storage. This removes reliance on compiler VLA extensions and keeps the temporary buffers managed by standard C++ containers. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index d44a9b8c9..dc84fec0f 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -121,18 +121,20 @@ struct MinSumAlgorithm static void finalp(float *links, int cnt) { int mask = 0x80000000; - float mags[cnt], mins[cnt]; + std::vector mags(cnt), mins(cnt); + std::vector signs(cnt); + for (int i = 0; i < cnt; ++i) mags[i] = std::abs(links[i]); - CODE::exclusive_reduce(mags, mins, cnt, min); - int signs[cnt]; - CODE::exclusive_reduce(reinterpret_cast(links), signs, cnt, xor_); + CODE::exclusive_reduce(mags.data(), mins.data(), cnt, min); + CODE::exclusive_reduce(reinterpret_cast(links), signs.data(), cnt, xor_); + for (int i = 0; i < cnt; ++i) signs[i] &= mask; for (int i = 0; i < cnt; ++i) - reinterpret_cast(links)[i] = signs[i] | reinterpret_cast(mins)[i]; + reinterpret_cast(links)[i] = signs[i] | reinterpret_cast(mins.data())[i]; } static float sign(float a, float b) { From 6de853d3d189631c16ba18a7597db3883c8f2287 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:40:25 -0400 Subject: [PATCH 11/19] ldpctool: Remove VLAs from MinSumAlgorithm Replace variable length arrays in the int8_t specialization of MinSumAlgorithm::finalp() with a single std::vector scratch buffer. This removes reliance on compiler VLA extensions while preserving the existing contiguous temporary buffer layout. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index dc84fec0f..1cae14716 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -199,13 +199,17 @@ struct MinSumAlgorithm } static void finalp(int8_t *links, int cnt) { - int8_t mags[cnt], mins[cnt]; + std::vector scratch(3 * cnt); + int8_t *mags = scratch.data(); + int8_t *mins = mags + cnt; + int8_t *signs = mins + cnt; + for (int i = 0; i < cnt; ++i) mags[i] = sqabs(links[i]); - CODE::exclusive_reduce(mags, mins, cnt, min); - int8_t signs[cnt]; + CODE::exclusive_reduce(mags, mins, cnt, min); CODE::exclusive_reduce(links, signs, cnt, xor_); + for (int i = 0; i < cnt; ++i) signs[i] |= 127; From 1f628755638c7404b66e25b3d2fcddc612789feb Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:42:59 -0400 Subject: [PATCH 12/19] ldpctool: Remove VLAs from OffsetMinSumAlgorithm Replace variable length arrays in OffsetMinSumAlgorithm::finalp() with a std::vector buffers. This removes reliance on compiler VLA extensions while preserving the existing contiguous temporary buffer layout. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index 1cae14716..489a36edb 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -248,13 +248,15 @@ struct OffsetMinSumAlgorithm static void finalp(TYPE *links, int cnt) { TYPE beta = 0.5 * FACTOR; - TYPE mags[cnt], mins[cnt]; + std::vector mags(cnt); + std::vector mins(cnt); + std::vector signs(cnt); + for (int i = 0; i < cnt; ++i) mags[i] = std::max(std::abs(links[i]) - beta, TYPE(0)); - CODE::exclusive_reduce(mags, mins, cnt, min); - TYPE signs[cnt]; - CODE::exclusive_reduce(links, signs, cnt, sign); + CODE::exclusive_reduce(mags.data(), mins.data(), cnt, min); + CODE::exclusive_reduce(links, signs.data(), cnt, sign); for (int i = 0; i < cnt; ++i) links[i] = sign(mins[i], signs[i]); From 4b3bf214180b1b2a7e07fbc1300dd64179a159cc Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:44:38 -0400 Subject: [PATCH 13/19] ldpctool: Remove VLAs from OffsetMinSumAlgorithm Replace variable length arrays in the int8_t FACTOR specialization of OffsetMinSumAlgorithm::finalp() with a single std::vector scratch buffer. This removes reliance on compiler VLA extensions while preserving the existing contiguous temporary buffer layout. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index 489a36edb..7a6839816 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -327,12 +327,15 @@ struct OffsetMinSumAlgorithm static void finalp(int8_t *links, int cnt) { int8_t beta = std::nearbyint(0.5 * FACTOR); - int8_t mags[cnt], mins[cnt]; + std::vector scratch(3 * cnt); + int8_t *mags = scratch.data(); + int8_t *mins = mags + cnt; + int8_t *signs = mins + cnt; + for (int i = 0; i < cnt; ++i) mags[i] = subu(sqabs(links[i]), beta); CODE::exclusive_reduce(mags, mins, cnt, min); - int8_t signs[cnt]; CODE::exclusive_reduce(links, signs, cnt, xor_); for (int i = 0; i < cnt; ++i) signs[i] |= 127; From 4ccc7a9bfd0ea46c81b21c906ca19a45377aaad3 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:46:46 -0400 Subject: [PATCH 14/19] ldpctool: Remove VLA from MinSumCAlgorithm Replace the variable length temporary array in MinSumCAlgorithm::finalp() with a std::vector buffer. This removes reliance on compiler VLA extensions and uses standard C++ storage for the temporary reduction buffer. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index 7a6839816..9e53d889d 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -391,8 +391,8 @@ struct MinSumCAlgorithm } static void finalp(TYPE *links, int cnt) { - TYPE tmp[cnt]; - CODE::exclusive_reduce(links, tmp, cnt, min); + std::vector tmp(cnt); + CODE::exclusive_reduce(links, tmp.data(), cnt, min); for (int i = 0; i < cnt; ++i) links[i] = tmp[i]; } From 8ac0485e53964b34a309550fd4c99a517f110bae Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:48:29 -0400 Subject: [PATCH 15/19] ldpctool: Remove VLAs from MinSumCAlgorithm Replace the variable length temporary array in the float FACTOR specialization of MinSumCAlgorithm::finalp() with a std::vector buffer. This removes reliance on compiler VLA extensions and uses standard C++ storage for the temporary reduction buffer. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index 9e53d889d..b00939e46 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -447,8 +447,8 @@ struct MinSumCAlgorithm } static void finalp(float *links, int cnt) { - float tmp[cnt]; - CODE::exclusive_reduce(links, tmp, cnt, min); + std::vector tmp(cnt); + CODE::exclusive_reduce(links, tmp.data(), cnt, min); for (int i = 0; i < cnt; ++i) links[i] = tmp[i]; } From 7e26f86aa6982c27448c6795089e19cbede46978 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:50:53 -0400 Subject: [PATCH 16/19] ldpctool: Remove VLAs from MinSumCAlgorithm Replace the variable length temporary array in the int8_t FACTOR specialization of MinSumCAlgorithm::finalp() with a std::vector buffer. This removes reliance on compiler VLA extensions and uses standard C++ storage for the temporary reduction buffer. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index b00939e46..066ffd83f 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -544,8 +544,8 @@ struct MinSumCAlgorithm } static void finalp(int8_t *links, int cnt) { - int8_t tmp[cnt]; - CODE::exclusive_reduce(links, tmp, cnt, min); + std::vector tmp(cnt); + CODE::exclusive_reduce(links, tmp.data(), cnt, min); for (int i = 0; i < cnt; ++i) links[i] = tmp[i]; } From e4561aeb778bab479721fe750fce4d36ccc1f856 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:53:10 -0400 Subject: [PATCH 17/19] ldpctool: Remove VLAs from LogDomainSPA Replace variable length arrays in LogDomainSPA::finalp() with std::vector buffers. This removes reliance on compiler VLA extensions while preserving the existing contiguous temporary buffer layout. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index 066ffd83f..247f39bdc 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -589,13 +589,15 @@ struct LogDomainSPA } static void finalp(TYPE *links, int cnt) { - TYPE mags[cnt], sums[cnt]; + std::vector mags(cnt); + std::vector sums(cnt); + std::vector signs(cnt); + for (int i = 0; i < cnt; ++i) mags[i] = phi(std::abs(links[i])); - CODE::exclusive_reduce(mags, sums, cnt, add); - TYPE signs[cnt]; - CODE::exclusive_reduce(links, signs, cnt, sign); + CODE::exclusive_reduce(mags.data(), sums.data(), cnt, add); + CODE::exclusive_reduce(links, signs.data(), cnt, sign); for (int i = 0; i < cnt; ++i) links[i] = sign(phi(sums[i]), signs[i]); From 85021508f12a376ab699447bdc0ebd1bc48fb74d Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 13:58:52 -0400 Subject: [PATCH 18/19] ldpctool: Remove VLAs from LambdaMinAlgorithm Replace variable length arrays in LambdaMinAlgorithm::finalp() with std::vector storage. Update nth_element() usage to operate on vector iterators while removing the non-standard VLA usage. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index 247f39bdc..3a77dd424 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -643,12 +643,12 @@ struct LambdaMinAlgorithm static void finalp(TYPE *links, int cnt) { typedef std::pair Pair; - Pair mags[cnt]; + std::vector mags(cnt); for (int i = 0; i < cnt; ++i) mags[i] = Pair(std::abs(links[i]), i); - std::nth_element(mags, mags+LAMBDA, mags+cnt, [](Pair a, Pair b){ return a.first < b.first; }); + std::nth_element(mags.begin(), mags.begin()+LAMBDA, mags.end(), [](Pair a, Pair b){ return a.first < b.first; }); - TYPE sums[cnt]; + std::vector sums(cnt); for (int i = 0; i < cnt; ++i) { int j = 0; if (i == mags[0].second) @@ -662,8 +662,8 @@ struct LambdaMinAlgorithm } } - TYPE signs[cnt]; - CODE::exclusive_reduce(links, signs, cnt, sign); + std::vector signs(cnt); + CODE::exclusive_reduce(links, signs.data(), cnt, sign); for (int i = 0; i < cnt; ++i) links[i] = sign(phi(sums[i]), signs[i]); From d122e69fba60795cf819b38f23468c690b85823a Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 14:01:12 -0400 Subject: [PATCH 19/19] ldpctool: Remove VLAs from SumProductAlgorithm Replace variable length arrays in SumProductAlgorithm::finalp() with a std::vector buffers. This removes reliance on compiler VLA extensions while preserving the existing contiguous temporary buffer layout. Signed-off-by: Robin Getz --- plugins/channelrx/demoddatv/ldpctool/generic.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demoddatv/ldpctool/generic.h b/plugins/channelrx/demoddatv/ldpctool/generic.h index 3a77dd424..78b19c4c5 100644 --- a/plugins/channelrx/demoddatv/ldpctool/generic.h +++ b/plugins/channelrx/demoddatv/ldpctool/generic.h @@ -707,10 +707,12 @@ struct SumProductAlgorithm } static void finalp(TYPE *links, int cnt) { - TYPE in[cnt], out[cnt]; + std::vector in(cnt); + std::vector out(cnt); + for (int i = 0; i < cnt; ++i) in[i] = prep(links[i]); - CODE::exclusive_reduce(in, out, cnt, mul); + CODE::exclusive_reduce(in.data(), out.data(), cnt, mul); for (int i = 0; i < cnt; ++i) links[i] = postp(out[i]); }