PyDict_Next does not guarantee pos is contiguous, and pypy increments past the end of the dict size. Patch fixes reliance on pos for constructing args for gpiod call. Signed-off-by: George Harker <george@xxxxxxxxxxxxxxxxxxxxx> --- bindings/python/gpiod/ext/request.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/bindings/python/gpiod/ext/request.c b/bindings/python/gpiod/ext/request.c index e1a2a42..997e6fc 100644 --- a/bindings/python/gpiod/ext/request.c +++ b/bindings/python/gpiod/ext/request.c @@ -205,7 +205,7 @@ static PyObject *request_get_values(request_object *self, PyObject *args) static PyObject *request_set_values(request_object *self, PyObject *args) { PyObject *values, *key, *val, *val_stripped; - Py_ssize_t pos = 0; + Py_ssize_t pos = 0, index = 0; int ret; ret = PyArg_ParseTuple(args, "O", &values); @@ -214,8 +214,9 @@ static PyObject *request_set_values(request_object *self, PyObject *args) clear_buffers(self); + /* Note: pos may not be contiguous. */ while (PyDict_Next(values, &pos, &key, &val)) { - self->offsets[pos - 1] = Py_gpiod_PyLongAsUnsignedInt(key); + self->offsets[index] = Py_gpiod_PyLongAsUnsignedInt(key); if (PyErr_Occurred()) return NULL; @@ -223,15 +224,17 @@ static PyObject *request_set_values(request_object *self, PyObject *args) if (!val_stripped) return NULL; - self->values[pos - 1] = PyLong_AsLong(val_stripped); + self->values[index] = PyLong_AsLong(val_stripped); Py_DECREF(val_stripped); if (PyErr_Occurred()) return NULL; + + index++; } Py_BEGIN_ALLOW_THREADS; ret = gpiod_line_request_set_values_subset(self->request, - pos, + index, self->offsets, self->values); Py_END_ALLOW_THREADS; -- 2.39.5