tools lib traceevent: Get rid of die() in reparent_op_arg()
[firefly-linux-kernel-4.4.55.git] / tools / lib / traceevent / parse-filter.c
index 2500e75583fcc26e6380731d407dc6d985ba6929..9b05892566e06b59cf2f2b169fed101bf9e0de4a 100644 (file)
@@ -56,7 +56,21 @@ static void show_error(char **error_str, const char *fmt, ...)
        index = pevent_get_input_buf_ptr();
        len = input ? strlen(input) : 0;
 
-       error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3);
+       error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3);
+       if (error == NULL) {
+               /*
+                * Maybe it's due to len is too long.
+                * Retry without the input buffer part.
+                */
+               len = 0;
+
+               error = malloc(MAX_ERR_STR_SIZE);
+               if (error == NULL) {
+                       /* no memory */
+                       *error_str = NULL;
+                       return;
+               }
+       }
 
        if (len) {
                strcpy(error, input);
@@ -95,7 +109,11 @@ static enum event_type read_token(char **tok)
            (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
            pevent_peek_char() == '~') {
                /* append it */
-               *tok = malloc_or_die(3);
+               *tok = malloc(3);
+               if (*tok == NULL) {
+                       free_token(token);
+                       return EVENT_ERROR;
+               }
                sprintf(*tok, "%c%c", *token, '~');
                free_token(token);
                /* Now remove the '~' from the buffer */
@@ -147,11 +165,13 @@ add_filter_type(struct event_filter *filter, int id)
        if (filter_type)
                return filter_type;
 
-       filter->event_filters = realloc(filter->event_filters,
-                                       sizeof(*filter->event_filters) *
-                                       (filter->filters + 1));
-       if (!filter->event_filters)
-               die("Could not allocate filter");
+       filter_type = realloc(filter->event_filters,
+                             sizeof(*filter->event_filters) *
+                             (filter->filters + 1));
+       if (!filter_type)
+               return NULL;
+
+       filter->event_filters = filter_type;
 
        for (i = 0; i < filter->filters; i++) {
                if (filter->event_filters[i].event_id > id)
@@ -182,7 +202,10 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent)
 {
        struct event_filter *filter;
 
-       filter = malloc_or_die(sizeof(*filter));
+       filter = malloc(sizeof(*filter));
+       if (filter == NULL)
+               return NULL;
+
        memset(filter, 0, sizeof(*filter));
        filter->pevent = pevent;
        pevent_ref(pevent);
@@ -192,12 +215,7 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent)
 
 static struct filter_arg *allocate_arg(void)
 {
-       struct filter_arg *arg;
-
-       arg = malloc_or_die(sizeof(*arg));
-       memset(arg, 0, sizeof(*arg));
-
-       return arg;
+       return calloc(1, sizeof(struct filter_arg));
 }
 
 static void free_arg(struct filter_arg *arg)
@@ -242,15 +260,19 @@ static void free_arg(struct filter_arg *arg)
        free(arg);
 }
 
-static void add_event(struct event_list **events,
+static int add_event(struct event_list **events,
                      struct event_format *event)
 {
        struct event_list *list;
 
-       list = malloc_or_die(sizeof(*list));
+       list = malloc(sizeof(*list));
+       if (list == NULL)
+               return -1;
+
        list->next = *events;
        *events = list;
        list->event = event;
+       return 0;
 }
 
 static int event_match(struct event_format *event,
@@ -265,7 +287,7 @@ static int event_match(struct event_format *event,
                !regexec(ereg, event->name, 0, NULL, 0);
 }
 
-static int
+static enum pevent_errno
 find_event(struct pevent *pevent, struct event_list **events,
           char *sys_name, char *event_name)
 {
@@ -273,6 +295,7 @@ find_event(struct pevent *pevent, struct event_list **events,
        regex_t ereg;
        regex_t sreg;
        int match = 0;
+       int fail = 0;
        char *reg;
        int ret;
        int i;
@@ -283,23 +306,31 @@ find_event(struct pevent *pevent, struct event_list **events,
                sys_name = NULL;
        }
 
-       reg = malloc_or_die(strlen(event_name) + 3);
+       reg = malloc(strlen(event_name) + 3);
+       if (reg == NULL)
+               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+
        sprintf(reg, "^%s$", event_name);
 
        ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
        free(reg);
 
        if (ret)
-               return -1;
+               return PEVENT_ERRNO__INVALID_EVENT_NAME;
 
        if (sys_name) {
-               reg = malloc_or_die(strlen(sys_name) + 3);
+               reg = malloc(strlen(sys_name) + 3);
+               if (reg == NULL) {
+                       regfree(&ereg);
+                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               }
+
                sprintf(reg, "^%s$", sys_name);
                ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
                free(reg);
                if (ret) {
                        regfree(&ereg);
-                       return -1;
+                       return PEVENT_ERRNO__INVALID_EVENT_NAME;
                }
        }
 
@@ -307,7 +338,10 @@ find_event(struct pevent *pevent, struct event_list **events,
                event = pevent->events[i];
                if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
                        match = 1;
-                       add_event(events, event);
+                       if (add_event(events, event) < 0) {
+                               fail = 1;
+                               break;
+                       }
                }
        }
 
@@ -316,7 +350,9 @@ find_event(struct pevent *pevent, struct event_list **events,
                regfree(&sreg);
 
        if (!match)
-               return -1;
+               return PEVENT_ERRNO__EVENT_NOT_FOUND;
+       if (fail)
+               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
 
        return 0;
 }
@@ -340,6 +376,10 @@ create_arg_item(struct event_format *event, const char *token,
        struct filter_arg *arg;
 
        arg = allocate_arg();
+       if (arg == NULL) {
+               show_error(error_str, "failed to allocate filter arg");
+               return NULL;
+       }
 
        switch (type) {
 
@@ -349,8 +389,11 @@ create_arg_item(struct event_format *event, const char *token,
                arg->value.type =
                        type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
                arg->value.str = strdup(token);
-               if (!arg->value.str)
-                       die("malloc string");
+               if (!arg->value.str) {
+                       free_arg(arg);
+                       show_error(error_str, "failed to allocate string filter arg");
+                       return NULL;
+               }
                break;
        case EVENT_ITEM:
                /* if it is a number, then convert it */
@@ -390,6 +433,9 @@ create_arg_op(enum filter_op_type btype)
        struct filter_arg *arg;
 
        arg = allocate_arg();
+       if (!arg)
+               return NULL;
+
        arg->type = FILTER_ARG_OP;
        arg->op.type = btype;
 
@@ -402,6 +448,9 @@ create_arg_exp(enum filter_exp_type etype)
        struct filter_arg *arg;
 
        arg = allocate_arg();
+       if (!arg)
+               return NULL;
+
        arg->type = FILTER_ARG_EXP;
        arg->op.type = etype;
 
@@ -414,6 +463,9 @@ create_arg_cmp(enum filter_exp_type etype)
        struct filter_arg *arg;
 
        arg = allocate_arg();
+       if (!arg)
+               return NULL;
+
        /* Use NUM and change if necessary */
        arg->type = FILTER_ARG_NUM;
        arg->op.type = etype;
@@ -421,8 +473,8 @@ create_arg_cmp(enum filter_exp_type etype)
        return arg;
 }
 
-static int add_right(struct filter_arg *op, struct filter_arg *arg,
-                    char **error_str)
+static enum pevent_errno
+add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str)
 {
        struct filter_arg *left;
        char *str;
@@ -453,9 +505,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
                case FILTER_ARG_FIELD:
                        break;
                default:
-                       show_error(error_str,
-                                  "Illegal rvalue");
-                       return -1;
+                       show_error(error_str, "Illegal rvalue");
+                       return PEVENT_ERRNO__ILLEGAL_RVALUE;
                }
 
                /*
@@ -502,7 +553,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
                        if (left->type != FILTER_ARG_FIELD) {
                                show_error(error_str,
                                           "Illegal lvalue for string comparison");
-                               return -1;
+                               return PEVENT_ERRNO__ILLEGAL_LVALUE;
                        }
 
                        /* Make sure this is a valid string compare */
@@ -521,25 +572,31 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
                                        show_error(error_str,
                                                   "RegEx '%s' did not compute",
                                                   str);
-                                       return -1;
+                                       return PEVENT_ERRNO__INVALID_REGEX;
                                }
                                break;
                        default:
                                show_error(error_str,
                                           "Illegal comparison for string");
-                               return -1;
+                               return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
                        }
 
                        op->type = FILTER_ARG_STR;
                        op->str.type = op_type;
                        op->str.field = left->field.field;
                        op->str.val = strdup(str);
-                       if (!op->str.val)
-                               die("malloc string");
+                       if (!op->str.val) {
+                               show_error(error_str, "Failed to allocate string filter");
+                               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       }
                        /*
                         * Need a buffer to copy data for tests
                         */
-                       op->str.buffer = malloc_or_die(op->str.field->size + 1);
+                       op->str.buffer = malloc(op->str.field->size + 1);
+                       if (!op->str.buffer) {
+                               show_error(error_str, "Failed to allocate string filter");
+                               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       }
                        /* Null terminate this buffer */
                        op->str.buffer[op->str.field->size] = 0;
 
@@ -557,7 +614,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
                        case FILTER_CMP_NOT_REGEX:
                                show_error(error_str,
                                           "Op not allowed with integers");
-                               return -1;
+                               return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
 
                        default:
                                break;
@@ -577,9 +634,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg,
        return 0;
 
  out_fail:
-       show_error(error_str,
-                  "Syntax error");
-       return -1;
+       show_error(error_str, "Syntax error");
+       return PEVENT_ERRNO__SYNTAX_ERROR;
 }
 
 static struct filter_arg *
@@ -592,7 +648,7 @@ rotate_op_right(struct filter_arg *a, struct filter_arg *b)
        return arg;
 }
 
-static int add_left(struct filter_arg *op, struct filter_arg *arg)
+static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
 {
        switch (op->type) {
        case FILTER_ARG_EXP:
@@ -611,11 +667,11 @@ static int add_left(struct filter_arg *op, struct filter_arg *arg)
                /* left arg of compares must be a field */
                if (arg->type != FILTER_ARG_FIELD &&
                    arg->type != FILTER_ARG_BOOLEAN)
-                       return -1;
+                       return PEVENT_ERRNO__INVALID_ARG_TYPE;
                op->num.left = arg;
                break;
        default:
-               return -1;
+               return PEVENT_ERRNO__INVALID_ARG_TYPE;
        }
        return 0;
 }
@@ -728,15 +784,18 @@ enum filter_vals {
        FILTER_VAL_TRUE,
 };
 
-void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
-                 struct filter_arg *arg)
+static enum pevent_errno
+reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
+               struct filter_arg *arg, char **error_str)
 {
        struct filter_arg *other_child;
        struct filter_arg **ptr;
 
        if (parent->type != FILTER_ARG_OP &&
-           arg->type != FILTER_ARG_OP)
-               die("can not reparent other than OP");
+           arg->type != FILTER_ARG_OP) {
+               show_error(error_str, "can not reparent other than OP");
+               return PEVENT_ERRNO__REPARENT_NOT_OP;
+       }
 
        /* Get the sibling */
        if (old_child->op.right == arg) {
@@ -745,8 +804,10 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
        } else if (old_child->op.left == arg) {
                ptr = &old_child->op.left;
                other_child = old_child->op.right;
-       } else
-               die("Error in reparent op, find other child");
+       } else {
+               show_error(error_str, "Error in reparent op, find other child");
+               return PEVENT_ERRNO__REPARENT_FAILED;
+       }
 
        /* Detach arg from old_child */
        *ptr = NULL;
@@ -757,23 +818,29 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
                *parent = *arg;
                /* Free arg without recussion */
                free(arg);
-               return;
+               return 0;
        }
 
        if (parent->op.right == old_child)
                ptr = &parent->op.right;
        else if (parent->op.left == old_child)
                ptr = &parent->op.left;
-       else
-               die("Error in reparent op");
+       else {
+               show_error(error_str, "Error in reparent op");
+               return PEVENT_ERRNO__REPARENT_FAILED;
+       }
+
        *ptr = arg;
 
        free_arg(old_child);
+       return 0;
 }
 
-enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
+/* Returns either filter_vals (success) or pevent_errno (failfure) */
+static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
+                   char **error_str)
 {
-       enum filter_vals lval, rval;
+       int lval, rval;
 
        switch (arg->type) {
 
@@ -788,63 +855,68 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
                return FILTER_VAL_NORM;
 
        case FILTER_ARG_EXP:
-               lval = test_arg(arg, arg->exp.left);
+               lval = test_arg(arg, arg->exp.left, error_str);
                if (lval != FILTER_VAL_NORM)
                        return lval;
-               rval = test_arg(arg, arg->exp.right);
+               rval = test_arg(arg, arg->exp.right, error_str);
                if (rval != FILTER_VAL_NORM)
                        return rval;
                return FILTER_VAL_NORM;
 
        case FILTER_ARG_NUM:
-               lval = test_arg(arg, arg->num.left);
+               lval = test_arg(arg, arg->num.left, error_str);
                if (lval != FILTER_VAL_NORM)
                        return lval;
-               rval = test_arg(arg, arg->num.right);
+               rval = test_arg(arg, arg->num.right, error_str);
                if (rval != FILTER_VAL_NORM)
                        return rval;
                return FILTER_VAL_NORM;
 
        case FILTER_ARG_OP:
                if (arg->op.type != FILTER_OP_NOT) {
-                       lval = test_arg(arg, arg->op.left);
+                       lval = test_arg(arg, arg->op.left, error_str);
                        switch (lval) {
                        case FILTER_VAL_NORM:
                                break;
                        case FILTER_VAL_TRUE:
                                if (arg->op.type == FILTER_OP_OR)
                                        return FILTER_VAL_TRUE;
-                               rval = test_arg(arg, arg->op.right);
+                               rval = test_arg(arg, arg->op.right, error_str);
                                if (rval != FILTER_VAL_NORM)
                                        return rval;
 
-                               reparent_op_arg(parent, arg, arg->op.right);
-                               return FILTER_VAL_NORM;
+                               return reparent_op_arg(parent, arg, arg->op.right,
+                                                      error_str);
 
                        case FILTER_VAL_FALSE:
                                if (arg->op.type == FILTER_OP_AND)
                                        return FILTER_VAL_FALSE;
-                               rval = test_arg(arg, arg->op.right);
+                               rval = test_arg(arg, arg->op.right, error_str);
                                if (rval != FILTER_VAL_NORM)
                                        return rval;
 
-                               reparent_op_arg(parent, arg, arg->op.right);
-                               return FILTER_VAL_NORM;
+                               return reparent_op_arg(parent, arg, arg->op.right,
+                                                      error_str);
+
+                       default:
+                               return lval;
                        }
                }
 
-               rval = test_arg(arg, arg->op.right);
+               rval = test_arg(arg, arg->op.right, error_str);
                switch (rval) {
                case FILTER_VAL_NORM:
+               default:
                        break;
+
                case FILTER_VAL_TRUE:
                        if (arg->op.type == FILTER_OP_OR)
                                return FILTER_VAL_TRUE;
                        if (arg->op.type == FILTER_OP_NOT)
                                return FILTER_VAL_FALSE;
 
-                       reparent_op_arg(parent, arg, arg->op.left);
-                       return FILTER_VAL_NORM;
+                       return reparent_op_arg(parent, arg, arg->op.left,
+                                              error_str);
 
                case FILTER_VAL_FALSE:
                        if (arg->op.type == FILTER_OP_AND)
@@ -852,33 +924,45 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
                        if (arg->op.type == FILTER_OP_NOT)
                                return FILTER_VAL_TRUE;
 
-                       reparent_op_arg(parent, arg, arg->op.left);
-                       return FILTER_VAL_NORM;
+                       return reparent_op_arg(parent, arg, arg->op.left,
+                                              error_str);
                }
 
-               return FILTER_VAL_NORM;
+               return rval;
        default:
-               die("bad arg in filter tree");
+               show_error(error_str, "bad arg in filter tree");
+               return PEVENT_ERRNO__BAD_FILTER_ARG;
        }
        return FILTER_VAL_NORM;
 }
 
 /* Remove any unknown event fields */
-static struct filter_arg *collapse_tree(struct filter_arg *arg)
+static struct filter_arg *collapse_tree(struct filter_arg *arg, char **error_str)
 {
        enum filter_vals ret;
 
-       ret = test_arg(arg, arg);
+       ret = test_arg(arg, arg, error_str);
        switch (ret) {
        case FILTER_VAL_NORM:
-               return arg;
+               break;
 
        case FILTER_VAL_TRUE:
        case FILTER_VAL_FALSE:
                free_arg(arg);
                arg = allocate_arg();
-               arg->type = FILTER_ARG_BOOLEAN;
-               arg->boolean.value = ret == FILTER_VAL_TRUE;
+               if (arg) {
+                       arg->type = FILTER_ARG_BOOLEAN;
+                       arg->boolean.value = ret == FILTER_VAL_TRUE;
+               } else {
+                       show_error(error_str, "Failed to allocate filter arg");
+               }
+               break;
+
+       default:
+               /* test_arg() already set the error_str */
+               free_arg(arg);
+               arg = NULL;
+               break;
        }
 
        return arg;
@@ -1025,6 +1109,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                        switch (op_type) {
                        case OP_BOOL:
                                arg = create_arg_op(btype);
+                               if (arg == NULL)
+                                       goto fail_alloc;
                                if (current_op)
                                        ret = add_left(arg, current_op);
                                else
@@ -1035,6 +1121,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
 
                        case OP_NOT:
                                arg = create_arg_op(btype);
+                               if (arg == NULL)
+                                       goto fail_alloc;
                                if (current_op)
                                        ret = add_right(current_op, arg, error_str);
                                if (ret < 0)
@@ -1054,6 +1142,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                        arg = create_arg_exp(etype);
                                else
                                        arg = create_arg_cmp(ctype);
+                               if (arg == NULL)
+                                       goto fail_alloc;
 
                                if (current_op)
                                        ret = add_right(current_op, arg, error_str);
@@ -1075,6 +1165,8 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                        break;
                case EVENT_NONE:
                        break;
+               case EVENT_ERROR:
+                       goto fail_alloc;
                default:
                        goto fail_print;
                }
@@ -1086,12 +1178,17 @@ process_filter(struct event_format *event, struct filter_arg **parg,
        if (!current_op)
                current_op = current_exp;
 
-       current_op = collapse_tree(current_op);
+       current_op = collapse_tree(current_op, error_str);
+       if (current_op == NULL)
+               goto fail;
 
        *parg = current_op;
 
        return 0;
 
+ fail_alloc:
+       show_error(error_str, "failed to allocate filter arg");
+       goto fail;
  fail_print:
        show_error(error_str, "Syntax error");
  fail:
@@ -1122,6 +1219,10 @@ process_event(struct event_format *event, const char *filter_str,
        /* If parg is NULL, then make it into FALSE */
        if (!*parg) {
                *parg = allocate_arg();
+               if (*parg == NULL) {
+                       show_error(error_str, "failed to allocate filter arg");
+                       return -1;
+               }
                (*parg)->type = FILTER_ARG_BOOLEAN;
                (*parg)->boolean.value = FILTER_FALSE;
        }
@@ -1145,11 +1246,21 @@ static int filter_event(struct event_filter *filter,
        } else {
                /* just add a TRUE arg */
                arg = allocate_arg();
+               if (arg == NULL) {
+                       show_error(error_str, "failed to allocate filter arg");
+                       return -1;
+               }
                arg->type = FILTER_ARG_BOOLEAN;
                arg->boolean.value = FILTER_TRUE;
        }
 
        filter_type = add_filter_type(filter, event->id);
+       if (filter_type == NULL) {
+               show_error(error_str, "failed to add a new filter: %s",
+                          filter_str ? filter_str : "true");
+               return -1;
+       }
+
        if (filter_type->filter)
                free_arg(filter_type->filter);
        filter_type->filter = arg;
@@ -1210,7 +1321,13 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
                else
                        len = strlen(filter_str);
 
-               this_event = malloc_or_die(len + 1);
+               this_event = malloc(len + 1);
+               if (this_event == NULL) {
+                       show_error(error_str, "Memory allocation failure");
+                       /* This can only happen when events is NULL, but still */
+                       free_events(events);
+                       return -1;
+               }
                memcpy(this_event, filter_str, len);
                this_event[len] = 0;
 
@@ -1233,7 +1350,10 @@ int pevent_filter_add_filter_str(struct event_filter *filter,
                /* Find this event */
                ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
                if (ret < 0) {
-                       if (event_name)
+                       if (ret == PEVENT_ERRNO__MEM_ALLOC_FAILED)
+                               show_error(error_str,
+                                          "Memory allocation failure");
+                       else if (event_name)
                                show_error(error_str,
                                           "No event found under '%s.%s'",
                                           sys_name, event_name);
@@ -1374,6 +1494,9 @@ static int copy_filter_type(struct event_filter *filter,
        if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
                /* Add trivial event */
                arg = allocate_arg();
+               if (arg == NULL)
+                       return -1;
+
                arg->type = FILTER_ARG_BOOLEAN;
                if (strcmp(str, "TRUE") == 0)
                        arg->boolean.value = 1;
@@ -1381,6 +1504,9 @@ static int copy_filter_type(struct event_filter *filter,
                        arg->boolean.value = 0;
 
                filter_type = add_filter_type(filter, event->id);
+               if (filter_type == NULL)
+                       return -1;
+
                filter_type->filter = arg;
 
                free(str);
@@ -1482,8 +1608,10 @@ int pevent_update_trivial(struct event_filter *dest, struct event_filter *source
  * @type: remove only true, false, or both
  *
  * Removes filters that only contain a TRUE or FALES boolean arg.
+ *
+ * Returns 0 on success and -1 if there was a problem.
  */
-void pevent_filter_clear_trivial(struct event_filter *filter,
+int pevent_filter_clear_trivial(struct event_filter *filter,
                                 enum filter_trivial_type type)
 {
        struct filter_type *filter_type;
@@ -1492,13 +1620,15 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
        int i;
 
        if (!filter->filters)
-               return;
+               return 0;
 
        /*
         * Two steps, first get all ids with trivial filters.
         *  then remove those ids.
         */
        for (i = 0; i < filter->filters; i++) {
+               int *new_ids;
+
                filter_type = &filter->event_filters[i];
                if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
                        continue;
@@ -1513,19 +1643,24 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
                        break;
                }
 
-               ids = realloc(ids, sizeof(*ids) * (count + 1));
-               if (!ids)
-                       die("Can't allocate ids");
+               new_ids = realloc(ids, sizeof(*ids) * (count + 1));
+               if (!new_ids) {
+                       free(ids);
+                       return -1;
+               }
+
+               ids = new_ids;
                ids[count++] = filter_type->event_id;
        }
 
        if (!count)
-               return;
+               return 0;
 
        for (i = 0; i < count; i++)
                pevent_filter_remove_event(filter, ids[i]);
 
        free(ids);
+       return 0;
 }
 
 /**