From f9bbb4c1bc2dd07578d423f3ce2ba3cd0b707584 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 25 Mar 2026 09:15:33 +0000 Subject: [PATCH 1/6] fix: add bounds checking to SrsInitSrs/SrsInitGrumpkinSrs to fix debug build test The CBind.CatchesExceptionAndReturnsErrorResponse test relied on undefined behavior (buffer overread) to trigger an exception. In debug builds, the UB silently reads garbage and returns success instead of throwing, causing the test to fail. Add proper bounds validation to SrsInitSrs::execute and SrsInitGrumpkinSrs::execute before accessing raw buffer pointers. This ensures the test works reliably in all build modes and eliminates the underlying UB. --- barretenberg/cpp/src/barretenberg/bbapi/bbapi_srs.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/bbapi/bbapi_srs.cpp b/barretenberg/cpp/src/barretenberg/bbapi/bbapi_srs.cpp index 365eee1bb3ae..1225e844bd4e 100644 --- a/barretenberg/cpp/src/barretenberg/bbapi/bbapi_srs.cpp +++ b/barretenberg/cpp/src/barretenberg/bbapi/bbapi_srs.cpp @@ -61,6 +61,14 @@ SrsInitSrs::Response SrsInitSrs::execute(BB_UNUSED BBApiRequest& request) && SrsInitGrumpkinSrs::Response SrsInitGrumpkinSrs::execute(BB_UNUSED BBApiRequest& request) && { + // Validate buffer size before accessing raw pointer + const size_t required_size = static_cast(num_points) * sizeof(curve::Grumpkin::AffineElement); + if (points_buf.size() < required_size) { + throw_or_abort("SrsInitGrumpkinSrs: points_buf too small (" + std::to_string(points_buf.size()) + + " bytes) for num_points=" + std::to_string(num_points) + " (need " + + std::to_string(required_size) + ")"); + } + // Parse Grumpkin affine elements from buffer std::vector points(num_points); for (uint32_t i = 0; i < num_points; ++i) { From c6926db6508a105a6a38c5d412db2bdde5f37816 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 25 Mar 2026 13:05:22 +0000 Subject: [PATCH 2/6] fix: debug build failures from SRS compression and mock pairing points Two fixes for debug build: 1. Legacy CRS fallback: when compressed CRS (bn254_g1_compressed.dat) is not available but old uncompressed CRS (bn254_g1.dat) exists, read the uncompressed format directly. This ensures tests work on machines that haven't re-downloaded the CRS after the compression change in #21112. 2. Non-throwing debug pairing checks: the stdlib PairingPoints constructor and aggregate() method perform native pairing verification in debug builds (#ifndef NDEBUG). When mock/dummy data produces invalid points (e.g. during VK generation with cleared witnesses), this threw an uncatchable exception. Wrapped these debug-only checks in try-catch so they log failures without crashing. --- .../srs/factories/get_bn254_crs.cpp | 16 ++++++++++++++++ .../stdlib/primitives/pairing_points.hpp | 17 +++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/get_bn254_crs.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/get_bn254_crs.cpp index 4b95fcefb2a9..76b4bd7da851 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/get_bn254_crs.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/get_bn254_crs.cpp @@ -221,6 +221,22 @@ std::vector get_bn254_g1_data(const std::filesystem::path& p return points; } + // Fallback: read legacy uncompressed CRS (64 bytes/point) directly + constexpr size_t UNCOMPRESSED_POINT_SIZE = 64; + auto legacy_path = path / "bn254_g1.dat"; + size_t legacy_points = get_file_size(legacy_path) / UNCOMPRESSED_POINT_SIZE; + if (legacy_points >= num_points) { + vinfo("using legacy uncompressed bn254 crs with ", legacy_points, " points at ", legacy_path); + auto legacy_data = read_file(legacy_path, num_points * UNCOMPRESSED_POINT_SIZE); + std::vector points(num_points); + bb::parallel_for([&](bb::ThreadChunk chunk) { + for (auto i : chunk.range(num_points)) { + points[i] = from_buffer(legacy_data, i * UNCOMPRESSED_POINT_SIZE); + } + }); + return points; + } + if (!allow_download && compressed_points == 0) { throw_or_abort("bn254 g1 data not found at " + path.string() + " and bb does not automatically download in this context." + diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp index c87964f35620..be213c42845c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp @@ -54,8 +54,12 @@ template struct PairingPoints { } #ifndef NDEBUG - bb::PairingPoints native_pp(P0().get_value(), P1().get_value()); - info("Are Pairing Points with tag ", tag_index, " valid? ", native_pp.check() ? "true" : "false"); + try { + bb::PairingPoints native_pp(P0().get_value(), P1().get_value()); + info("Are Pairing Points with tag ", tag_index, " valid? ", native_pp.check() ? "true" : "false"); + } catch (const std::exception&) { + info("Are Pairing Points with tag ", tag_index, " valid? false (point not on curve)"); + } #endif } @@ -210,8 +214,13 @@ template struct PairingPoints { } #ifndef NDEBUG - bb::PairingPoints native_pp(P0().get_value(), P1().get_value()); - info("Are aggregated Pairing Points with tag ", tag_index, " valid? ", native_pp.check() ? "true" : "false"); + try { + bb::PairingPoints native_pp(P0().get_value(), P1().get_value()); + info( + "Are aggregated Pairing Points with tag ", tag_index, " valid? ", native_pp.check() ? "true" : "false"); + } catch (const std::exception&) { + info("Are aggregated Pairing Points with tag ", tag_index, " valid? false (point not on curve)"); + } #endif } From 9606be2dc2231ca4385ff6f12141676d7ee9bd43 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Wed, 25 Mar 2026 13:11:10 +0000 Subject: [PATCH 3/6] chore: remove legacy CRS fallback (handled by #21972) --- .../barretenberg/srs/factories/get_bn254_crs.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/get_bn254_crs.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/get_bn254_crs.cpp index 76b4bd7da851..4b95fcefb2a9 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/get_bn254_crs.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/get_bn254_crs.cpp @@ -221,22 +221,6 @@ std::vector get_bn254_g1_data(const std::filesystem::path& p return points; } - // Fallback: read legacy uncompressed CRS (64 bytes/point) directly - constexpr size_t UNCOMPRESSED_POINT_SIZE = 64; - auto legacy_path = path / "bn254_g1.dat"; - size_t legacy_points = get_file_size(legacy_path) / UNCOMPRESSED_POINT_SIZE; - if (legacy_points >= num_points) { - vinfo("using legacy uncompressed bn254 crs with ", legacy_points, " points at ", legacy_path); - auto legacy_data = read_file(legacy_path, num_points * UNCOMPRESSED_POINT_SIZE); - std::vector points(num_points); - bb::parallel_for([&](bb::ThreadChunk chunk) { - for (auto i : chunk.range(num_points)) { - points[i] = from_buffer(legacy_data, i * UNCOMPRESSED_POINT_SIZE); - } - }); - return points; - } - if (!allow_download && compressed_points == 0) { throw_or_abort("bn254 g1 data not found at " + path.string() + " and bb does not automatically download in this context." + From c09583a1af868c49b62d92b30029e70e89e58c88 Mon Sep 17 00:00:00 2001 From: federicobarbacovi <171914500+federicobarbacovi@users.noreply.github.com> Date: Wed, 25 Mar 2026 13:21:51 +0000 Subject: [PATCH 4/6] Turn throw or abort into bb::assert_failure --- .../dsl/acir_format/chonk_recursion_constraints.test.cpp | 1 + .../cpp/src/barretenberg/ecc/curves/bn254/pairing_impl.hpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/chonk_recursion_constraints.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/chonk_recursion_constraints.test.cpp index 47af5a7c1aa4..113811ac5e1a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/chonk_recursion_constraints.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/chonk_recursion_constraints.test.cpp @@ -93,6 +93,7 @@ TEST_F(ChonkRecursionConstraintTest, GenerateRecursiveChonkVerifierVKFromConstra using VerificationKey = ChonkRecursionConstraintTest::VerificationKey; using ChonkData = ChonkRecursionConstraintTest::ChonkData; + BB_DISABLE_ASSERTS(); ChonkData chonk_data = ChonkRecursionConstraintTest::get_chonk_data(); std::shared_ptr vk_from_valid_witness; diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/pairing_impl.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/pairing_impl.hpp index 98b04e9b998e..b0f96b0982db 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/pairing_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/pairing_impl.hpp @@ -287,7 +287,7 @@ fq12 reduced_ate_pairing_batch_precomputed(const g1::affine_element* P_affines, { for (size_t i = 0; i < num_points; ++i) { if (!P_affines[i].on_curve()) { - throw_or_abort("reduced_ate_pairing_batch_precomputed: one of the points is not on the curve."); + bb::assert_failure("reduced_ate_pairing_batch_precomputed: one of the points is not on the curve."); } } @@ -307,10 +307,10 @@ fq12 reduced_ate_pairing_batch(const g1::affine_element* P_affines, bool has_infinity_pair = false; for (size_t i = 0; i < num_points; ++i) { if (!P_affines[i].on_curve()) { - throw_or_abort("reduced_ate_pairing_batch: one of the P points is not on the curve."); + bb::assert_failure("reduced_ate_pairing_batch: one of the P points is not on the curve."); } if (!Q_affines[i].on_curve()) { - throw_or_abort("reduced_ate_pairing_batch: one of the Q points is not on the curve."); + bb::assert_failure("reduced_ate_pairing_batch: one of the Q points is not on the curve."); } // If either P_i or Q_i is the point at infinity, then e(P_i, Q_i) = 1, so we can skip the calculation of From fb3140eb4662ff61adbb59450810f19aaf724e93 Mon Sep 17 00:00:00 2001 From: federicobarbacovi <171914500+federicobarbacovi@users.noreply.github.com> Date: Wed, 25 Mar 2026 13:27:09 +0000 Subject: [PATCH 5/6] Remove try catch --- .../src/barretenberg/stdlib/primitives/pairing_points.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp index be213c42845c..bda034815f32 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp @@ -54,12 +54,8 @@ template struct PairingPoints { } #ifndef NDEBUG - try { - bb::PairingPoints native_pp(P0().get_value(), P1().get_value()); - info("Are Pairing Points with tag ", tag_index, " valid? ", native_pp.check() ? "true" : "false"); - } catch (const std::exception&) { - info("Are Pairing Points with tag ", tag_index, " valid? false (point not on curve)"); - } + bb::PairingPoints native_pp(P0().get_value(), P1().get_value()); + info("Are Pairing Points with tag ", tag_index, " valid? ", native_pp.check() ? "true" : "false"); #endif } From b08d1c5da7095358e05c968c86e80bc8d185e838 Mon Sep 17 00:00:00 2001 From: federicobarbacovi <171914500+federicobarbacovi@users.noreply.github.com> Date: Thu, 26 Mar 2026 15:03:20 +0000 Subject: [PATCH 6/6] Remove try catch --- .../barretenberg/stdlib/primitives/pairing_points.hpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp index bda034815f32..c87964f35620 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/pairing_points.hpp @@ -210,13 +210,8 @@ template struct PairingPoints { } #ifndef NDEBUG - try { - bb::PairingPoints native_pp(P0().get_value(), P1().get_value()); - info( - "Are aggregated Pairing Points with tag ", tag_index, " valid? ", native_pp.check() ? "true" : "false"); - } catch (const std::exception&) { - info("Are aggregated Pairing Points with tag ", tag_index, " valid? false (point not on curve)"); - } + bb::PairingPoints native_pp(P0().get_value(), P1().get_value()); + info("Are aggregated Pairing Points with tag ", tag_index, " valid? ", native_pp.check() ? "true" : "false"); #endif }