From: Gerhard Sittig Date: Sun, 1 Nov 2020 11:33:47 +0000 (+0100) Subject: decoder: check annotation rows' references to annotation classes X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=8ab7ede6bb84e78232a8927fea16295040d650b4;p=libsigrokdecode.git decoder: check annotation rows' references to annotation classes Check the annotation class indices when iterating annotation rows. Refuse to load decoders with inconsistent declarations, emit error messages to raise developers' awareness of implementation bugs. This fixes bug #1601. --- diff --git a/decoder.c b/decoder.c index 3e04722..cc0a1e1 100644 --- a/decoder.c +++ b/decoder.c @@ -391,7 +391,7 @@ err_out: } /* Convert annotation class attribute to GSList of char **. */ -static int get_annotations(struct srd_decoder *dec) +static int get_annotations(struct srd_decoder *dec, size_t *ret_count) { PyObject *py_annlist, *py_ann; GSList *annotations; @@ -399,6 +399,9 @@ static int get_annotations(struct srd_decoder *dec) ssize_t i; PyGILState_STATE gstate; + if (ret_count) + *ret_count = 0; + gstate = PyGILState_Ensure(); if (!PyObject_HasAttrString(dec->py_dec, "annotations")) { @@ -418,7 +421,10 @@ static int get_annotations(struct srd_decoder *dec) goto err_out; } - for (i = PyTuple_Size(py_annlist) - 1; i >= 0; i--) { + i = PyTuple_Size(py_annlist); + if (ret_count) + *ret_count = i; + while (i--) { py_ann = PyTuple_GetItem(py_annlist, i); if (!py_ann) goto except_out; @@ -451,7 +457,7 @@ err_out: } /* Convert annotation_rows to GSList of 'struct srd_decoder_annotation_row'. */ -static int get_annotation_rows(struct srd_decoder *dec) +static int get_annotation_rows(struct srd_decoder *dec, size_t cls_count) { const char *py_member_name = "annotation_rows"; @@ -530,6 +536,11 @@ static int get_annotation_rows(struct srd_decoder *dec) class_idx = PyLong_AsSize_t(py_item); if (PyErr_Occurred()) goto except_out; + if (class_idx >= cls_count) { + srd_err("Protocol decoder %s annotation row %zd references invalid class %zu.", + dec->name, i, class_idx); + goto err_out; + } ann_row->ann_classes = g_slist_prepend(ann_row->ann_classes, GSIZE_TO_POINTER(class_idx)); @@ -815,6 +826,7 @@ SRD_API int srd_decoder_load(const char *module_name) int is_subclass; const char *fail_txt; PyGILState_STATE gstate; + size_t ann_cls_count; if (!srd_check_init()) return SRD_ERR; @@ -957,12 +969,12 @@ SRD_API int srd_decoder_load(const char *module_name) goto err_out; } - if (get_annotations(d) != SRD_OK) { + if (get_annotations(d, &ann_cls_count) != SRD_OK) { fail_txt = "cannot get annotations"; goto err_out; } - if (get_annotation_rows(d) != SRD_OK) { + if (get_annotation_rows(d, ann_cls_count) != SRD_OK) { fail_txt = "cannot get annotation rows"; goto err_out; }