diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp index 7a0a1298f452..fdbb7508dfa8 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp @@ -629,14 +629,14 @@ template struct alignas(32) field { BB_INLINE static field asm_sqr_with_coarse_reduction(const field& a) noexcept; BB_INLINE static field asm_add_with_coarse_reduction(const field& a, const field& b) noexcept; BB_INLINE static field asm_sub_with_coarse_reduction(const field& a, const field& b) noexcept; - BB_INLINE static void asm_self_mul_with_coarse_reduction(const field& a, const field& b) noexcept; - BB_INLINE static void asm_self_sqr_with_coarse_reduction(const field& a) noexcept; - BB_INLINE static void asm_self_add_with_coarse_reduction(const field& a, const field& b) noexcept; - BB_INLINE static void asm_self_sub_with_coarse_reduction(const field& a, const field& b) noexcept; + BB_INLINE static void asm_self_mul_with_coarse_reduction(field& a, const field& b) noexcept; + BB_INLINE static void asm_self_sqr_with_coarse_reduction(field& a) noexcept; + BB_INLINE static void asm_self_add_with_coarse_reduction(field& a, const field& b) noexcept; + BB_INLINE static void asm_self_sub_with_coarse_reduction(field& a, const field& b) noexcept; BB_INLINE static void asm_conditional_negate(field& r, uint64_t predicate) noexcept; BB_INLINE static field asm_reduce_once(const field& a) noexcept; - BB_INLINE static void asm_self_reduce_once(const field& a) noexcept; + BB_INLINE static void asm_self_reduce_once(field& a) noexcept; static constexpr uint64_t zero_reference = 0x00ULL; #endif constexpr field tonelli_shanks_sqrt() const noexcept; diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_impl_x64.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_impl_x64.hpp index 1ae46ef8acd3..9af0bf5f653f 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_impl_x64.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_impl_x64.hpp @@ -46,7 +46,7 @@ template field field::asm_mul_with_coarse_reduction(const field& return r; } -template void field::asm_self_mul_with_coarse_reduction(const field& a, const field& b) noexcept +template void field::asm_self_mul_with_coarse_reduction(field& a, const field& b) noexcept { constexpr uint64_t r_inv = T::r_inv; constexpr uint64_t modulus_0 = modulus.data[0]; @@ -141,7 +141,7 @@ template field field::asm_sqr_with_coarse_reduction(const field& return r; } -template void field::asm_self_sqr_with_coarse_reduction(const field& a) noexcept +template void field::asm_self_sqr_with_coarse_reduction(field& a) noexcept { constexpr uint64_t r_inv = T::r_inv; constexpr uint64_t modulus_0 = modulus.data[0]; @@ -227,7 +227,7 @@ template field field::asm_add_with_coarse_reduction(const field& return r; } -template void field::asm_self_add_with_coarse_reduction(const field& a, const field& b) noexcept +template void field::asm_self_add_with_coarse_reduction(field& a, const field& b) noexcept { constexpr uint64_t twice_not_modulus_0 = twice_not_modulus.data[0]; constexpr uint64_t twice_not_modulus_1 = twice_not_modulus.data[1]; @@ -277,7 +277,7 @@ template field field::asm_sub_with_coarse_reduction(const field& return r; } -template void field::asm_self_sub_with_coarse_reduction(const field& a, const field& b) noexcept +template void field::asm_self_sub_with_coarse_reduction(field& a, const field& b) noexcept { constexpr uint64_t twice_modulus_0 = twice_modulus.data[0]; constexpr uint64_t twice_modulus_1 = twice_modulus.data[1]; @@ -353,7 +353,7 @@ template field field::asm_reduce_once(const field& a) noexcept return r; } -template void field::asm_self_reduce_once(const field& a) noexcept +template void field::asm_self_reduce_once(field& a) noexcept { constexpr uint64_t not_modulus_0 = not_modulus.data[0]; constexpr uint64_t not_modulus_1 = not_modulus.data[1]; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.cpp index 850ab550ad94..ef826e3ad6b2 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/databus/databus.cpp @@ -45,7 +45,9 @@ field_t databus::bus_vector::operator[](const field_pt& index) // Ensure the read is valid auto raw_index = static_cast(uint256_t(index.get_value()).data[0]); if (raw_index >= length) { + // Set a failure when the index is out of bounds. Return early to avoid OOB vector access. context->failure("bus_vector: access out of bounds"); + return field_pt::from_witness_index(context, context->zero_idx()); } // The read index must be a witness; if constant, add it as a constant variable diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/ram_table.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/ram_table.cpp index 1c6d3e403fc8..9d1a29e7103b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/ram_table.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/ram_table.cpp @@ -180,9 +180,9 @@ template field_t ram_table::read(const fiel const auto native_index = uint256_t(index.get_value()); if (native_index >= length) { - // set a failure when the index is out of bounds. another error will be thrown when we try to call - // `read_RAM_array`. + // Set a failure when the index is out of bounds. Return early to avoid OOB vector access. context->failure("ram_table: RAM array access out of bounds"); + return field_pt::from_witness_index(context, context->zero_idx()); } if (!check_indices_initialized()) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/rom_table.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/rom_table.cpp index e6fbf9a5486c..6efe0cb06a56 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/rom_table.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/rom_table.cpp @@ -178,7 +178,9 @@ template field_t rom_table::operator[](cons const auto native_index = uint256_t(index.get_value()); if (native_index >= length) { + // Set a failure when the index is out of bounds. Return early to avoid OOB vector access. context->failure("rom_table: ROM array access out of bounds"); + return field_pt::from_witness_index(context, context->zero_idx()); } uint32_t output_idx = context->read_ROM_array(rom_id, index.get_witness_index()); @@ -188,7 +190,6 @@ template field_t rom_table::operator[](cons // If the index is legitimate, restore the tag if (native_index < length) { - element.set_origin_tag(_tags[cast_index]); } return element; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/rom_table.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/rom_table.test.cpp index 30fcebc646d7..f42d8900f89d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/rom_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/rom_table.test.cpp @@ -167,3 +167,28 @@ TEST(RomTable, OobConstantIndexDoesNotCrashRegression) EXPECT_TRUE(builder.failed()); } + +/** + * @brief Regression: OOB witness-index read must soft-fail without OOB vector access. + */ +TEST(RomTable, OobWitnessIndexDoesNotCrashRegression) +{ + using Builder = UltraCircuitBuilder; + using field_ct = stdlib::field_t; + using witness_ct = stdlib::witness_t; + using rom_table_ct = stdlib::rom_table; + + Builder builder; + + std::vector table_values; + table_values.emplace_back(witness_ct(&builder, bb::fr(1))); + table_values.emplace_back(witness_ct(&builder, bb::fr(2))); + table_values.emplace_back(witness_ct(&builder, bb::fr(3))); + rom_table_ct table(table_values); + + // OOB witness index — should soft-fail, not crash + field_ct oob_index = witness_ct(&builder, bb::fr(100000000)); + table[oob_index]; + + EXPECT_TRUE(builder.failed()); +} diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/twin_rom_table.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/twin_rom_table.cpp index 6788a77a3252..57c783c8ba59 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/twin_rom_table.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/memory/twin_rom_table.cpp @@ -150,7 +150,10 @@ std::array, 2> twin_rom_table::operator[](const field_ initialize_table(); if (uint256_t(index.get_value()) >= length) { + // Set a failure when the index is out of bounds. Return early to avoid OOB vector access. context->failure("twin_rom_table: ROM array access out of bounds"); + return { field_pt::from_witness_index(context, context->zero_idx()), + field_pt::from_witness_index(context, context->zero_idx()) }; } auto output_indices = context->read_ROM_array_pair(rom_id, index.get_witness_index()); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp index 607a0d868c6f..2bea47b140da 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/zk_sumcheck_data.hpp @@ -151,7 +151,7 @@ template struct ZKSumcheckData { } total_sum *= scaling_factor; - return { total_sum + constant_term * (static_cast(1) << libra_univariates.size()), scaling_factor }; + return { total_sum + constant_term * (1UL << libra_univariates.size()), scaling_factor }; } /**