Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/ci3_labels_to_env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ function main {
fi
fi
fi
elif has_label "ci-skip"; then
echo "WARNING: Skipping CI due to the ci-skipok label! Make sure this is intended!" >&2
ci_mode="skip"
elif has_label "ci-release-pr"; then
ci_mode="release-pr"
elif has_label "ci-full"; then
Expand All @@ -73,9 +76,6 @@ function main {
ci_mode="barretenberg"
elif [[ "${GITHUB_REF:-}" == refs/tags/v* ]]; then
ci_mode="release"
elif has_label "ci-skip"; then
echo "WARNING: Skipping CI due to the ci-skipok label! Make sure this is intended!" >&2
ci_mode="skip"
else
ci_mode="fast"
fi
Expand Down
71 changes: 71 additions & 0 deletions barretenberg/cpp/src/barretenberg/bbapi/bbapi.test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "barretenberg/bbapi/bbapi.hpp"
#include "barretenberg/api/file_io.hpp"
#include "barretenberg/bbapi/bbapi_shared.hpp"
#include "barretenberg/chonk/private_execution_steps.hpp"
#include "barretenberg/common/serialize.hpp"
#include "barretenberg/common/utils.hpp"
#include "barretenberg/serialize/test_helper.hpp"
Expand Down Expand Up @@ -113,3 +114,73 @@ TEST(BBApiInputValidation, VkWithCorrectSizeAccepted)
std::vector<uint8_t> good_vk(expected_size, 0);
EXPECT_NO_THROW(bbapi::validate_vk_size<VK>(good_vk));
}

// Helper: pack a vector of PrivateExecutionStepRaw into a byte buffer via msgpack.
namespace {
std::vector<uint8_t> pack_steps(const std::vector<PrivateExecutionStepRaw>& steps)
{
std::stringstream ss;
msgpack::pack(ss, steps);
const std::string s = ss.str();
return { s.begin(), s.end() };
}
} // namespace

TEST(BBApiInputValidation, MsgpackParseUncompressedAcceptsCleanInput)
{
PrivateExecutionStepRaw step{
.bytecode = { 0xCA, 0xFE }, .witness = { 0xBE, 0xEF }, .vk = {}, .function_name = "test_fn"
};

auto buf = pack_steps({ step });
auto result = PrivateExecutionStepRaw::parse_uncompressed(buf);

ASSERT_EQ(result.size(), 1);
EXPECT_EQ(result[0].bytecode, step.bytecode);
EXPECT_EQ(result[0].witness, step.witness);
EXPECT_EQ(result[0].function_name, "test_fn");
}

TEST(BBApiInputValidation, MsgpackParseUncompressedRejectsTrailingData)
{
PrivateExecutionStepRaw step{ .bytecode = {}, .witness = {}, .vk = {}, .function_name = "x" };

auto buf = pack_steps({ step });
buf.push_back(0x00);

EXPECT_THROW(PrivateExecutionStepRaw::parse_uncompressed(buf), std::invalid_argument);
}

TEST(BBApiInputValidation, MsgpackLoadAcceptsCleanFile)
{
PrivateExecutionStepRaw step{ .bytecode = { 1, 2, 3 }, .witness = { 4, 5 }, .vk = {}, .function_name = "file_fn" };

auto buf = pack_steps({ step });

auto tmp = std::filesystem::temp_directory_path() / "bb_test_clean.msgpack";
std::ofstream out(tmp, std::ios::binary);
out.write(reinterpret_cast<const char*>(buf.data()), static_cast<std::streamsize>(buf.size()));
out.close();

auto result = PrivateExecutionStepRaw::load(tmp);
std::filesystem::remove(tmp);

ASSERT_EQ(result.size(), 1);
EXPECT_EQ(result[0].function_name, "file_fn");
}

TEST(BBApiInputValidation, MsgpackLoadRejectsTrailingData)
{
PrivateExecutionStepRaw step{ .bytecode = {}, .witness = {}, .vk = {}, .function_name = "x" };

auto buf = pack_steps({ step });
buf.push_back(0x00);

auto tmp = std::filesystem::temp_directory_path() / "bb_test_tailed.msgpack";
std::ofstream out(tmp, std::ios::binary);
out.write(reinterpret_cast<const char*>(buf.data()), static_cast<std::streamsize>(buf.size()));
out.close();

EXPECT_THROW(PrivateExecutionStepRaw::load(tmp), std::invalid_argument);
std::filesystem::remove(tmp);
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,12 @@ template <typename T> T unpack_from_file(const std::filesystem::path& filename)
T result;
std::string encoded_data(fsize, '\0');
fin.read(encoded_data.data(), static_cast<std::streamsize>(fsize));
msgpack::unpack(encoded_data.data(), fsize).get().convert(result);
std::size_t offset = 0;
msgpack::unpack(encoded_data.data(), fsize, offset).get().convert(result);
if (offset != fsize) {
THROW std::invalid_argument("msgpack input has trailing data (" + std::to_string(fsize - offset) +
" extra bytes)");
}
return result;
}

Expand Down Expand Up @@ -121,7 +126,12 @@ std::vector<PrivateExecutionStepRaw> PrivateExecutionStepRaw::parse_uncompressed
{
std::vector<PrivateExecutionStepRaw> raw_steps;
// Read with msgpack
msgpack::unpack(reinterpret_cast<const char*>(buf.data()), buf.size()).get().convert(raw_steps);
std::size_t offset = 0;
msgpack::unpack(reinterpret_cast<const char*>(buf.data()), buf.size(), offset).get().convert(raw_steps);
if (offset != buf.size()) {
THROW std::invalid_argument("msgpack input has trailing data (" + std::to_string(buf.size() - offset) +
" extra bytes)");
}
// Unlike load_and_decompress, we don't need to decompress the bytecode and witness fields
return raw_steps;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <limits>
namespace bb::numeric {

// De Bruijn MSB. Returns 0 for input 0 (by convention; many callers rely on this).
// from http://supertech.csail.mit.edu/papers/debruijn.pdf
constexpr inline uint32_t get_msb32(const uint32_t in)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ template <class base_uint>
std::pair<uintx<base_uint>, uintx<base_uint>> uintx<base_uint>::divmod_base(const uintx& b) const

{
BB_ASSERT_DEBUG(b != 0);
BB_ASSERT(b != 0);
if (*this == 0) {
return { uintx(0), uintx(0) };
}
Expand Down
2 changes: 2 additions & 0 deletions barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ template <typename Fr> class Polynomial {
*/
static Polynomial shiftable(size_t virtual_size)
{
BB_ASSERT_GTE(virtual_size, NUM_ZERO_ROWS, "shiftable virtual_size must be >= NUM_ZERO_ROWS");
return Polynomial(
/*actual size*/ virtual_size - NUM_ZERO_ROWS, virtual_size, /*shiftable offset*/ NUM_ZERO_ROWS);
}
Expand All @@ -114,6 +115,7 @@ template <typename Fr> class Polynomial {
*/
static Polynomial shiftable(size_t size, size_t virtual_size)
{
BB_ASSERT_GTE(size, NUM_ZERO_ROWS, "shiftable size must be >= NUM_ZERO_ROWS");
return Polynomial(/*actual size*/ size - NUM_ZERO_ROWS, virtual_size, /*shiftable offset*/ NUM_ZERO_ROWS);
}
// Allow polynomials to be entirely reset/dormant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@
#include <math.h>
#include <memory.h>
#include <memory>
#include <mutex>

namespace bb::polynomial_arithmetic {

namespace {

template <typename Fr> std::shared_ptr<Fr[]> get_scratch_space(const size_t num_elements)
{
static std::mutex scratch_mutex;
std::lock_guard lock(scratch_mutex);
static std::shared_ptr<Fr[]> working_memory = nullptr;
static size_t current_size = 0;
if (num_elements > current_size) {
Expand Down Expand Up @@ -52,6 +55,8 @@ void scale_by_generator(Fr* coeffs,
const Fr& generator_shift,
const size_t generator_size)
{
BB_ASSERT(generator_size % domain.num_threads == 0,
"generator_size must be divisible by num_threads to avoid silently skipping elements");
parallel_for(domain.num_threads, [&](size_t j) {
Fr thread_shift = generator_shift.pow(static_cast<uint64_t>(j * (generator_size / domain.num_threads)));
Fr work_generator = generator_start * thread_shift;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ template <typename FF> struct RowDisablingPolynomial {
* @param log_circuit_size
* @return FF
*/
static FF evaluate_at_challenge(std::vector<FF> multivariate_challenge, const size_t log_circuit_size)
static FF evaluate_at_challenge(std::span<const FF> multivariate_challenge, const size_t log_circuit_size)
{
FF evaluation_at_multivariate_challenge{ 1 };

Expand All @@ -188,7 +188,7 @@ template <typename FF> struct RowDisablingPolynomial {
* @param padding_indicator_array An array with first log_n entries equal to 1, and the remaining entries are 0.
* @return FF
*/
static FF evaluate_at_challenge(std::span<FF> multivariate_challenge,
static FF evaluate_at_challenge(std::span<const FF> multivariate_challenge,
const std::vector<FF>& padding_indicator_array)
{
FF evaluation_at_multivariate_challenge{ 1 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ template <class Curve> class EcdsaTests : public ::testing::Test {

if (random_signature) {
// Logging in case of random signature
info("The private key used generate this signature is: ", private_key);
info("The private key used generate this signature is: ", account.private_key);
}

return { account, signature };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,7 @@ void field_t<Builder>::evaluate_linear_identity(
Builder* ctx = validate_context(a.context, b.context, c.context, d.context);

if (a.is_constant() && b.is_constant() && c.is_constant() && d.is_constant()) {
BB_ASSERT_EQ(a.get_value() + b.get_value() + c.get_value() + d.get_value(), 0);
BB_ASSERT_EQ(a.get_value() + b.get_value() + c.get_value() + d.get_value(), 0, msg);
return;
}

Expand Down Expand Up @@ -1136,7 +1136,7 @@ void field_t<Builder>::evaluate_polynomial_identity(
const field_t& a, const field_t& b, const field_t& c, const field_t& d, const std::string& msg)
{
if (a.is_constant() && b.is_constant() && c.is_constant() && d.is_constant()) {
BB_ASSERT((a.get_value() * b.get_value() + c.get_value() + d.get_value()).is_zero());
BB_ASSERT((a.get_value() * b.get_value() + c.get_value() + d.get_value()).is_zero(), msg);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,12 @@ template <typename Builder_> class field_t {
// (this.v * this.mul + this.add) * inverse.v == 1;
// created by applying `assert_is_not_zero` to `*this` coincides with the constraint created by
// `divide_no_zero_check`, hence we can safely apply the latter instead of `/` operator.
auto* ctx = get_context();
if (is_constant()) {
BB_ASSERT(!get_value().is_zero(), "field_t::invert denominator is constant 0");
return field_t(fr::one()).divide_no_zero_check(*this);
}

auto* ctx = get_context();
if (get_value().is_zero() && !ctx->failed()) {
ctx->failure("field_t::invert denominator is 0");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ template <typename Builder> void ram_table<Builder>::write(const field_pt& index
initialize_table();

if (uint256_t(index.get_value()) >= length) {
// set a failure when the index is out of bounds. an error will be thrown when we try to call either
// `init_RAM_element` or `write_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 index_wire = index;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,28 @@ TYPED_TEST(RamTableTests, RamTableReadWriteConsistency)
bool verified = CircuitChecker::check(builder);
EXPECT_EQ(verified, true);
}

/**
* @brief OOB write soft-fails correctly without crashing.
*/
TEST(RamTable, OobWriteDoesNotCrashRegression)
{
using Builder = UltraCircuitBuilder;
using field_ct = stdlib::field_t<Builder>;
using ram_table_ct = stdlib::ram_table<Builder>;

Builder builder;

const size_t table_size = 3;
std::vector<field_ct> init_values(table_size, field_ct(0));
ram_table_ct table(&builder, init_values);

for (size_t i = 0; i < table_size; ++i) {
table.write(i, field_ct(bb::fr(i)));
}

// OOB write — should soft-fail, not crash
table.write(field_ct(100000000), field_ct(bb::fr(42)));

EXPECT_TRUE(builder.failed());
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ template <typename Builder> field_t<Builder> rom_table<Builder>::operator[](cons
if (index >= length) {
BB_ASSERT(context != nullptr);
context->failure("rom_table: ROM array access out of bounds");
return raw_entries[0];
}

return raw_entries[index];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,27 @@ TYPED_TEST(RomTableTests, RomCopy)
bool verified = CircuitChecker::check(builder);
EXPECT_EQ(verified, true);
}

/**
* @brief OOB constant-index access soft-fails correctly without crashing.
*/
TEST(RomTable, OobConstantIndexDoesNotCrashRegression)
{
using Builder = UltraCircuitBuilder;
using field_ct = stdlib::field_t<Builder>;
using witness_ct = stdlib::witness_t<Builder>;
using rom_table_ct = stdlib::rom_table<Builder>;

Builder builder;

std::vector<field_ct> 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 constant index — should soft-fail, not crash
table[static_cast<size_t>(100000000)];

EXPECT_TRUE(builder.failed());
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ std::array<field_t<Builder>, 2> twin_rom_table<Builder>::operator[](const size_t
if (index >= length) {
BB_ASSERT(context != nullptr);
context->failure("twin_rom_table: ROM array access out of bounds");
return raw_entries[0];
}

return raw_entries[index];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,27 @@ TYPED_TEST(TwinRomTableTests, ReadWriteConsistency)
bool verified = CircuitChecker::check(builder);
EXPECT_EQ(verified, true);
}

/**
* @brief OOB constant-index access soft-fails correctly without crashing.
*/
TEST(TwinRomTable, OobConstantIndexDoesNotCrashRegression)
{
using Builder = UltraCircuitBuilder;
using field_ct = stdlib::field_t<Builder>;
using witness_ct = stdlib::witness_t<Builder>;
using twin_rom_table_ct = stdlib::twin_rom_table<Builder>;
using field_pair_ct = std::array<field_ct, 2>;

Builder builder;

std::vector<field_pair_ct> table_values;
table_values.emplace_back(field_pair_ct{ witness_ct(&builder, bb::fr(1)), witness_ct(&builder, bb::fr(2)) });
table_values.emplace_back(field_pair_ct{ witness_ct(&builder, bb::fr(3)), witness_ct(&builder, bb::fr(4)) });
twin_rom_table_ct table(table_values);

// OOB constant index — should soft-fail, not crash
table[static_cast<size_t>(100000000)];

EXPECT_TRUE(builder.failed());
}
Loading
Loading