From 854fd940165736db01eeff05719f1a60a6a89a8b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 3 May 2013 01:13:51 +0000 Subject: bge py api: raise an overflow exception when assigning a float to a bge object which is out of the float range. also avoid raising exceptions by ConvertPythonToValue when they will be ignored. --- source/gameengine/Expressions/ListValue.cpp | 8 ++++---- source/gameengine/Expressions/Value.cpp | 31 ++++++++++++++++++++++------- source/gameengine/Expressions/Value.h | 2 +- source/gameengine/Ketsji/KX_GameObject.cpp | 21 ++++++++++--------- 4 files changed, 39 insertions(+), 23 deletions(-) (limited to 'source') diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index abab40cbe67..c40394eceb1 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -425,7 +425,7 @@ static PyObject *listvalue_buffer_concat(PyObject *self, PyObject *other) for (i=0;iConvertPythonToValue(PyList_GetItem(other,i), "cList + pyList: CListValue, "); + listitemval = listval->ConvertPythonToValue(PyList_GetItem(other,i), true, "cList + pyList: CListValue, "); if (listitemval) { listval_new->SetValue(i+numitems_orig, listitemval); @@ -570,7 +570,7 @@ PyAttributeDef CListValue::Attributes[] = { PyObject *CListValue::Pyappend(PyObject *value) { - CValue* objval = ConvertPythonToValue(value, "CList.append(i): CValueList, "); + CValue *objval = ConvertPythonToValue(value, true, "CList.append(i): CValueList, "); if (!objval) /* ConvertPythonToValue sets the error */ return NULL; @@ -595,7 +595,7 @@ PyObject *CListValue::Pyindex(PyObject *value) { PyObject *result = NULL; - CValue* checkobj = ConvertPythonToValue(value, "val = cList[i]: CValueList, "); + CValue *checkobj = ConvertPythonToValue(value, true, "val = cList[i]: CValueList, "); if (checkobj==NULL) return NULL; /* ConvertPythonToValue sets the error */ @@ -624,7 +624,7 @@ PyObject *CListValue::Pycount(PyObject *value) { int numfound = 0; - CValue* checkobj = ConvertPythonToValue(value, ""); /* error ignored */ + CValue *checkobj = ConvertPythonToValue(value, false, ""); /* error ignored */ if (checkobj==NULL) { /* in this case just return that there are no items in the list */ PyErr_Clear(); diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 383e83dcd89..e5c4001de4c 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -537,10 +537,17 @@ PyObject *CValue::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrde return PyUnicode_From_STR_String(self->GetName()); } -CValue* CValue::ConvertPythonToValue(PyObject *pyobj, const char *error_prefix) +/** + * There are 2 reasons this could return NULL + * - unsupported type. + * - error converting (overflow). + * + * \param do_type_exception Use to skip raising an exception for unknown types. + */ +CValue *CValue::ConvertPythonToValue(PyObject *pyobj, const bool do_type_exception, const char *error_prefix) { - CValue* vallie = NULL; + CValue *vallie; /* refcounting is broking here! - this crashes anyway, just store a python list for KX_GameObject */ #if 0 if (PyList_Check(pyobj)) @@ -581,7 +588,14 @@ CValue* CValue::ConvertPythonToValue(PyObject *pyobj, const char *error_prefix) } else if (PyFloat_Check(pyobj)) { - vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) ); + const double tval = PyFloat_AsDouble(pyobj); + if (tval > (double)FLT_MAX || tval < (double)-FLT_MAX) { + PyErr_Format(PyExc_OverflowError, "%soverflow converting from float, out of internal range", error_prefix); + vallie = NULL; + } + else { + vallie = new CFloatValue((float)tval); + } } else if (PyLong_Check(pyobj)) { @@ -594,10 +608,13 @@ CValue* CValue::ConvertPythonToValue(PyObject *pyobj, const char *error_prefix) if (PyObject_TypeCheck(pyobj, &CValue::Type)) /* Note, don't let these get assigned to GameObject props, must check elsewhere */ { vallie = (static_cast(BGE_PROXY_REF(pyobj)))->AddRef(); - } else - { - /* return an error value from the caller */ - PyErr_Format(PyExc_TypeError, "%scould convert python value to a game engine property", error_prefix); + } + else { + if (do_type_exception) { + /* return an error value from the caller */ + PyErr_Format(PyExc_TypeError, "%scould convert python value to a game engine property", error_prefix); + } + vallie = NULL; } return vallie; diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index e9bb6b1ba3c..db7d69a638f 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -220,7 +220,7 @@ public: return NULL; } - virtual CValue *ConvertPythonToValue(PyObject *pyobj, const char *error_prefix); + virtual CValue *ConvertPythonToValue(PyObject *pyobj, const bool do_type_exception, const char *error_prefix); static PyObject *pyattr_get_name(void *self, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 172440cfcb6..f52ee0c42c3 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1858,15 +1858,14 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) } } else { /* ob["key"] = value */ - int set= 0; + bool set = false; /* as CValue */ if (attr_str && PyObject_TypeCheck(val, &PyObjectPlus::Type)==0) /* don't allow GameObjects for eg to be assigned to CValue props */ { - CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */ + CValue *vallie = self->ConvertPythonToValue(val, false, "gameOb[key] = value: "); - if (vallie) - { + if (vallie) { CValue* oldprop = self->GetProperty(attr_str); if (oldprop) @@ -1875,7 +1874,7 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) self->SetProperty(attr_str, vallie); vallie->Release(); - set= 1; + set = true; /* try remove dict value to avoid double ups */ if (self->m_attr_dict) { @@ -1883,13 +1882,12 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) PyErr_Clear(); } } - else { - PyErr_Clear(); + else if (PyErr_Occurred()) { + return -1; } } - if (set==0) - { + if (set == false) { if (self->m_attr_dict==NULL) /* lazy init */ self->m_attr_dict= PyDict_New(); @@ -1898,7 +1896,7 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) { if (attr_str) self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */ - set= 1; + set = true; } else { if (attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str); @@ -1906,8 +1904,9 @@ static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) } } - if (set==0) + if (set == false) { return -1; /* pythons error value */ + } } -- cgit v1.2.3