Author: gclayton Date: Wed Aug 10 18:25:57 2016 New Revision: 278304 URL: http://llvm.org/viewvc/llvm-project?rev=278304&view=rev Log: Fix a problem where if a uint64_t value is placed into a python dictionary and sent up to LLDB and converted to StructuredData, it would not be able to parse the full 64 bit value. A number like 0xf000000000000000L could be placed into a dictionary, and sent to LLDB and it would end up being 0xffffffffffffffff since it would overflow a int64_t. We leave the old code there, but if it overflows, we treat the number like a uint64_t and get it to decode correctly. Added a gtest to cover this so we don't regress. I verified the gtest failed prior to the fix, and it succeeds after it.
<rdar://problem/27409265> Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp Modified: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp?rev=278304&r1=278303&r2=278304&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (original) +++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp Wed Aug 10 18:25:57 2016 @@ -624,7 +624,18 @@ PythonInteger::GetInteger() const { assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); - return PyLong_AsLongLong(m_py_obj); + int overflow = 0; + int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow); + if (overflow != 0) + { + // We got an integer that overflows, like 18446744072853913392L + // we can't use PyLong_AsLongLong() as it will return + // 0xffffffffffffffff. If we use the unsigned long long + // it will work as expected. + const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj); + result = *((int64_t *)&uval); + } + return result; } return UINT64_MAX; } Modified: lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp?rev=278304&r1=278303&r2=278304&view=diff ============================================================================== --- lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp (original) +++ lldb/trunk/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp Wed Aug 10 18:25:57 2016 @@ -595,3 +595,27 @@ TEST_F(PythonDataObjectsTest, TestObject EXPECT_TRUE(numerator_attr.IsAllocated()); EXPECT_EQ(42, numerator_attr.GetInteger()); } + +TEST_F(PythonDataObjectsTest, TestExtractingUInt64ThroughStructuredData) +{ + // Make up a custom dictionary with "sys" pointing to the `sys` module. + const char *key_name = "addr"; + const uint64_t value = 0xf000000000000000ull; + PythonDictionary python_dict(PyInitialValue::Empty); + PythonInteger python_ull_value(PyRefType::Owned, PyLong_FromUnsignedLongLong(value)); + python_dict.SetItemForKey(PythonString(key_name), python_ull_value); + StructuredData::ObjectSP structured_data_sp = python_dict.CreateStructuredObject(); + EXPECT_TRUE((bool)structured_data_sp); + if (structured_data_sp) + { + StructuredData::Dictionary *structured_dict_ptr = structured_data_sp->GetAsDictionary(); + EXPECT_TRUE(structured_dict_ptr != nullptr); + if (structured_dict_ptr) + { + StructuredData::ObjectSP structured_addr_value_sp = structured_dict_ptr->GetValueForKey(key_name); + EXPECT_TRUE((bool)structured_addr_value_sp); + const uint64_t extracted_value = structured_addr_value_sp->GetIntegerValue(123); + EXPECT_TRUE(extracted_value == value); + } + } +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits