Copilot commented on code in PR #50409:
URL: https://github.com/apache/arrow/pull/50409#discussion_r3547474573


##########
python/pyarrow/src/arrow/python/datetime.cc:
##########
@@ -596,7 +597,7 @@ Result<std::string> TzinfoToString(PyObject* tzinfo) {
 
 PyObject* MonthDayNanoIntervalToNamedTuple(
     const MonthDayNanoIntervalType::MonthDayNanos& interval) {
-  OwnedRef tuple(PyStructSequence_New(&MonthDayNanoTupleType));
+  OwnedRef tuple(PyStructSequence_New(MonthDayNanoTupleType));
   if (ARROW_PREDICT_FALSE(tuple.obj() == nullptr)) {
     return nullptr;

Review Comment:
   MonthDayNanoTupleType can be nullptr here unless NewMonthDayNanoTupleType() 
was called earlier. PyStructSequence_New(nullptr) is undefined behavior and can 
segfault; previously passing &MonthDayNanoTupleType at least avoided a null 
pointer. Ensure the cached type is initialized before use (and balance the 
refcount from NewMonthDayNanoTupleType).



##########
python/pyarrow/src/arrow/python/python_to_arrow.cc:
##########
@@ -1050,8 +1049,8 @@ class PyStructConverter : public 
StructConverter<PyConverter, PyConverterTrait>
       PyObject* unicode =
           PyUnicode_FromStringAndSize(field_name.c_str(), field_name.size());
       RETURN_IF_PYERROR();
-      PyList_SET_ITEM(bytes_field_names_.obj(), i, bytes);
-      PyList_SET_ITEM(unicode_field_names_.obj(), i, unicode);
+      PyList_SetItem(bytes_field_names_.obj(), i, bytes);
+      PyList_SetItem(unicode_field_names_.obj(), i, unicode);

Review Comment:
   PyList_SetItem() can fail and does not steal references on failure. The 
current code ignores the return value (and doesn't check PyErr), which can 
leave a pending exception and leak the created objects if an unexpected failure 
occurs.



##########
python/pyarrow/src/arrow/python/arrow_to_pandas.cc:
##########
@@ -1016,8 +1016,8 @@ Status ConvertMap(PandasOptions options, const 
ChunkedArray& data,
           return CheckPyError();
         },
         [&list_item](int64_t idx, OwnedRef& key_value, OwnedRef& item_value) {
-          PyList_SET_ITEM(list_item.obj(), idx,
-                          PyTuple_Pack(2, key_value.obj(), item_value.obj()));
+          PyList_SetItem(list_item.obj(), idx,
+                         PyTuple_Pack(2, key_value.obj(), item_value.obj()));
           return CheckPyError();

Review Comment:
   PyList_SetItem() can fail and only steals the tuple reference on success. As 
written, a SetItem failure would leak the tuple from PyTuple_Pack and rely on 
CheckPyError() to notice the error later. Consider creating the tuple first, 
checking errors, and detaching only after a successful SetItem.



##########
python/pyarrow/src/arrow/python/python_to_arrow.cc:
##########
@@ -1266,7 +1265,7 @@ Status ConvertToSequenceAndInferSize(PyObject* obj, 
PyObject** seq, int64_t* siz
         RETURN_IF_PYERROR();
         break;
       }
-      PyList_SET_ITEM(lst, i, item);
+      PyList_SetItem(lst, i, item);

Review Comment:
   PyList_SetItem() returns -1 on failure and does not steal a reference in 
that case. Ignoring the return value can leak `item` and leave a Python 
exception set, causing later C API calls to fail unpredictably.



##########
python/pyarrow/src/arrow/python/helpers.cc:
##########
@@ -121,12 +122,29 @@ std::string PyObject_StdStringRepr(PyObject* obj) {
   if (!bytes_ref) {
     PyErr_Clear();
     std::stringstream ss;
-    ss << "<object of type '" << Py_TYPE(obj)->tp_name << "' repr() failed>";
+    ss << "<object of type '" << PyObject_StdStringTypeName(obj) << "' repr() 
failed>";
     return ss.str();
   }
   return PyBytes_AsStdString(bytes_ref.obj());
 }
 
+std::string PyObject_StdStringTypeName(PyObject* obj) {
+  // Once Python 3.10 is dropped, this can use PyType_GetName(Py_TYPE(obj)) 
(added in 3.11).
+  OwnedRef name_ref(
+      PyObject_GetAttrString(reinterpret_cast<PyObject*>(Py_TYPE(obj)), 
"__name__"));
+  if (!name_ref) {
+    PyErr_Clear();
+    return "?";
+  }
+  Py_ssize_t size;
+  const char* data = PyUnicode_AsUTF8AndSize(name_ref.obj(), &size);
+  if (data == nullptr) {
+    PyErr_Clear();
+    return "?";
+  }
+  return std::string(data, size);
+}

Review Comment:
   PyObject_StdStringTypeName() currently returns type.__name__ only, which 
drops the module-qualified name previously provided by tp_name (e.g., 
"pkg.Class" -> "Class"). This can make new/updated error messages less 
informative. Consider returning "{__module__}.{__qualname__}" (dropping the 
module for builtins) to preserve prior behavior while avoiding direct struct 
access.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to