src/Viewer/viewmgr.*: added asserts, diagnostics and checking for out-of-range view numbers.
It seems that some aircraft sometimes incorrectly pass view indices rather than numbers resulting in out-of-range access to FGViewMgr::views[]; See flightgear-devel thread with subject "View crash (after loading errors)". With this commit, if we are given an incorrect view number, we output a diagnostic with SG_ALERT, assert fail, and cope with the problem. Arguably we could do something more serious such as opening a popup or throw an exception.
This commit is contained in:
parent
71c7659f98
commit
380ecdf8ba
2 changed files with 32 additions and 31 deletions
|
@ -75,6 +75,15 @@ FGViewMgr::init ()
|
|||
|
||||
config_list = fgGetNode("/sim", true)->getChildren("view");
|
||||
_current = fgGetInt("/sim/current-view/view-number");
|
||||
if (_current != 0 && (_current < 0 || _current >= (int) views.size())) {
|
||||
SG_LOG(SG_VIEW, SG_ALERT,
|
||||
"Invalid /sim/current-view/view-number=" << _current
|
||||
<< ". views.size()=" << views.size()
|
||||
<< ". Will assert false and use zero."
|
||||
);
|
||||
assert(0);
|
||||
_current = 0;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < config_list.size(); i++) {
|
||||
SGPropertyNode* n = config_list[i];
|
||||
|
@ -185,23 +194,16 @@ void FGViewMgr::clear()
|
|||
flightgear::View*
|
||||
FGViewMgr::get_current_view()
|
||||
{
|
||||
const auto numViews = static_cast<int>(views.size());
|
||||
if ((_current >= 0) && (_current < numViews)) {
|
||||
return views.at(_current);
|
||||
} else {
|
||||
if (views.empty())
|
||||
return nullptr;
|
||||
}
|
||||
assert(_current >= 0 && _current < (int) views.size());
|
||||
return views[_current];
|
||||
}
|
||||
|
||||
const flightgear::View*
|
||||
FGViewMgr::get_current_view() const
|
||||
{
|
||||
const auto numViews = static_cast<int>(views.size());
|
||||
if ((_current >= 0) && (_current < numViews)) {
|
||||
return views.at(_current);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
return const_cast<FGViewMgr*>(this)->get_current_view();
|
||||
}
|
||||
|
||||
|
||||
|
@ -294,7 +296,6 @@ void FGViewMgr::setCurrentViewIndex(int newview)
|
|||
if (newview == _current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// negative numbers -> set view with node index -newview
|
||||
if (newview < 0) {
|
||||
for (int i = 0; i < (int)config_list.size(); i++) {
|
||||
|
@ -302,25 +303,28 @@ void FGViewMgr::setCurrentViewIndex(int newview)
|
|||
if (index == newview)
|
||||
newview = i;
|
||||
}
|
||||
if (newview < 0)
|
||||
if (newview < 0) {
|
||||
SG_LOG(SG_VIEW, SG_ALERT,
|
||||
"Failed to find -ve newview=" << newview
|
||||
<< ". Will assert false and ignore."
|
||||
);
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// not sure it really makes sense to be doing this wrapping logic
|
||||
// here, it could mask various strange inputs, But keeping for compat
|
||||
// for now.
|
||||
const auto numViews = static_cast<int>(views.size());
|
||||
if (newview < 0) { // wrap to last
|
||||
newview = numViews - 1;
|
||||
} else if (newview >= numViews) { // wrap to zero
|
||||
newview = 0;
|
||||
}
|
||||
if (newview < 0 || newview >= (int) views.size()) {
|
||||
SG_LOG(SG_VIEW, SG_ALERT, "Invalid newview=" << newview
|
||||
<< ". views.size()=" << views.size()
|
||||
<< ". Will assert false and ignore."
|
||||
);
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_current_view()) {
|
||||
get_current_view()->unbind();
|
||||
}
|
||||
|
||||
// set new view
|
||||
_current = newview;
|
||||
|
||||
if (get_current_view()) {
|
||||
|
|
|
@ -75,19 +75,16 @@ public:
|
|||
flightgear::View* next_view();
|
||||
flightgear::View* prev_view();
|
||||
|
||||
// Support for extra view windows. This only works if --compositer-viewer=1 was specified.
|
||||
//
|
||||
|
||||
// Calls SviewPush().
|
||||
void view_push();
|
||||
|
||||
// Experimental. Only works if --compositer-viewer=1 was specified. Creates
|
||||
// new window with clone of current view. As of 2020-09-03, the clone's
|
||||
// scenery is not displayed correctly.
|
||||
// These all end up calling SviewCreate().
|
||||
void clone_current_view(const SGPropertyNode* config);
|
||||
|
||||
//
|
||||
void clone_last_pair(const SGPropertyNode* config);
|
||||
|
||||
void clone_last_pair_double(const SGPropertyNode* config);
|
||||
|
||||
void view_new(const SGPropertyNode* config);
|
||||
|
||||
// setters
|
||||
|
|
Loading…
Reference in a new issue