]> sigrok.org Git - libsigrokdecode.git/commitdiff
decoder: check annotation rows' references to annotation classes
authorGerhard Sittig <redacted>
Sun, 1 Nov 2020 11:33:47 +0000 (12:33 +0100)
committerGerhard Sittig <redacted>
Sun, 9 Jan 2022 16:53:37 +0000 (17:53 +0100)
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.

decoder.c

index 3e047221e844f67fd74856410d8d2670389b3094..cc0a1e1f8a2834fc787f8d08edcafc94e3b65018 100644 (file)
--- 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;
        }