isl_basic_set_opt: avoid invalid access on error path
[platform/upstream/isl.git] / isl_tab_pip.c
index bf5810e..7fb34c7 100644 (file)
@@ -119,6 +119,14 @@ struct isl_context_lex {
        struct isl_tab *tab;
 };
 
+/* A stack (linked list) of solutions of subtrees of the search space.
+ *
+ * "M" describes the solution in terms of the dimensions of "dom".
+ * The number of columns of "M" is one more than the total number
+ * of dimensions of "dom".
+ *
+ * If "M" is NULL, then there is no solution on "dom".
+ */
 struct isl_partial_sol {
        int level;
        struct isl_basic_set *dom;
@@ -307,13 +315,26 @@ static void sol_pop(struct isl_sol *sol)
                        sol_pop_one(sol);
                } else {
                        struct isl_basic_set *bset;
+                       isl_mat *M;
+                       unsigned n;
 
+                       n = isl_basic_set_dim(partial->next->dom, isl_dim_div);
+                       n -= n_div;
                        bset = sol_domain(sol);
-
                        isl_basic_set_free(partial->next->dom);
                        partial->next->dom = bset;
+                       M = partial->next->M;
+                       if (M) {
+                               M = isl_mat_drop_cols(M, M->n_col - n, n);
+                               partial->next->M = M;
+                               if (!M)
+                                       goto error;
+                       }
                        partial->next->level = sol->level;
 
+                       if (!bset)
+                               goto error;
+
                        sol->partial = partial->next;
                        isl_basic_set_free(partial->dom);
                        isl_mat_free(partial->M);
@@ -321,6 +342,9 @@ static void sol_pop(struct isl_sol *sol)
                }
        } else
                sol_pop_one(sol);
+
+       if (0)
+error:         sol->error = 1;
 }
 
 static void sol_dec_level(struct isl_sol *sol)
@@ -2592,6 +2616,14 @@ error:
        return NULL;
 }
 
+/* Representation of the context when using generalized basis reduction.
+ *
+ * "shifted" contains the offsets of the unit hypercubes that lie inside the
+ * context.  Any rational point in "shifted" can therefore be rounded
+ * up to an integer point in the context.
+ * If the context is constrained by any equality, then "shifted" is not used
+ * as it would be empty.
+ */
 struct isl_context_gbr {
        struct isl_context context;
        struct isl_tab *tab;
@@ -2697,6 +2729,8 @@ static struct isl_basic_set *drop_constant_terms(struct isl_basic_set *bset)
 
 static int use_shifted(struct isl_context_gbr *cgbr)
 {
+       if (!cgbr->tab)
+               return 0;
        return cgbr->tab->bmap->n_eq == 0 && cgbr->tab->bmap->n_div == 0;
 }
 
@@ -2815,6 +2849,15 @@ error:
        return NULL;
 }
 
+/* Add the equality described by "eq" to the context.
+ * If "check" is set, then we check if the context is empty after
+ * adding the equality.
+ * If "update" is set, then we check if the samples are still valid.
+ *
+ * We do not explicitly add shifted copies of the equality to
+ * cgbr->shifted since they would conflict with each other.
+ * Instead, we directly mark cgbr->shifted empty.
+ */
 static void context_gbr_add_eq(struct isl_context *context, isl_int *eq,
                int check, int update)
 {
@@ -2822,6 +2865,11 @@ static void context_gbr_add_eq(struct isl_context *context, isl_int *eq,
 
        cgbr->tab = add_gbr_eq(cgbr->tab, eq);
 
+       if (cgbr->shifted && !cgbr->shifted->empty && use_shifted(cgbr)) {
+               if (isl_tab_mark_empty(cgbr->shifted) < 0)
+                       goto error;
+       }
+
        if (cgbr->cone && cgbr->cone->n_col != cgbr->cone->n_dead) {
                if (isl_tab_extend_cons(cgbr->cone, 2) < 0)
                        goto error;
@@ -3095,7 +3143,9 @@ static int context_gbr_detect_equalities(struct isl_context *context,
 
        n_ineq = cgbr->tab->bmap->n_ineq;
        cgbr->tab = isl_tab_detect_equalities(cgbr->tab, cgbr->cone);
-       if (cgbr->tab && cgbr->tab->bmap->n_ineq > n_ineq)
+       if (!cgbr->tab)
+               return -1;
+       if (cgbr->tab->bmap->n_ineq > n_ineq)
                propagate_equalities(cgbr, tab, n_ineq);
 
        return 0;
@@ -3172,6 +3222,9 @@ static void *context_gbr_save(struct isl_context *context)
        struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
        struct isl_gbr_tab_undo *snap;
 
+       if (!cgbr->tab)
+               return NULL;
+
        snap = isl_alloc_type(cgbr->tab->mat->ctx, struct isl_gbr_tab_undo);
        if (!snap)
                return NULL;
@@ -4779,11 +4832,13 @@ int isl_basic_map_foreach_lexopt(__isl_keep isl_basic_map *bmap, int max,
        struct isl_sol_for *sol_for = NULL;
 
        bmap = isl_basic_map_copy(bmap);
+       bmap = isl_basic_map_detect_equalities(bmap);
        if (!bmap)
                return -1;
 
-       bmap = isl_basic_map_detect_equalities(bmap);
        sol_for = sol_for_init(bmap, max, fn, user);
+       if (!sol_for)
+               goto error;
 
        if (isl_basic_map_plain_is_empty(bmap))
                /* nothing */;
@@ -4982,13 +5037,19 @@ __isl_give isl_vec *isl_tab_basic_set_non_trivial_lexmin(
 {
        int i, j;
        int r;
-       isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+       isl_ctx *ctx;
        isl_vec *v = NULL;
-       isl_vec *sol = isl_vec_alloc(ctx, 0);
+       isl_vec *sol = NULL;
        struct isl_tab *tab;
        struct isl_trivial *triv = NULL;
        int level, init;
 
+       if (!bset)
+               return NULL;
+
+       ctx = isl_basic_set_get_ctx(bset);
+       sol = isl_vec_alloc(ctx, 0);
+
        tab = tab_for_lexmin(bset, NULL, 0, 0);
        if (!tab)
                goto error;
@@ -5104,6 +5165,9 @@ __isl_give isl_vec *isl_tab_basic_set_non_neg_lexmin(
        isl_ctx *ctx = isl_basic_set_get_ctx(bset);
        isl_vec *sol;
 
+       if (!bset)
+               return NULL;
+
        tab = tab_for_lexmin(bset, NULL, 0, 0);
        if (!tab)
                goto error;