From c005a6924bb0b9cc1a72b17d2ebecf936ed4c057 Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Fri, 26 Sep 2025 22:08:08 +0200 Subject: [PATCH] Sketcher: Fix crash on Sketcher.Constraint (#24269) * Sketcher: Fix crash on Sketcher.Constraint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/Mod/Sketcher/App/ConstraintPyImp.cpp | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Mod/Sketcher/App/ConstraintPyImp.cpp b/src/Mod/Sketcher/App/ConstraintPyImp.cpp index 07014ec41e..64077f1617 100644 --- a/src/Mod/Sketcher/App/ConstraintPyImp.cpp +++ b/src/Mod/Sketcher/App/ConstraintPyImp.cpp @@ -44,6 +44,36 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/) if (PyArg_ParseTuple(args, "")) { return 0; } + // The first argument must be a string (the constraint type). + PyObject* typeObj = PyTuple_GetItem(args, 0); + if (!PyUnicode_Check(typeObj)) { + PyErr_SetString(PyExc_TypeError, + "First argument to Constraint must be a string (the constraint type)"); + return -1; + } + + // Validate the types of the remaining arguments. + // The arguments representing a GeoId or a PosId MUST be integers. + // Values can be numbers (float/int). We allow any PyNumber for them. + // The logic here is to check arguments that are passed for GeoId/PosId. + // Preventing garbage values if we receive a Part.LineSegment which can crash + // see https://github.com/FreeCAD/FreeCAD/issues/17721 + for (int i = 1; i < PyTuple_Size(args); ++i) { + PyObject* current_arg = PyTuple_GetItem(args, i); // Borrowed reference + + // A simple but effective rule: if it's not a list or a bool, it must be a number for now. + // The most critical check is for non-numeric types being passed for an index. + if (Py_TYPE(current_arg)->tp_as_number == NULL && !PyBool_Check(current_arg) + && !PyList_Check(current_arg)) { + PyErr_Format(PyExc_TypeError, + "Invalid argument type for Constraint. " + "Expected an integer for a geometry or point index, but got type '%s' at " + "argument %d.", + Py_TYPE(current_arg)->tp_name, + i + 1); + return -1; + } + } PyErr_Clear();