Merge pull request #10146 from marioalexis84/app-string_hasher_py
App: Fix crash and undefined behavior in StringHasherPy and StringIDPy
This commit is contained in:
@@ -114,6 +114,8 @@
|
||||
#include "PropertyFile.h"
|
||||
#include "PropertyLinks.h"
|
||||
#include "PropertyPythonObject.h"
|
||||
#include "StringHasherPy.h"
|
||||
#include "StringIDPy.h"
|
||||
#include "TextDocument.h"
|
||||
#include "Transactions.h"
|
||||
#include "VRMLObject.h"
|
||||
@@ -311,6 +313,9 @@ void Application::setupPythonTypes()
|
||||
Base::Interpreter().addType(&App::MaterialPy::Type, pAppModule, "Material");
|
||||
Base::Interpreter().addType(&App::MetadataPy::Type, pAppModule, "Metadata");
|
||||
|
||||
Base::Interpreter().addType(&App::StringHasherPy::Type, pAppModule, "StringHasher");
|
||||
Base::Interpreter().addType(&App::StringIDPy::Type, pAppModule, "StringID");
|
||||
|
||||
// Add document types
|
||||
Base::Interpreter().addType(&App::PropertyContainerPy::Type, pAppModule, "PropertyContainer");
|
||||
Base::Interpreter().addType(&App::ExtensionContainerPy::Type, pAppModule, "ExtensionContainer");
|
||||
@@ -2109,6 +2114,10 @@ void Application::initTypes()
|
||||
App::RangeExpression ::init();
|
||||
App::PyObjectExpression ::init();
|
||||
|
||||
// Topological naming classes
|
||||
App::StringHasher ::init();
|
||||
App::StringID ::init();
|
||||
|
||||
// register transaction type
|
||||
new App::TransactionProducer<TransactionDocumentObject>
|
||||
(DocumentObject::getClassTypeId());
|
||||
|
||||
@@ -32,117 +32,135 @@ using namespace App;
|
||||
// returns a string which represent the object e.g. when printed in python
|
||||
std::string StringHasherPy::representation() const
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << "<StringHasher at " << getStringHasherPtr() << ">";
|
||||
return str.str();
|
||||
std::ostringstream str;
|
||||
str << "<StringHasher at " << getStringHasherPtr() << ">";
|
||||
return str.str();
|
||||
}
|
||||
|
||||
PyObject *StringHasherPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
|
||||
{
|
||||
return new StringHasherPy(new StringHasher);
|
||||
return new StringHasherPy(new StringHasher);
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int StringHasherPy::PyInit(PyObject* , PyObject* )
|
||||
int StringHasherPy::PyInit(PyObject* args, PyObject* kwds)
|
||||
{
|
||||
return 0;
|
||||
char* kw[] = {nullptr};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kw)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PyObject* StringHasherPy::isSame(PyObject *args)
|
||||
{
|
||||
PyObject *other;
|
||||
if (!PyArg_ParseTuple(args, "O!", &StringHasherPy::Type, &other)){ // convert args: Python->C
|
||||
return Py::new_reference_to(Py::False());
|
||||
}
|
||||
auto otherHasher = static_cast<StringHasherPy*>(other)->getStringHasherPtr();
|
||||
return Py::new_reference_to(Py::Boolean(getStringHasherPtr() == otherHasher));
|
||||
PyObject *other;
|
||||
if (!PyArg_ParseTuple(args, "O!", &StringHasherPy::Type, &other)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto otherHasher = static_cast<StringHasherPy*>(other)->getStringHasherPtr();
|
||||
bool same = getStringHasherPtr() == otherHasher;
|
||||
|
||||
return PyBool_FromLong(same ? 1 : 0);
|
||||
}
|
||||
|
||||
PyObject* StringHasherPy::getID(PyObject *args)
|
||||
{
|
||||
long id = -1;
|
||||
int index = 0;
|
||||
PyObject *value = nullptr;
|
||||
PyObject *base64 = Py_False;
|
||||
if (!PyArg_ParseTuple(args, "l|i",&id,&index)) {
|
||||
PyErr_Clear();
|
||||
if (!PyArg_ParseTuple(args, "O|O",&value,&base64))
|
||||
return nullptr;
|
||||
}
|
||||
if(id>0) {
|
||||
PY_TRY {
|
||||
auto sid = getStringHasherPtr()->getID(id, index);
|
||||
if(!sid) Py_Return;
|
||||
return sid.getPyObject();
|
||||
}PY_CATCH;
|
||||
}
|
||||
std::string txt;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
if (PyUnicode_Check(value)) {
|
||||
txt = PyUnicode_AsUTF8(value);
|
||||
}
|
||||
#else
|
||||
if (PyUnicode_Check(value)) {
|
||||
PyObject* unicode = PyUnicode_AsLatin1String(value);
|
||||
txt = PyString_AsString(unicode);
|
||||
Py_DECREF(unicode);
|
||||
}
|
||||
else if (PyString_Check(value)) {
|
||||
txt = PyString_AsString(value);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw Py::TypeError("expect argument of type string");
|
||||
PY_TRY {
|
||||
QByteArray data;
|
||||
StringIDRef sid;
|
||||
if(PyObject_IsTrue(base64)) {
|
||||
data = QByteArray::fromBase64(QByteArray::fromRawData(txt.c_str(),txt.size()));
|
||||
sid = getStringHasherPtr()->getID(data,true);
|
||||
}else
|
||||
sid = getStringHasherPtr()->getID(txt.c_str(),txt.size());
|
||||
return sid.getPyObject();
|
||||
}PY_CATCH;
|
||||
long id;
|
||||
int index = 0;
|
||||
if (PyArg_ParseTuple(args, "l|i", &id, &index)) {
|
||||
if (id > 0) {
|
||||
PY_TRY {
|
||||
auto sid = getStringHasherPtr()->getID(id, index);
|
||||
if (!sid) {
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
return sid.getPyObject();
|
||||
}
|
||||
PY_CATCH;
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_ValueError, "Id must be positive integer");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
PyObject *value = nullptr;
|
||||
PyObject *base64 = Py_False;
|
||||
if (PyArg_ParseTuple(args, "O!|O!", &PyUnicode_Type, &value, &PyBool_Type, &base64)) {
|
||||
PY_TRY {
|
||||
std::string txt = PyUnicode_AsUTF8(value);
|
||||
QByteArray data;
|
||||
StringIDRef sid;
|
||||
if (PyObject_IsTrue(base64)) {
|
||||
data = QByteArray::fromBase64(QByteArray::fromRawData(txt.c_str(),txt.size()));
|
||||
sid = getStringHasherPtr()->getID(data,true);
|
||||
}
|
||||
else {
|
||||
sid = getStringHasherPtr()->getID(txt.c_str(),txt.size());
|
||||
}
|
||||
|
||||
return sid.getPyObject();
|
||||
}
|
||||
PY_CATCH;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Positive integer and optional integer or "
|
||||
"string and optional boolean is required");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py::Int StringHasherPy::getCount() const {
|
||||
return Py::Int((long)getStringHasherPtr()->count());
|
||||
Py::Long StringHasherPy::getCount() const
|
||||
{
|
||||
return Py::Long(PyLong_FromSize_t(getStringHasherPtr()->count()), true);
|
||||
}
|
||||
|
||||
Py::Int StringHasherPy::getSize() const {
|
||||
return Py::Int((long)getStringHasherPtr()->size());
|
||||
Py::Long StringHasherPy::getSize() const
|
||||
{
|
||||
return Py::Long(PyLong_FromSize_t(getStringHasherPtr()->size()), true);
|
||||
}
|
||||
|
||||
Py::Boolean StringHasherPy::getSaveAll() const {
|
||||
return Py::Boolean(getStringHasherPtr()->getSaveAll());
|
||||
Py::Boolean StringHasherPy::getSaveAll() const
|
||||
{
|
||||
return Py::Boolean(getStringHasherPtr()->getSaveAll());
|
||||
}
|
||||
|
||||
void StringHasherPy::setSaveAll(Py::Boolean value) {
|
||||
getStringHasherPtr()->setSaveAll(value);
|
||||
void StringHasherPy::setSaveAll(Py::Boolean value)
|
||||
{
|
||||
getStringHasherPtr()->setSaveAll(value);
|
||||
}
|
||||
|
||||
Py::Int StringHasherPy::getThreshold() const {
|
||||
return Py::Int((long)getStringHasherPtr()->getThreshold());
|
||||
Py::Long StringHasherPy::getThreshold() const
|
||||
{
|
||||
return Py::Long(getStringHasherPtr()->getThreshold());
|
||||
}
|
||||
|
||||
void StringHasherPy::setThreshold(Py::Int value) {
|
||||
getStringHasherPtr()->setThreshold(value);
|
||||
void StringHasherPy::setThreshold(Py::Long value)
|
||||
{
|
||||
getStringHasherPtr()->setThreshold(value);
|
||||
}
|
||||
|
||||
Py::Dict StringHasherPy::getTable() const {
|
||||
Py::Dict dict;
|
||||
for(auto &v : getStringHasherPtr()->getIDMap())
|
||||
dict.setItem(Py::Int(v.first),Py::String(v.second.dataToText()));
|
||||
return dict;
|
||||
Py::Dict StringHasherPy::getTable() const
|
||||
{
|
||||
Py::Dict dict;
|
||||
for (const auto &v : getStringHasherPtr()->getIDMap()) {
|
||||
dict.setItem(Py::Long(v.first), Py::String(v.second.dataToText()));
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
PyObject *StringHasherPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int StringHasherPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -32,59 +32,69 @@ using namespace App;
|
||||
// returns a string which represent the object e.g. when printed in python
|
||||
std::string StringIDPy::representation() const
|
||||
{
|
||||
return getStringIDPtr()->toString(_index);
|
||||
return getStringIDPtr()->toString(this->_index);
|
||||
}
|
||||
|
||||
PyObject* StringIDPy::isSame(PyObject *args)
|
||||
{
|
||||
PyObject *other = nullptr;
|
||||
if (PyArg_ParseTuple(args, "O!", &StringIDPy::Type, &other) == 0) { // convert args: Python->C
|
||||
return Py::new_reference_to(Py::False());
|
||||
}
|
||||
auto *otherPy = static_cast<StringIDPy*>(other);
|
||||
return Py::new_reference_to(Py::Boolean(
|
||||
otherPy->getStringIDPtr() == this->getStringIDPtr()
|
||||
&& otherPy->_index == this->_index));
|
||||
PyObject *other = nullptr;
|
||||
if (!PyArg_ParseTuple(args, "O!", &StringIDPy::Type, &other)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto *otherPy = static_cast<StringIDPy*>(other);
|
||||
bool same = (otherPy->getStringIDPtr() == this->getStringIDPtr())
|
||||
&& (otherPy->_index == this->_index);
|
||||
|
||||
return PyBool_FromLong(same ? 1 : 0);
|
||||
}
|
||||
|
||||
Py::Int StringIDPy::getValue() const {
|
||||
return Py::Int(getStringIDPtr()->value());
|
||||
Py::Long StringIDPy::getValue() const
|
||||
{
|
||||
return Py::Long(getStringIDPtr()->value());
|
||||
}
|
||||
|
||||
Py::List StringIDPy::getRelated() const {
|
||||
Py::List list;
|
||||
for (const auto &id : getStringIDPtr()->relatedIDs()) {
|
||||
list.append(Py::Long(id.value()));
|
||||
}
|
||||
return list;
|
||||
Py::List StringIDPy::getRelated() const
|
||||
{
|
||||
Py::List list;
|
||||
for (const auto &id : getStringIDPtr()->relatedIDs()) {
|
||||
list.append(Py::Long(id.value()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Py::String StringIDPy::getData() const {
|
||||
return {Py::String(getStringIDPtr()->dataToText(this->_index))};
|
||||
Py::String StringIDPy::getData() const
|
||||
{
|
||||
return Py::String(getStringIDPtr()->dataToText(this->_index));
|
||||
}
|
||||
|
||||
Py::Boolean StringIDPy::getIsBinary() const {
|
||||
return {getStringIDPtr()->isBinary()};
|
||||
Py::Boolean StringIDPy::getIsBinary() const
|
||||
{
|
||||
return Py::Boolean(getStringIDPtr()->isBinary());
|
||||
}
|
||||
|
||||
Py::Boolean StringIDPy::getIsHashed() const {
|
||||
return {getStringIDPtr()->isHashed()};
|
||||
Py::Boolean StringIDPy::getIsHashed() const
|
||||
{
|
||||
return Py::Boolean(getStringIDPtr()->isHashed());
|
||||
}
|
||||
|
||||
Py::Int StringIDPy::getIndex() const {
|
||||
return Py::Int(this->_index);
|
||||
Py::Long StringIDPy::getIndex() const
|
||||
{
|
||||
return Py::Long(this->_index);
|
||||
}
|
||||
|
||||
void StringIDPy::setIndex(Py::Int index) {
|
||||
this->_index = index;
|
||||
void StringIDPy::setIndex(Py::Long index)
|
||||
{
|
||||
this->_index = index;
|
||||
}
|
||||
|
||||
PyObject *StringIDPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int StringIDPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user