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
8 changes: 8 additions & 0 deletions include/cllazyfile/lazyInstMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,14 @@ class SC_LAZYFILE_EXPORT lazyInstMgr {
return 0;
}
instancePosition pos = cv->at( 0 );
//a data section indexes its instances from its own constructor and is
//registered only afterwards, and only if it succeeded - so an instance
//can name a section that was never registered. Same test sourceRecord()
//already makes.
if( pos.section >= _dataSections.size() || !_dataSections[pos.section] ) {
std::cerr << "Error at " << __FILE__ << ":" << __LINE__ << " - instanceID " << id << " names data section " << pos.section << ", which failed to index." << std::endl;
return 0;
}
return _dataSections[pos.section]->getType( pos.begin );
}
std::cerr << "Error at " << __FILE__ << ":" << __LINE__ << " - instanceID " << id << " not found." << std::endl;
Expand Down
3 changes: 2 additions & 1 deletion src/cllazyfile/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@ if(SC_ENABLE_TESTING)
add_test(NAME lazy_index
COMMAND lazy_index_test
${CMAKE_CURRENT_SOURCE_DIR}/test/lazy_index.stp
${CMAKE_CURRENT_SOURCE_DIR}/test/lazy_scope.stp)
${CMAKE_CURRENT_SOURCE_DIR}/test/lazy_scope.stp
${CMAKE_CURRENT_SOURCE_DIR}/test/lazy_broken_section.stp)
endif()
23 changes: 21 additions & 2 deletions src/cllazyfile/lazyInstMgr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,24 @@ SDAI_Application_instance * lazyInstMgr::loadInstance( instanceID id, bool reSee
break;
case 1:
pos = cv->at( 0 );
assert( _dataSections.size() > pos.section );
//not an assert: a section that failed part way through its scan has
//already indexed the instances before the error under its id, and is
//then never registered. Those entries are bad input, not a programming
//error, and in Release the assert was compiled out and this indexed an
//empty vector. Same test sourceRecord() already makes.
if( pos.section >= _dataSections.size() || !_dataSections[pos.section] ) {
if( !_diagnosticCallback ) {
std::cerr << "Instance #" << id << " names data section "
<< pos.section << ", which failed to index." << std::endl;
}
LazyDiagnostic diagnostic;
diagnostic.severity = LAZY_DIAGNOSTIC_ERROR;
diagnostic.entity = id;
diagnostic.offset = pos.begin;
diagnostic.message = "instance belongs to a DATA section that failed to index";
emitDiagnostic( diagnostic );
break;
}
if( reSeek ) {
oldPos = _dataSections[pos.section]->tellg();
}
Expand Down Expand Up @@ -372,7 +389,9 @@ SDAI_Application_instance * lazyInstMgr::loadInstance( instanceID id, bool reSee
* safely revisit this instance without tripping the materialization
* cycle detector. */
loading_guard.release();
if( !isNilSTEPentity( inst ) ) {
/* isNilSTEPentity( 0 ) is false, so a null has to be tested for
* separately - every branch of the switch above can leave one. */
if( inst && !isNilSTEPentity( inst ) ) {
_instancesLoaded.insert( id, inst );
_loadedInstanceCount++;
++_materializations;
Expand Down
2 changes: 2 additions & 0 deletions src/cllazyfile/lazyP21DataSectionReader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ const namedLazyInstance lazyP21DataSectionReader::nextInstance() {
std::streampos end = -1;
namedLazyInstance i;

i.name = 0;
i.refs = 0;
i.componentTypes = 0;
i.loc.section = 0;
Expand Down Expand Up @@ -129,6 +130,7 @@ const namedLazyInstance lazyP21DataSectionReader::nextInstance() {
i.loc.begin = 0;
if( i.refs ) {
delete i.refs;
i.refs = 0;
}
if( i.componentTypes ) {
delete i.componentTypes;
Expand Down
28 changes: 27 additions & 1 deletion src/cllazyfile/lazy_index_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void emptyRegistryInit( Registry & ) {
}

int main( int argc, char ** argv ) {
require( argc == 3, "expected ordinary and scoped fixture paths" );
require( argc == 4, "expected ordinary, scoped and broken-section fixture paths" );

lazyInstMgr manager;
uint64_t progressCalls = 0;
Expand Down Expand Up @@ -133,5 +133,31 @@ int main( int argc, char ** argv ) {
complexOwner.find( "ENDSCOPE (C()D(" ) != std::string::npos &&
!complexOwner.empty() && complexOwner[complexOwner.size() - 1] == ';',
"complex scope source record was not preserved" );
/* A DATA section indexes its instances from its own constructor, under the
* id it will be given, and is registered only afterwards and only if the
* scan succeeded. A section that fails part way through therefore leaves
* every instance it had already indexed naming a section that does not
* exist. Asking for one of those must fail like any other unloadable
* instance rather than index an empty vector. */
lazyInstMgr broken;
broken.setRegistry( &emptyRegistry );
uint64_t brokenDiagnostics = 0;
broken.setDiagnosticCallback( [&brokenDiagnostics]( const LazyDiagnostic & ) {
++brokenDiagnostics;
} );
broken.openFile( argv[3] );
stats = broken.cacheStatistics();
require( stats.dataSections == 0, "the failed data section was registered anyway" );
require( broken.totalInstanceCount() == 1,
"the instance indexed before the failure was dropped from the index" );
require( broken.typeFromFile( 1 ) == 0,
"type of an instance in an unregistered section was not refused" );
require( broken.loadInstance( 1 ) == 0,
"instance in an unregistered section was not refused" );
require( brokenDiagnostics > 0,
"refusing the instance produced no diagnostic" );
require( broken.sourceRecord( 1 ).empty(),
"source record of an instance in an unregistered section was not empty" );

return EXIT_SUCCESS;
}
13 changes: 13 additions & 0 deletions src/cllazyfile/test/lazy_broken_section.stp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('lazy broken section test'),'2;1');
FILE_NAME('lazy_broken_section.stp','2026-08-21T00:00:00',('STEPcode'),('STEPcode'),'','','');
FILE_SCHEMA(('LAZY_TEST_SCHEMA { 1 0 10303 999 }'));
ENDSEC;
/* The DATA section indexes #1 and then fails: no ENDSEC; follows. The
section is therefore never registered, while #1 is already in the
instance index naming it. */
DATA;
#1=A();
not a step instance
END-ISO-10303-21;
Loading