From 538afcb7e06f7644c8c930de5c647f38f3cabb52 Mon Sep 17 00:00:00 2001 From: Jonathan Hanks <jonathan.hanks@ligo.org> Date: Tue, 13 Oct 2020 12:22:51 -0700 Subject: [PATCH] More work on #186. Adding checks in shmem_receiver.hh for cycle and segment sizes. --- src/daqd/shmem_receiver.hh | 71 +++++++++++++++++++++---------- src/daqd/tests/test_shmem_recv.cc | 53 +++++++++++++++++++++-- 2 files changed, 97 insertions(+), 27 deletions(-) diff --git a/src/daqd/shmem_receiver.hh b/src/daqd/shmem_receiver.hh index bbb1af586..f4fcb1349 100644 --- a/src/daqd/shmem_receiver.hh +++ b/src/daqd/shmem_receiver.hh @@ -10,42 +10,30 @@ #include <chrono> #include <functional> #include <thread> +#include <sstream> #include "daq_core.h" #include "drv/shmem.h" class ShMemReceiver { - volatile daq_multi_cycle_data_t* shmem_; - - daq_dc_data_t data_; - unsigned int prev_cycle_; - unsigned int prev_gps_; - std::function< void( void ) > signal_stalled_; - - void - wait( ) - { - std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) ); - } - public: ShMemReceiver( ) = delete; ShMemReceiver( ShMemReceiver& other ) = delete; ShMemReceiver( const std::string& endpoint, - size_t shmem_size, + std::size_t shmem_size, std::function< void( void ) > signal = []( ) {} ) : shmem_( static_cast< volatile daq_multi_cycle_data_t* >( shmem_open_segment( endpoint.c_str( ), shmem_size ) ) ), - prev_cycle_( 0xffffffff ), - prev_gps_( 0xffffffff ), signal_stalled_{ std::move( signal ) } + shmem_size_( shmem_size ), signal_stalled_{ std::move( signal ) } { } - explicit ShMemReceiver( volatile daq_multi_cycle_data_t* shmem_area, - std::function< void( void ) > signal = []( ) {} ) - : shmem_( shmem_area ), prev_cycle_( 0xffffffff ), - prev_gps_( 0xffffffff ), signal_stalled_{ std::move( signal ) } + ShMemReceiver( volatile daq_multi_cycle_data_t* shmem_area, + std::size_t shmem_size, + std::function< void( void ) > signal = []( ) {} ) + : shmem_( shmem_area ), + shmem_size_( shmem_size ), signal_stalled_{ std::move( signal ) } { } @@ -84,7 +72,9 @@ public: signal_stalled_( ); } } - cur_cycle = handle_cycle_jumps( cur_cycle ); + unsigned int max_cycle = get_max_cycle( ); + verify_cycle_state( cur_cycle, max_cycle ); + cur_cycle = handle_cycle_jumps( cur_cycle, max_cycle ); unsigned int cycle_stride = shmem_->header.cycleDataSize; // figure out offset to the right block @@ -121,10 +111,31 @@ private: .timeSec; } + void + verify_cycle_state( unsigned int cur_cycle, unsigned int max_cycle ) + { + if ( cur_cycle >= max_cycle || max_cycle > 64 ) + { + throw std::runtime_error( + "Invalid shmem header or nonsensical values" ); + } + auto cycleDataSize = shmem_->header.cycleDataSize; + if ( cycleDataSize * max_cycle + + sizeof( daq_multi_cycle_header_t ) > + shmem_size_ ) + { + std::ostringstream os; + os << "Overflow condition exists, the cycleDataSize is wrong for the " + "shared memory size. cycleDataSize=" << cycleDataSize << " max_cycle=" + << max_cycle << " header_size=" << sizeof( daq_multi_cycle_header_t) << " shmem_size=" << shmem_size_; + std::string msg = os.str(); + throw std::runtime_error( msg ); + } + } + int - handle_cycle_jumps( unsigned int new_cycle ) + handle_cycle_jumps( unsigned int new_cycle, unsigned int max_cycle ) { - unsigned int max_cycle = get_max_cycle( ); unsigned int prev = prev_cycle_; unsigned int prev_gps = prev_gps_; @@ -149,6 +160,20 @@ private: } return new_cycle; } + + void + wait( ) + { + std::this_thread::sleep_for( std::chrono::milliseconds( 3 ) ); + } + + volatile daq_multi_cycle_data_t* shmem_; + std::size_t shmem_size_; + + daq_dc_data_t data_{}; + unsigned int prev_cycle_{ 0xffffffff }; + unsigned int prev_gps_{ 0xffffffff }; + std::function< void( void ) > signal_stalled_; }; #endif // DAQD_// SHMEM_RECEIVER_HH diff --git a/src/daqd/tests/test_shmem_recv.cc b/src/daqd/tests/test_shmem_recv.cc index 78cb5d441..84d8748a0 100644 --- a/src/daqd/tests/test_shmem_recv.cc +++ b/src/daqd/tests/test_shmem_recv.cc @@ -32,7 +32,7 @@ TEST_CASE( } ShMemReceiver recv( - reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ) ); + reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), sizeof( daq_multi_cycle_data_t) ); recv.reset_previous_cycle( 4, 1000000000 ); auto data = recv.receive_data( ); REQUIRE( data->dataBlock[ 0 ] == 5 ); @@ -62,7 +62,7 @@ TEST_CASE( "ShMemReceiver should try to catch up if it sees a jump" ) } ShMemReceiver recv( - reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ) ); + reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), sizeof( daq_multi_cycle_data_t ) ); recv.reset_previous_cycle( 0, 1000000000 ); auto data = recv.receive_data( ); REQUIRE( data->dataBlock[ 0 ] == 1 ); @@ -94,7 +94,8 @@ TEST_CASE( "ShMemReceiver should try to catch up if it sees a jump, even when " } ShMemReceiver recv( - reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ) ); + reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), + sizeof( daq_multi_cycle_data_t ) ); recv.reset_previous_cycle( 10, 1000000000 ); auto data = recv.receive_data( ); REQUIRE( data->dataBlock[ 0 ] == 11 ); @@ -124,8 +125,52 @@ TEST_CASE( "ShMemReceiver should try to catch up but will jump if needed" ) } ShMemReceiver recv( - reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ) ); + reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), + sizeof( daq_multi_cycle_data_t ) ); recv.reset_previous_cycle( 0, 1000000000 - 1 ); auto data = recv.receive_data( ); REQUIRE( data->dataBlock[ 0 ] == 5 ); +} + +TEST_CASE( "ShMemReceiver will throw an exception if max cycles is too big") +{ + auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( ); + shmem->header.maxCycle = 65; + shmem->header.curCycle = 5; + shmem->header.cycleDataSize = sizeof( shmem->dataBlock ) / 16; + ShMemReceiver recv( + reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), + sizeof( daq_multi_cycle_data_t ) ); + recv.reset_previous_cycle( 0, 1000000000 - 1 ); + REQUIRE_THROWS_AS(recv.receive_data(), std::runtime_error); +} + +TEST_CASE( "ShMemReceiver will throw an exception if curCycle is too big") +{ + auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( ); + shmem->header.maxCycle = 16; + shmem->header.curCycle = 15; + shmem->header.cycleDataSize = sizeof( shmem->dataBlock ) / 16; + ShMemReceiver recv( + reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), + sizeof( daq_multi_cycle_data_t ) ); + recv.reset_previous_cycle( 15, 1000000000 - 1 ); + shmem->header.curCycle = 16; + REQUIRE_THROWS_AS(recv.receive_data(), std::runtime_error); +} + +TEST_CASE( "ShMemReceiver will throw an exception if cycleDataSize*maxCycle is too big") +{ + auto shmem = raii::make_unique_ptr< daq_multi_cycle_data_t >( ); + shmem->header.maxCycle = 16; + shmem->header.curCycle = 15; + shmem->header.cycleDataSize = sizeof( shmem->dataBlock ) / 16; + ShMemReceiver recv( + reinterpret_cast< volatile daq_multi_cycle_data_t* >( shmem.get( ) ), + sizeof( daq_multi_cycle_data_t ) ); + recv.reset_previous_cycle( 15, 1000000000 - 1 ); + shmem->header.curCycle = 0; + // this does not take away the header size, so it should lead to an overflow condition + shmem->header.cycleDataSize = sizeof(daq_multi_cycle_data_t)/16; + REQUIRE_THROWS_AS(recv.receive_data(), std::runtime_error); } \ No newline at end of file -- GitLab