diff --git a/alternator/executor.cc b/alternator/executor.cc index 92f05360a6..f4285bcb32 100644 --- a/alternator/executor.cc +++ b/alternator/executor.cc @@ -3470,7 +3470,11 @@ void executor::describe_single_item(const cql3::selection::selection& selection, // names are unique so add() makes sense rjson::add_with_string_name(item, attr_name, std::move(v)); } else if (item_length_in_bytes) { - (*item_length_in_bytes) += value_cast(entry.second).length() - 1; + auto len = value_cast(entry.second).length(); + // BUG FIX 9: Prevent unsigned integer underflow + if (len > 0) { + (*item_length_in_bytes) += len - 1; + } } } } diff --git a/test/boost/alternator_unit_test.cc b/test/boost/alternator_unit_test.cc index 9025bd29ed..312991520e 100644 --- a/test/boost/alternator_unit_test.cc +++ b/test/boost/alternator_unit_test.cc @@ -226,3 +226,31 @@ BOOST_AUTO_TEST_CASE(test_base64_edge_cases) { BOOST_FAIL("base64_begins_with should handle edge cases without exception"); } } + +// Test to ensure no unsigned integer underflow in length calculations +BOOST_AUTO_TEST_CASE(test_no_underflow_in_length_calc) { + // This test is more of a compilation and logic test to ensure the + // length calculation bug fix works correctly. + // The actual bug would require integration testing with the full system, + // but we can at least test the arithmetic logic. + + uint64_t length = 0; + size_t value_length = 0; // Zero length value + + // The fixed logic: only subtract if length > 0 + if (value_length > 0) { + length += value_length - 1; + } + + // With the fix, length should remain 0 (no underflow) + BOOST_CHECK_EQUAL(length, 0); + + // Test with non-zero length + value_length = 5; + if (value_length > 0) { + length += value_length - 1; + } + + // Should add 4 (5-1) + BOOST_CHECK_EQUAL(length, 4); +}