diff options
17 files changed, 80 insertions, 10 deletions
diff --git a/src/bindings/swig/wrapped/WrappedDataModel.h b/src/bindings/swig/wrapped/WrappedDataModel.h index e1b29af..481f0ea 100644 --- a/src/bindings/swig/wrapped/WrappedDataModel.h +++ b/src/bindings/swig/wrapped/WrappedDataModel.h @@ -99,6 +99,10 @@ public: return false; } + virtual bool isLocation(const std::string& expr) { + return true; + } + virtual void assign(const Arabica::DOM::Element<std::string>& assignElem, const Arabica::DOM::Node<std::string>& node, const std::string& content) { diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index 5b0db2d..7ae34f2 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -585,8 +585,8 @@ void InterpreterImpl::run(void* instance) { } } catch (Event e) { LOG(ERROR) << e; - } catch(boost::bad_lexical_cast e) { - LOG(ERROR) << "InterpreterImpl::run catched exception: " << e.what(); + } catch(std::exception e) { + LOG(ERROR) << "InterpreterImpl::run catched an exception: " << e.what() << std::endl << "Unclean shutdown"; } catch (...) { LOG(ERROR) << "InterpreterImpl::run catched unknown exception"; } @@ -1164,9 +1164,10 @@ void InterpreterImpl::send(const Arabica::DOM::Node<std::string>& element) { if (HAS_ATTR(element, "namelist")) { std::list<std::string> names = tokenizeIdRefs(ATTR(element, "namelist")); for (std::list<std::string>::const_iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) { - if (!_dataModel.isDeclared(*nameIter)) { - LOG(ERROR) << "Error in send element " << DOMUtils::xPathForNode(element) << " namelist:" << std::endl << "'" << *nameIter << "' is not declared" << std::endl; + if (!_dataModel.isLocation(*nameIter)) { + LOG(ERROR) << "Error in send element " << DOMUtils::xPathForNode(element) << " namelist:" << std::endl << "'" << *nameIter << "' is not a location expression" << std::endl; ERROR_EXECUTION2(err, "Location expression '" + *nameIter + "' in namelist is invalid", element); + receiveInternal(err); return; } Data namelistValue = _dataModel.getStringAsData(*nameIter); @@ -1200,6 +1201,7 @@ void InterpreterImpl::send(const Arabica::DOM::Node<std::string>& element) { } catch (Event e) { e.name = "error.execution"; receiveInternal(e); + return; } // set as content if it's only an atom if (sendReq.data.atom.length() > 0) { @@ -1311,7 +1313,15 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) { if (HAS_ATTR(element, "namelist")) { std::list<std::string> names = tokenizeIdRefs(ATTR(element, "namelist")); for (std::list<std::string>::const_iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) { - invokeReq.namelist[*nameIter] = _dataModel.evalAsString(*nameIter); + if (!_dataModel.isLocation(*nameIter)) { + LOG(ERROR) << "Error in send element " << DOMUtils::xPathForNode(element) << " namelist:" << std::endl << "'" << *nameIter << "' is not a location expression" << std::endl; + ERROR_EXECUTION2(err, "Location expression '" + *nameIter + "' in namelist is invalid", element); + receiveInternal(err); + return; + } + Data namelistValue = _dataModel.getStringAsData(*nameIter); + invokeReq.namelist[*nameIter] = namelistValue; + invokeReq.data.compound[*nameIter] = namelistValue; } } diff --git a/src/uscxml/plugins/DataModel.h b/src/uscxml/plugins/DataModel.h index f142a60..1a4deba 100644 --- a/src/uscxml/plugins/DataModel.h +++ b/src/uscxml/plugins/DataModel.h @@ -41,6 +41,7 @@ public: virtual std::list<std::string> getNames() = 0; virtual bool validate(const std::string& location, const std::string& schema) = 0; + virtual bool isLocation(const std::string& expr) = 0; virtual void setEvent(const Event& event) = 0; virtual Data getStringAsData(const std::string& content) = 0; @@ -121,6 +122,10 @@ public: virtual bool validate(const std::string& location, const std::string& schema) { return _impl->validate(location, schema); } + virtual bool isLocation(const std::string& expr) { + return _impl->isLocation(expr); + } + virtual void setEvent(const Event& event) { return _impl->setEvent(event); } diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp index 6dc8c26..73a3744 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp @@ -482,6 +482,19 @@ void JSCDataModel::setForeach(const std::string& item, } } +bool JSCDataModel::isLocation(const std::string& expr) { + JSStringRef scriptJS = JSStringCreateWithUTF8CString((expr + "++").c_str()); + JSValueRef exception = NULL; + bool valid = JSCheckScriptSyntax(_ctx, scriptJS, NULL, 0, &exception); + JSStringRelease(scriptJS); + + if (exception || !valid) { + return false; + } + return true; +} + + bool JSCDataModel::isDeclared(const std::string& expr) { JSStringRef scriptJS = JSStringCreateWithUTF8CString(expr.c_str()); JSValueRef exception = NULL; diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h index 82882f0..fea2234 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h @@ -49,6 +49,7 @@ public: } virtual bool validate(const std::string& location, const std::string& schema); + virtual bool isLocation(const std::string& expr); virtual void setEvent(const Event& event); virtual Data getStringAsData(const std::string& content); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 8b222f7..a995ec2 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -457,6 +457,22 @@ bool V8DataModel::validate(const std::string& location, const std::string& schem return true; } +bool V8DataModel::isLocation(const std::string& expr) { + v8::Locker locker; + v8::HandleScope handleScope; + v8::TryCatch tryCatch; + v8::Context::Scope contextScope(_contexts.back()); + + v8::Handle<v8::String> source = v8::String::New((expr + "++").c_str()); + v8::Handle<v8::Script> script = v8::Script::Compile(source); + + if (script.IsEmpty() || tryCatch.HasCaught()) { + return false; + } + + return true; +} + uint32_t V8DataModel::getLength(const std::string& expr) { v8::Locker locker; v8::HandleScope handleScope; @@ -468,7 +484,7 @@ uint32_t V8DataModel::getLength(const std::string& expr) { Event exceptionEvent; exceptionEvent.name = "error.execution"; - exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM); + exceptionEvent.data.compound["cause"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM); throw(exceptionEvent); } @@ -720,7 +736,7 @@ void V8DataModel::throwExceptionEvent(const v8::TryCatch& tryCatch) { exceptionEvent.eventType = Event::PLATFORM; std::string exceptionString(*v8::String::AsciiValue(tryCatch.Exception())); - exceptionEvent.data.compound["exception"] = Data(exceptionString, Data::VERBATIM);; + exceptionEvent.data.compound["cause"] = Data(exceptionString, Data::VERBATIM);; v8::Handle<v8::Message> message = tryCatch.Message(); if (!message.IsEmpty()) { diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h index 5bfca93..6df1951 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h @@ -53,6 +53,7 @@ public: virtual void setEvent(const Event& event); virtual bool validate(const std::string& location, const std::string& schema); + virtual bool isLocation(const std::string& expr); virtual uint32_t getLength(const std::string& expr); virtual void setForeach(const std::string& item, diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp index 45d7a5c..073657a 100644 --- a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp +++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp @@ -76,6 +76,10 @@ bool NULLDataModel::validate(const std::string& location, const std::string& sch return true; } +bool NULLDataModel::isLocation(const std::string& expr) { + return true; +} + uint32_t NULLDataModel::getLength(const std::string& expr) { return 0; } diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.h b/src/uscxml/plugins/datamodel/null/NULLDataModel.h index 162ffdb..f9609c4 100644 --- a/src/uscxml/plugins/datamodel/null/NULLDataModel.h +++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.h @@ -50,6 +50,7 @@ public: virtual void setEvent(const Event& event); virtual bool validate(const std::string& location, const std::string& schema); + virtual bool isLocation(const std::string& expr); virtual uint32_t getLength(const std::string& expr); virtual void setForeach(const std::string& item, diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index 8f5e588..924e14a 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -607,6 +607,10 @@ bool SWIDataModel::validate(const std::string& location, const std::string& sche return true; } +bool SWIDataModel::isLocation(const std::string& expr) { + return true; +} + uint32_t SWIDataModel::getLength(const std::string& expr) { SWIEngineLock engineLock; try { diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h index f022811..a673a40 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h @@ -68,6 +68,7 @@ public: virtual void registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor); virtual bool validate(const std::string& location, const std::string& schema); + virtual bool isLocation(const std::string& expr); virtual uint32_t getLength(const std::string& expr); virtual void setForeach(const std::string& item, diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp index 4300512..6d34677 100644 --- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp +++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.cpp @@ -98,6 +98,10 @@ bool PromelaDataModel::validate(const std::string& location, const std::string& return true; } +bool PromelaDataModel::isLocation(const std::string& expr) { + return true; +} + uint32_t PromelaDataModel::getLength(const std::string& expr) { if (!isDeclared(expr)) { ERROR_EXECUTION_THROW("Variable '" + expr + "' was not declared"); diff --git a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h index cbbf570..ca6b19d 100644 --- a/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h +++ b/src/uscxml/plugins/datamodel/promela/PromelaDataModel.h @@ -49,6 +49,7 @@ public: virtual void registerIOProcessor(const std::string& name, const IOProcessor& ioprocessor); virtual bool validate(const std::string& location, const std::string& schema); + virtual bool isLocation(const std::string& expr); virtual uint32_t getLength(const std::string& expr); virtual void setForeach(const std::string& item, diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp index 3b28547..c38842b 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp @@ -285,6 +285,10 @@ bool XPathDataModel::validate(const std::string& location, const std::string& sc return true; } +bool XPathDataModel::isLocation(const std::string& expr) { + return true; +} + uint32_t XPathDataModel::getLength(const std::string& expr) { // std::cout << _datamodel << std::endl; XPathValue<std::string> result = _xpath.evaluate_expr(expr, _doc); diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h index d18d05a..09d63fa 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h @@ -95,6 +95,7 @@ public: virtual void setEvent(const Event& event); virtual bool validate(const std::string& location, const std::string& schema); + virtual bool isLocation(const std::string& expr); virtual uint32_t getLength(const std::string& expr); virtual void setForeach(const std::string& item, diff --git a/test/w3c/ecma/test553.scxml b/test/w3c/ecma/test553.scxml index 0df3c3e..3dd0aeb 100644 --- a/test/w3c/ecma/test553.scxml +++ b/test/w3c/ecma/test553.scxml @@ -5,9 +5,9 @@ of <send>'s args causes an error.. --><scxml xmlns="http://www.w3.org/2005/07/s <state id="s0"> <onentry> <!-- timeout event --> - <send event="timeout" delayexpr="'50ms'"/> + <send event="timeout" delayexpr="'500ms'"/> <!-- generate an invalid namelist --> - <send event="event1" namelist=""foo""/> + <send event="event1" namelist=""foo"/> </onentry> <!-- if we get the timeout before event1, we assume that event1 hasn't been sent diff --git a/test/w3c/ecma/test554.scxml b/test/w3c/ecma/test554.scxml index 764241e..b2fa50e 100644 --- a/test/w3c/ecma/test554.scxml +++ b/test/w3c/ecma/test554.scxml @@ -9,7 +9,7 @@ before the timer goes off. --><scxml xmlns="http://www.w3.org/2005/07/scxml" xm </onentry> <!-- reference an invalid namelist --> - <invoke type="http://www.w3.org/TR/scxml/" namelist=""foo""> + <invoke type="http://www.w3.org/TR/scxml/" namelist=""foo"> <content> <scxml initial="subFinal" version="1.0" datamodel="ecmascript"> <final id="subFinal"/> |