Changeset: 8c9cde34bbcd for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/8c9cde34bbcd
Modified Files:
        sql/server/rel_select.c
Branch: Jul2021
Log Message:

Do a more defensive overflow detection on the sum of digits and use the right 
size macro


diffs (50 lines):

diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -497,9 +497,10 @@ check_arguments_and_find_largest_any_typ
                if (res && res->digits == 0 && (t = exp_subtype(e)) && 
(!strcmp(res->type->base.name, "char") || !strcmp(res->type->base.name, 
"varchar"))) {
                        unsigned int tdigits = type_digits_to_char_digits(t);
                        if (sf->func->fix_scale == DIGITS_ADD) {
-                               rdigits += tdigits;
-                               if (rdigits >= (unsigned int) INT_MAX)
+                               unsigned int nvalue = rdigits + tdigits;
+                               if (nvalue < rdigits || nvalue >= (unsigned 
int) INT32_MAX)
                                        return sql_error(sql, 02, 
SQLSTATE(42000) "SELECT: output number of digits for %s is too large", 
sf->func->base.name);
+                               rdigits = nvalue;
                        } else if (sf->func->fix_scale == INOUT && n == 
exps->h) {
                                rdigits = tdigits;
                        } else {
@@ -3045,9 +3046,13 @@ rel_binop_(mvc *sql, sql_rel *rel, sql_e
                        exp_sum_scales(f, l, r);
                } else if (f->func->fix_scale == DIGITS_ADD) {
                        sql_subtype *res = f->res->h->data;
-                       res->digits = (t1->digits && t2->digits)?t1->digits + 
t2->digits:0;
-                       if (res->digits >= (unsigned int) INT_MAX)
-                               return sql_error(sql, 02, SQLSTATE(42000) 
"SELECT: output number of digits for %s is too large", fname);
+                       if (t1->digits && t2->digits) {
+                               res->digits = t1->digits + t2->digits;
+                               if (res->digits < t1->digits || res->digits < 
t2->digits || res->digits >= (unsigned int) INT32_MAX)
+                                       return sql_error(sql, 02, 
SQLSTATE(42000) "SELECT: output number of digits for %s is too large", fname);
+                       } else {
+                               res->digits = 0;
+                       }
                }
                if (card == card_relation && l->card > CARD_ATOM) {
                        sql_subfunc *zero_or_one = sql_bind_func(sql, "sys", 
"zero_or_one", exp_subtype(l), NULL, F_AGGR);
@@ -3160,9 +3165,13 @@ rel_binop_(mvc *sql, sql_rel *rel, sql_e
                                                exp_sum_scales(f, l, r);
                                        } else if (f->func->fix_scale == 
DIGITS_ADD) {
                                                sql_subtype *res = 
f->res->h->data;
-                                               res->digits = (t1->digits && 
t2->digits)?t1->digits + t2->digits:0;
-                                               if (res->digits >= (unsigned 
int) INT32_MAX)
-                                                       return sql_error(sql, 
02, SQLSTATE(42000) "SELECT: output number of digits for %s is too large", 
fname);
+                                               if (t1->digits && t2->digits) {
+                                                       res->digits = 
t1->digits + t2->digits;
+                                                       if (res->digits < 
t1->digits || res->digits < t2->digits || res->digits >= (unsigned int) 
INT32_MAX)
+                                                               return 
sql_error(sql, 02, SQLSTATE(42000) "SELECT: output number of digits for %s is 
too large", fname);
+                                               } else {
+                                                       res->digits = 0;
+                                               }
                                        }
                                        return exp_binop(sql->sa, l, r, f);
                                }
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to