From 2b6a35b66ad79c3a57d3c55a198376efee36a5b7 Mon Sep 17 00:00:00 2001 From: Luiz Scheinkman Date: Thu, 11 Jan 2018 15:33:10 -0800 Subject: [PATCH 1/3] Issue #1380: Validate python parameters passed to SP compute method --- src/nupic/bindings/algorithms.i | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/nupic/bindings/algorithms.i b/src/nupic/bindings/algorithms.i index 95a410ab98..9b4d82e8fe 100644 --- a/src/nupic/bindings/algorithms.i +++ b/src/nupic/bindings/algorithms.i @@ -1163,10 +1163,22 @@ void forceRetentionOfImageSensorLiteLibrary(void) { self._initFromCapnpPyBytes(proto.as_builder().to_bytes()) # copy * 2 %} - inline void compute(PyObject *py_x, bool learn, PyObject *py_y) + inline void compute(PyObject *py_inputArray, bool learn, PyObject *py_activeArray) { - PyArrayObject* x = (PyArrayObject*) py_x; - PyArrayObject* y = (PyArrayObject*) py_y; + PyArrayObject* x = (PyArrayObject*) py_inputArray; + PyArrayObject* y = (PyArrayObject*) py_activeArray; + if (!PyArray_ISUNSIGNED(x) || PyArray_DTYPE(x)->elsize != sizeof(nupic::UInt)) + { + NTA_THROW << "Invalid data type given for input array." + << " Expecting 'uint" << sizeof(nupic::UInt) * 8 << "'" + << " but got '" << PyArray_DTYPE(x)->type << "'"; + } + if (!PyArray_ISUNSIGNED(y) || PyArray_DTYPE(y)->elsize != sizeof(nupic::UInt)) + { + NTA_THROW << "Invalid data type given for active array." + << " Expecting 'uint" << sizeof(nupic::UInt) * 8 << "'" + << " but got '" << PyArray_DTYPE(y)->type << "'"; + } self->compute((nupic::UInt*) PyArray_DATA(x), (bool)learn, (nupic::UInt*) PyArray_DATA(y)); } From fda19d07a65ea201d8331d2bfa19820eb825c8d9 Mon Sep 17 00:00:00 2001 From: Luiz Scheinkman Date: Fri, 12 Jan 2018 15:00:47 -0800 Subject: [PATCH 2/3] Issue #1380: Reuse 'NumpyVectorWeakRefT' class per reviewer sugestion --- src/nupic/bindings/algorithms.i | 18 +++--------------- src/nupic/py_support/NumpyVector.hpp | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/nupic/bindings/algorithms.i b/src/nupic/bindings/algorithms.i index 9b4d82e8fe..880cdf18d3 100644 --- a/src/nupic/bindings/algorithms.i +++ b/src/nupic/bindings/algorithms.i @@ -1165,21 +1165,9 @@ void forceRetentionOfImageSensorLiteLibrary(void) { inline void compute(PyObject *py_inputArray, bool learn, PyObject *py_activeArray) { - PyArrayObject* x = (PyArrayObject*) py_inputArray; - PyArrayObject* y = (PyArrayObject*) py_activeArray; - if (!PyArray_ISUNSIGNED(x) || PyArray_DTYPE(x)->elsize != sizeof(nupic::UInt)) - { - NTA_THROW << "Invalid data type given for input array." - << " Expecting 'uint" << sizeof(nupic::UInt) * 8 << "'" - << " but got '" << PyArray_DTYPE(x)->type << "'"; - } - if (!PyArray_ISUNSIGNED(y) || PyArray_DTYPE(y)->elsize != sizeof(nupic::UInt)) - { - NTA_THROW << "Invalid data type given for active array." - << " Expecting 'uint" << sizeof(nupic::UInt) * 8 << "'" - << " but got '" << PyArray_DTYPE(y)->type << "'"; - } - self->compute((nupic::UInt*) PyArray_DATA(x), (bool)learn, (nupic::UInt*) PyArray_DATA(y)); + nupic::CheckedNumpyVectorWeakRefT inputArray(py_inputArray); + nupic::CheckedNumpyVectorWeakRefT activeArray(py_activeArray); + self->compute(inputArray.begin(), learn, activeArray.begin()); } inline void stripUnlearnedColumns(PyObject *py_x) diff --git a/src/nupic/py_support/NumpyVector.hpp b/src/nupic/py_support/NumpyVector.hpp index 9f16bf8541..89329ed071 100644 --- a/src/nupic/py_support/NumpyVector.hpp +++ b/src/nupic/py_support/NumpyVector.hpp @@ -31,6 +31,7 @@ #include // For nupic::Real. #include // For NTA_ASSERT #include // For std::copy. +#include // for 'type_name' namespace nupic { @@ -438,6 +439,29 @@ namespace nupic { PyArrayObject* pyArray_; }; + /** + * Similar to NumpyVectorWeakRefT but also provides extra type checking + */ + template + class CheckedNumpyVectorWeakRefT : public NumpyVectorWeakRefT + { + public: + CheckedNumpyVectorWeakRefT(PyObject* pyArray) + : NumpyVectorWeakRefT(pyArray) + { + if (PyArray_NDIM(this->pyArray_) != 1) + { + NTA_THROW << "Expecting 1D array " + << "but got " << PyArray_NDIM(this->pyArray_) << "D array"; + } + if (!PyArray_EquivTypenums( + PyArray_TYPE(this->pyArray_), LookupNumpyDType((const T *) 0))) + { + NTA_THROW << "Expecting '" << boost::compute::type_name() << "' " + << "but got '" << PyArray_DTYPE(this->pyArray_)->type << "'"; + } + } + }; } // End namespace nupic. #endif From 6a152d6585d65d84927ffff2bc76e1699717db09 Mon Sep 17 00:00:00 2001 From: Luiz Scheinkman Date: Fri, 12 Jan 2018 16:29:03 -0800 Subject: [PATCH 3/3] Issue #1380: Fix Linux build --- src/nupic/bindings/algorithms.i | 4 ++-- src/nupic/py_support/NumpyVector.hpp | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/nupic/bindings/algorithms.i b/src/nupic/bindings/algorithms.i index 880cdf18d3..5a1f94003b 100644 --- a/src/nupic/bindings/algorithms.i +++ b/src/nupic/bindings/algorithms.i @@ -1165,8 +1165,8 @@ void forceRetentionOfImageSensorLiteLibrary(void) { inline void compute(PyObject *py_inputArray, bool learn, PyObject *py_activeArray) { - nupic::CheckedNumpyVectorWeakRefT inputArray(py_inputArray); - nupic::CheckedNumpyVectorWeakRefT activeArray(py_activeArray); + nupic::CheckedNumpyVectorWeakRefT inputArray(py_inputArray); + nupic::CheckedNumpyVectorWeakRefT activeArray(py_activeArray); self->compute(inputArray.begin(), learn, activeArray.begin()); } diff --git a/src/nupic/py_support/NumpyVector.hpp b/src/nupic/py_support/NumpyVector.hpp index 89329ed071..4d2c4f7cf2 100644 --- a/src/nupic/py_support/NumpyVector.hpp +++ b/src/nupic/py_support/NumpyVector.hpp @@ -31,7 +31,7 @@ #include // For nupic::Real. #include // For NTA_ASSERT #include // For std::copy. -#include // for 'type_name' +#include // for 'type_id' namespace nupic { @@ -457,7 +457,9 @@ namespace nupic { if (!PyArray_EquivTypenums( PyArray_TYPE(this->pyArray_), LookupNumpyDType((const T *) 0))) { - NTA_THROW << "Expecting '" << boost::compute::type_name() << "' " + boost::typeindex::stl_type_index expectedType = + boost::typeindex::stl_type_index::type_id(); + NTA_THROW << "Expecting '" << expectedType.pretty_name() << "' " << "but got '" << PyArray_DTYPE(this->pyArray_)->type << "'"; } }