1
0
Fork 0

Stricter syntax checking for JSBSim.

JSBSim was not checking the tag names inside <test> and <condition> statements and this has led to abusive use of tags unsupported by JSBSim such as <and> and <or>. The problem is that JSBSim was not interpreting the <or> statement as the user meant it: JSBSim interpreted it as <test logic="AND"> while the user obviously meant <test logic="OR">. As a result JSBSim silently swallowed the tag and gave results which were not was the user expected without any obvious indication about what was going wrong.

As a result, this commit implements stricter syntax checking and rejects illegal tags within <test> and <condition> statements.

This commit also introduces stricter checking on XML elements which allow either a real value or a property name to be used. JSBSim now rejects the statements where the property name is specified inside a <property> statement. For example, the follwoing statement is rejected:

<clipto>
  <min> <property> /fdm/jsbsim/some/property </property> </min>
...

The correct syntax being
<clipto>
  <min> /fdm/jsbsim/some/property </min>
This commit is contained in:
Bertrand Coconnier 2019-04-27 12:29:22 +02:00
parent aaa753d169
commit 3539b13985
8 changed files with 68 additions and 47 deletions

View file

@ -53,11 +53,10 @@ CLASS IMPLEMENTATION
bool FGPropertyReader::ResetToIC(void)
{
map<SGPropertyNode_ptr, double>::iterator it = interface_prop_initial_value.begin();
for (;it != interface_prop_initial_value.end(); ++it) {
SGPropertyNode* node = it->first;
for (auto v: interface_prop_initial_value) {
SGPropertyNode* node = v.first;
if (!node->getAttribute(SGPropertyNode::PRESERVE))
node->setDoubleValue(it->second);
node->setDoubleValue(v.second);
}
return true;
@ -67,9 +66,6 @@ bool FGPropertyReader::ResetToIC(void)
void FGPropertyReader::Load(Element* el, FGPropertyManager* PM, bool override)
{
// Interface properties are all stored in the interface properties array.
string interface_property_string = "";
Element *property_element = el->FindElement("property");
if (property_element && FGJSBBase::debug_lvl > 0) {
cout << endl << " ";
@ -81,12 +77,12 @@ void FGPropertyReader::Load(Element* el, FGPropertyManager* PM, bool override)
}
while (property_element) {
SGPropertyNode* node = 0;
SGPropertyNode* node = nullptr;
double value=0.0;
if ( ! property_element->GetAttributeValue("value").empty())
value = property_element->GetAttributeValueAsNumber("value");
interface_property_string = property_element->GetDataLine();
string interface_property_string = property_element->GetDataLine();
if (PM->HasNode(interface_property_string)) {
if (override) {
node = PM->GetNode(interface_property_string);

View file

@ -36,6 +36,7 @@ INCLUDES
#include <iostream>
#include <cstdlib>
#include <stdexcept>
#include "FGCondition.h"
#include "FGPropertyValue.h"
@ -65,20 +66,30 @@ FGCondition::FGCondition(Element* element, FGPropertyManager* PropertyManager)
else { // error
cerr << element->ReadFrom()
<< "Unrecognized LOGIC token " << logic << endl;
throw std::invalid_argument("Illegal argument");
}
} else {
Logic = eAND; // default
}
Element* condition_element = element->GetElement();
for (unsigned int i=0; i<element->GetNumDataLines(); i++) {
string data = element->GetDataLine(i);
conditions.push_back(new FGCondition(data, PropertyManager,
condition_element));
conditions.push_back(new FGCondition(data, PropertyManager, element));
}
Element* condition_element = element->GetElement();
const string& elName = element->GetName();
while (condition_element) {
string tagName = condition_element->GetName();
if (tagName != elName) {
cerr << condition_element->ReadFrom()
<< "Unrecognized tag <" << tagName << "> in the condition statement."
<< endl;
throw std::invalid_argument("Illegal argument");
}
conditions.push_back(new FGCondition(condition_element, PropertyManager));
condition_element = element->GetNextElement();
}

View file

@ -34,8 +34,11 @@
INCLUDES
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include <stdexcept>
#include "math/FGRealValue.h"
#include "math/FGPropertyValue.h"
#include "input_output/FGXMLElement.h"
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
FORWARD DECLARATIONS
@ -60,13 +63,22 @@ class FGPropertyManager;
class FGParameterValue : public FGParameter
{
public:
FGParameterValue(const std::string& value, FGPropertyManager* pm) {
if (is_number(value)) {
param = new FGRealValue(atof(value.c_str()));
} else {
// "value" must be a property if execution passes to here.
param = new FGPropertyValue(value, pm);
FGParameterValue(Element* el, FGPropertyManager* pm) {
string value = el->GetDataLine();
if (el->GetNumDataLines() != 1 || value.empty()) {
cerr << el->ReadFrom()
<< "The element <" << el->GetName()
<< "> must either contain a value number or a property name."
<< endl;
throw invalid_argument("Illegal argument");
}
Construct(value, pm);
}
FGParameterValue(const std::string& value, FGPropertyManager* pm) {
Construct(value, pm);
}
double GetValue(void) const override { return param->GetValue(); }
@ -86,6 +98,15 @@ public:
}
private:
FGParameter_ptr param;
void Construct(const std::string& value, FGPropertyManager* pm) {
if (is_number(value)) {
param = new FGRealValue(atof(value.c_str()));
} else {
// "value" must be a property if execution passes to here.
param = new FGPropertyValue(value, pm);
}
}
};
typedef SGSharedPtr<FGParameterValue> FGParameterValue_ptr;

View file

@ -57,16 +57,14 @@ CLASS IMPLEMENTATION
FGDeadBand::FGDeadBand(FGFCS* fcs, Element* element)
: FGFCSComponent(fcs, element)
{
Width = nullptr;
gain = 1.0;
string width_string = "0.0";
Element* width_element = element->FindElement("width");
if (width_element)
width_string = width_element->GetDataLine();
Width = new FGParameterValue(width_string, PropertyManager);
Width = new FGParameterValue(width_element, PropertyManager);
else
Width = new FGRealValue(0.0);
if (element->FindElement("gain"))
gain = element->FindElementValueAsNumber("gain");

View file

@ -168,21 +168,19 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
return;
}
string clip_string = el->GetDataLine();
ClipMin = new FGParameterValue(clip_string, PropertyManager);
ClipMin = new FGParameterValue(el, PropertyManager);
el = clip_el->FindElement("max");
if (!el) {
cerr << clip_el->ReadFrom()
<< "Element <max> is missing, <clipto> is ignored." << endl;
ClipMin = nullptr;
return;
}
clip_string = el->GetDataLine();
ClipMax = new FGParameterValue(clip_string, PropertyManager);
ClipMax = new FGParameterValue(el, PropertyManager);
clip_string = clip_el->GetAttributeValue("type");
if (clip_string == "cyclic")
if (clip_el->GetAttributeValue("type") == "cyclic")
cyclic_clip = true;
clip = true;

View file

@ -99,8 +99,8 @@ void FGFilter::ReadFilterCoefficients(Element* element, int index)
coefficient[1] += index;
if ( element->FindElement(coefficient) ) {
string property_string = element->FindElementValue(coefficient);
C[index] = new FGParameterValue(property_string, PropertyManager);
C[index] = new FGParameterValue(element->FindElement(coefficient),
PropertyManager);
DynamicFilter |= !C[index]->IsConstant();
}
}

View file

@ -69,12 +69,11 @@ FGGain::FGGain(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
}
}
string gain_string = "1.0";
Element* gain_element = element->FindElement("gain");
if (gain_element)
gain_string = gain_element->GetDataLine();
Gain = new FGParameterValue(gain_string, PropertyManager);
Gain = new FGParameterValue(gain_element, PropertyManager);
else
Gain = new FGRealValue(1.0);
if (Type == "AEROSURFACE_SCALE") {
Element* scale_element = element->FindElement("domain");

View file

@ -64,14 +64,12 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
if (pid_type == "standard") IsStandard = true;
string kp_string = "0.0";
el = element->FindElement("kp");
if (el)
kp_string = el->GetDataLine();
Kp = new FGParameterValue(el, PropertyManager);
else
Kp = new FGRealValue(0.0);
Kp = new FGParameterValue(kp_string, PropertyManager);
string ki_string = "0.0";
el = element->FindElement("ki");
if (el) {
string integ_type = el->GetAttributeValue("type");
@ -87,17 +85,17 @@ FGPID::FGPID(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, element)
IntType = eAdamsBashforth2;
}
ki_string = el->GetDataLine();
Ki = new FGParameterValue(el, PropertyManager);
}
else
Ki = new FGRealValue(0.0);
Ki = new FGParameterValue(ki_string, PropertyManager);
string kd_string = "0.0";
el = element->FindElement("kd");
if (el)
kd_string = el->GetDataLine();
Kd = new FGParameterValue(kd_string, PropertyManager);
Kd = new FGParameterValue(el, PropertyManager);
else
Kd = new FGRealValue(0.0);
el = element->FindElement("pvdot");
if (el)