Core: Fix memory leaks with PySequence_GetItem
This commit is contained in:
@@ -100,14 +100,8 @@ PyObject* DocumentObjectPy::addProperty(PyObject *args, PyObject *kwd)
|
||||
|
||||
// enum support
|
||||
auto* propEnum = dynamic_cast<App::PropertyEnumeration*>(prop);
|
||||
if (propEnum) {
|
||||
if (enumVals && PySequence_Check(enumVals)) {
|
||||
std::vector<std::string> enumValsAsVector;
|
||||
for (Py_ssize_t i = 0; i < PySequence_Length(enumVals); ++i) {
|
||||
enumValsAsVector.emplace_back(PyUnicode_AsUTF8(PySequence_GetItem(enumVals,i)));
|
||||
}
|
||||
propEnum->setEnums(enumValsAsVector);
|
||||
}
|
||||
if (propEnum && enumVals) {
|
||||
propEnum->setPyObject(enumVals);
|
||||
}
|
||||
|
||||
return Py::new_reference_to(this);
|
||||
|
||||
@@ -70,14 +70,8 @@ PyObject* DocumentPy::addProperty(PyObject *args, PyObject *kwd)
|
||||
|
||||
// enum support
|
||||
auto* propEnum = dynamic_cast<App::PropertyEnumeration*>(prop);
|
||||
if (propEnum) {
|
||||
if (enumVals && PySequence_Check(enumVals)) {
|
||||
std::vector<std::string> enumValsAsVector;
|
||||
for (Py_ssize_t i = 0; i < PySequence_Length(enumVals); ++i) {
|
||||
enumValsAsVector.emplace_back(PyUnicode_AsUTF8(PySequence_GetItem(enumVals,i)));
|
||||
}
|
||||
propEnum->setEnums(enumValsAsVector);
|
||||
}
|
||||
if (propEnum && enumVals) {
|
||||
propEnum->setPyObject(enumVals);
|
||||
}
|
||||
|
||||
return Py::new_reference_to(this);
|
||||
|
||||
@@ -217,10 +217,10 @@ static const std::map<std::string, int> &getStatusMap() {
|
||||
return statusMap;
|
||||
}
|
||||
|
||||
PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args)
|
||||
PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args)
|
||||
{
|
||||
char* name;
|
||||
PyObject *pyValue;
|
||||
char* name {};
|
||||
PyObject* pyValue {};
|
||||
if (!PyArg_ParseTuple(args, "sO", &name, &pyValue))
|
||||
return nullptr;
|
||||
|
||||
@@ -232,47 +232,51 @@ PyObject* PropertyContainerPy::setPropertyStatus(PyObject *args)
|
||||
|
||||
auto linkProp = Base::freecad_dynamic_cast<App::PropertyLinkBase>(prop);
|
||||
std::bitset<32> status(prop->getStatus());
|
||||
size_t count = 1;
|
||||
bool isSeq = false;
|
||||
|
||||
std::vector<Py::Object> items;
|
||||
if (PyList_Check(pyValue) || PyTuple_Check(pyValue)) {
|
||||
isSeq = true;
|
||||
count = PySequence_Size(pyValue);
|
||||
Py::Sequence seq(pyValue);
|
||||
for (const auto& it : seq) {
|
||||
items.emplace_back(it);
|
||||
}
|
||||
}
|
||||
else {
|
||||
items.emplace_back(pyValue);
|
||||
}
|
||||
|
||||
for(size_t i=0; i<count; ++i) {
|
||||
Py::Object item;
|
||||
if (isSeq)
|
||||
item = Py::Object(PySequence_GetItem(pyValue,i));
|
||||
else
|
||||
item = Py::Object(pyValue);
|
||||
for (const auto& item : items) {
|
||||
bool value = true;
|
||||
if (item.isString()) {
|
||||
const auto &statusMap = getStatusMap();
|
||||
auto v = static_cast<std::string>(Py::String(item));
|
||||
if(v.size()>1 && v[0] == '-') {
|
||||
if (v.size() > 1 && v[0] == '-') {
|
||||
value = false;
|
||||
v = v.substr(1);
|
||||
}
|
||||
auto it = statusMap.find(v);
|
||||
if(it == statusMap.end()) {
|
||||
if(linkProp && v == "AllowPartial") {
|
||||
if (it == statusMap.end()) {
|
||||
if (linkProp && v == "AllowPartial") {
|
||||
linkProp->setAllowPartial(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
PyErr_Format(PyExc_ValueError, "Unknown property status '%s'", v.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
status.set(it->second,value);
|
||||
|
||||
status.set(it->second, value);
|
||||
}
|
||||
else if (item.isNumeric()) {
|
||||
int v = Py::Int(item);
|
||||
if(v<0) {
|
||||
if (v < 0) {
|
||||
value = false;
|
||||
v = -v;
|
||||
}
|
||||
if(v==0 || v>31)
|
||||
if (v == 0 || v > 31) {
|
||||
PyErr_Format(PyExc_ValueError, "Status value out of range '%d'", v);
|
||||
status.set(v,value);
|
||||
return nullptr;
|
||||
}
|
||||
status.set(v, value);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError, "Expects status type to be Int or String");
|
||||
|
||||
@@ -844,17 +844,18 @@ void PropertyIntegerSet::setPyObject(PyObject *value)
|
||||
{
|
||||
if (PySequence_Check(value)) {
|
||||
|
||||
Py_ssize_t nSize = PySequence_Length(value);
|
||||
Py::Sequence sequence(value);
|
||||
Py_ssize_t nSize = sequence.size();
|
||||
std::set<long> values;
|
||||
|
||||
for (Py_ssize_t i=0; i<nSize;++i) {
|
||||
PyObject* item = PySequence_GetItem(value, i);
|
||||
if (!PyLong_Check(item)) {
|
||||
Py::Object item = sequence.getItem(i);
|
||||
if (!PyLong_Check(item.ptr())) {
|
||||
std::string error = std::string("type in list must be int, not ");
|
||||
error += item->ob_type->tp_name;
|
||||
error += item.ptr()->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
values.insert(PyLong_AsLong(item));
|
||||
values.insert(PyLong_AsLong(item.ptr()));
|
||||
}
|
||||
|
||||
setValues(values);
|
||||
|
||||
@@ -576,14 +576,18 @@ int RotationPy::setCustomAttributes(const char* attr, PyObject* obj)
|
||||
}
|
||||
}
|
||||
else if (strcmp(attr, "Axes") == 0) {
|
||||
if (PySequence_Check(obj) && PySequence_Size(obj) == 2) {
|
||||
PyObject* vec1 = PySequence_GetItem(obj, 0);
|
||||
PyObject* vec2 = PySequence_GetItem(obj, 1);
|
||||
if (PyObject_TypeCheck(vec1, &(VectorPy::Type))
|
||||
&& PyObject_TypeCheck(vec2, &(VectorPy::Type))) {
|
||||
this->getRotationPtr()->setValue(*static_cast<VectorPy*>(vec1)->getVectorPtr(),
|
||||
*static_cast<VectorPy*>(vec2)->getVectorPtr());
|
||||
return 1;
|
||||
if (PySequence_Check(obj)) {
|
||||
Py::Sequence sequence(obj);
|
||||
if (sequence.size() == 2) {
|
||||
Py::Object vec1 = sequence.getItem(0);
|
||||
Py::Object vec2 = sequence.getItem(1);
|
||||
if (PyObject_TypeCheck(vec1.ptr(), &(VectorPy::Type))
|
||||
&& PyObject_TypeCheck(vec2.ptr(), &(VectorPy::Type))) {
|
||||
Base::Vector3d* pt1 = static_cast<VectorPy*>(vec1.ptr())->getVectorPtr();
|
||||
Base::Vector3d* pt2 = static_cast<VectorPy*>(vec2.ptr())->getVectorPtr();
|
||||
this->getRotationPtr()->setValue(*pt1, *pt2);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,28 +410,28 @@ PyObject* ViewProviderPy::partialRender(PyObject* args)
|
||||
return nullptr;
|
||||
|
||||
std::vector<std::string> values;
|
||||
if(value != Py_None) {
|
||||
PyObject *item = nullptr;
|
||||
Py_ssize_t nSize;
|
||||
if (PyList_Check(value) || PyTuple_Check(value))
|
||||
nSize = PySequence_Size(value);
|
||||
else {
|
||||
item = value;
|
||||
value = nullptr;
|
||||
nSize = 1;
|
||||
if (value != Py_None) {
|
||||
std::vector<Py::Object> pylist;
|
||||
if (PyList_Check(value) || PyTuple_Check(value)) {
|
||||
Py::Sequence seq(value);
|
||||
for (const auto& it : seq) {
|
||||
pylist.emplace_back(it);
|
||||
}
|
||||
}
|
||||
values.resize(nSize);
|
||||
for (Py_ssize_t i = 0; i < nSize; ++i) {
|
||||
if(value)
|
||||
item = PySequence_GetItem(value, i);
|
||||
if (PyUnicode_Check(item)) {
|
||||
values[i] = PyUnicode_AsUTF8(item);
|
||||
else {
|
||||
pylist.emplace_back(value);
|
||||
}
|
||||
|
||||
values.reserve(pylist.size());
|
||||
for (const auto& it : pylist) {
|
||||
if (it.isString()) {
|
||||
values.push_back(Py::String(it));
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be str");
|
||||
error += " not, ";
|
||||
error += item->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
error += it.ptr()->ob_type->tp_name;
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user