Core: Fix memory leaks with PySequence_GetItem

This commit is contained in:
wmayer
2024-05-08 23:40:27 +02:00
parent 5b98af4591
commit 58988a7482
6 changed files with 63 additions and 66 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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");

View File

@@ -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);

View File

@@ -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;
}
}
}
}

View File

@@ -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);
}
}
}