perf python: Check counts_values size in set_values

The set_values function incorrectly assumed the list contained exactly
5 elements. Add a check to prevent out-of-bounds access.

Fixes: 877108e42b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
Ian Rogers 2026-08-09 00:14:46 -07:00 committed by Namhyung Kim
parent 44e82c4d2f
commit 612aca22a9

View File

@ -1881,11 +1881,11 @@ static void pyrf_counts_values__delete(struct pyrf_counts_values *pcounts_values
0, help }
static PyMemberDef pyrf_counts_values_members[] = {
counts_values_member_def(val, T_ULONG, "Value of event"),
counts_values_member_def(ena, T_ULONG, "Time for which enabled"),
counts_values_member_def(run, T_ULONG, "Time for which running"),
counts_values_member_def(id, T_ULONG, "Unique ID for an event"),
counts_values_member_def(lost, T_ULONG, "Num of lost samples"),
counts_values_member_def(val, T_ULONGLONG, "Value of event"),
counts_values_member_def(ena, T_ULONGLONG, "Time for which enabled"),
counts_values_member_def(run, T_ULONGLONG, "Time for which running"),
counts_values_member_def(id, T_ULONGLONG, "Unique ID for an event"),
counts_values_member_def(lost, T_ULONGLONG, "Num of lost samples"),
{ .name = NULL, },
};
@ -1895,8 +1895,15 @@ static PyObject *pyrf_counts_values_get_values(struct pyrf_counts_values *self,
if (!vals)
return NULL;
for (int i = 0; i < 5; i++)
PyList_SetItem(vals, i, PyLong_FromLong(self->values.values[i]));
for (int i = 0; i < 5; i++) {
PyObject *val = PyLong_FromUnsignedLongLong(self->values.values[i]);
if (!val) {
Py_DECREF(vals);
return NULL;
}
PyList_SetItem(vals, i, val);
}
return vals;
}
@ -1907,19 +1914,34 @@ static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObje
Py_ssize_t size;
PyObject *item = NULL;
if (list == NULL) {
PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
return -1;
}
if (!PyList_Check(list)) {
PyErr_SetString(PyExc_TypeError, "Value assigned must be a list");
return -1;
}
size = PyList_Size(list);
if (size != 5) {
PyErr_SetString(PyExc_ValueError, "List must have exactly 5 entries");
return -1;
}
for (Py_ssize_t i = 0; i < size; i++) {
unsigned long long val;
item = PyList_GetItem(list, i);
if (!PyLong_Check(item)) {
PyErr_SetString(PyExc_TypeError, "List members should be numbers");
return -1;
}
self->values.values[i] = PyLong_AsLong(item);
val = PyLong_AsUnsignedLongLong(item);
if (val == (unsigned long long)-1 && PyErr_Occurred())
return -1;
self->values.values[i] = val;
}
return 0;