diff --git a/src/math/bigintops.c b/src/math/bigintops.c index 61a795f566..058a09c10f 100644 --- a/src/math/bigintops.c +++ b/src/math/bigintops.c @@ -119,6 +119,8 @@ static void store_int64_result(MVMThreadContext *tc, MVMP6bigintBody *body, MVMi mp_err err; mp_int *i = MVM_malloc(sizeof(mp_int)); if ((err = mp_init_i64(i, result)) != MP_OKAY) { + mp_clear(i); + MVM_free(i); MVM_exception_throw_adhoc(tc, "Error creating a big integer from a native integer (%"PRIi64"): %s", result, mp_error_to_string(err)); } body->u.bigint = i; @@ -276,9 +278,13 @@ MVMObject * MVM_bigint_##opname(MVMThreadContext *tc, MVMObject *result_type, MV mp_int *ia = ba->u.bigint; \ mp_int *ib = MVM_malloc(sizeof(mp_int)); \ if ((err = mp_init(ib)) != MP_OKAY) { \ + mp_clear(ib); \ + MVM_free(ib); \ MVM_exception_throw_adhoc(tc, "Error initializing a big integer: %s", mp_error_to_string(err)); \ } \ if ((err = mp_##opname(ia, ib)) != MP_OKAY) { \ + mp_clear(ib); \ + MVM_free(ib); \ MVM_exception_throw_adhoc(tc, "Error performing %s with a big integer: %s", #opname, mp_error_to_string(err)); \ } \ store_bigint_result(bb, ib); \ @@ -310,9 +316,13 @@ MVMObject * MVM_bigint_##opname(MVMThreadContext *tc, MVMObject *result_type, MV ib = force_bigint(tc, bb, 1); \ ic = MVM_malloc(sizeof(mp_int)); \ if ((err = mp_init(ic)) != MP_OKAY) { \ + mp_clear(ic); \ + MVM_free(ic); \ MVM_exception_throw_adhoc(tc, "Error initializing a big integer: %s", mp_error_to_string(err)); \ } \ if ((err = mp_##opname(ia, ib, ic)) != MP_OKAY) { \ + mp_clear(ic); \ + MVM_free(ic); \ MVM_exception_throw_adhoc(tc, "Error performing %s with big integers: %s", #opname, mp_error_to_string(err)); \ } \ store_bigint_result(bc, ic); \ @@ -329,9 +339,13 @@ void MVM_bigint_fallback_##opname(MVMThreadContext *tc, MVMP6bigintBody *ba, MVM ib = force_bigint(tc, bb, 1); \ ic = MVM_malloc(sizeof(mp_int)); \ if ((err = mp_init(ic)) != MP_OKAY) { \ + mp_clear(ic); \ + MVM_free(ic); \ MVM_exception_throw_adhoc(tc, "Error initializing a big integer: %s", mp_error_to_string(err)); \ } \ if ((err = mp_##opname(ia, ib, ic)) != MP_OKAY) { \ + mp_clear(ic); \ + MVM_free(ic); \ MVM_exception_throw_adhoc(tc, "Error performing %s with big integers: %s", #opname, mp_error_to_string(err)); \ } \ store_bigint_result(bc, ic); \ @@ -355,9 +369,13 @@ MVMObject * MVM_bigint_##opname(MVMThreadContext *tc, MVMObject *result_type, MV ib = force_bigint(tc, bb, 1); \ ic = MVM_malloc(sizeof(mp_int)); \ if ((err = mp_init(ic)) != MP_OKAY) { \ + mp_clear(ic); \ + MVM_free(ic); \ MVM_exception_throw_adhoc(tc, "Error initializing a big integer: %s", mp_error_to_string(err)); \ } \ if ((err = mp_##opname(ia, ib, ic)) != MP_OKAY) { \ + mp_clear(ic); \ + MVM_free(ic); \ MVM_exception_throw_adhoc(tc, "Error performing %s with big integers: %s", #opname, mp_error_to_string(err)); \ } \ store_bigint_result(bc, ic); \ @@ -394,6 +412,8 @@ MVMObject * MVM_bigint_##opname(MVMThreadContext *tc, MVMObject *result_type, MV mp_int *ib = force_bigint(tc, bb, 1); \ mp_int *ic = MVM_malloc(sizeof(mp_int)); \ if ((err = mp_init(ic)) != MP_OKAY) { \ + mp_clear(ic); \ + MVM_free(ic); \ MVM_exception_throw_adhoc(tc, "Error initializing a big integer: %s", mp_error_to_string(err)); \ } \ two_complement_bitop(tc, ia, ib, ic, mp_##opname); \ @@ -440,9 +460,13 @@ MVMObject *MVM_bigint_gcd(MVMThreadContext *tc, MVMObject *result_type, MVMObjec mp_int *ib = force_bigint(tc, bb, 1); mp_int *ic = MVM_malloc(sizeof(mp_int)); if ((err = mp_init(ic)) != MP_OKAY) { + mp_clear(ic); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } if ((err = mp_gcd(ia, ib, ic)) != MP_OKAY) { + mp_clear(ic); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error getting the GCD of two big integer: %s", mp_error_to_string(err)); } store_bigint_result(bc, ic); @@ -509,10 +533,14 @@ MVMObject * MVM_bigint_mod(MVMThreadContext *tc, MVMObject *result_type, MVMObje mp_err err; if ((err = mp_init(ic)) != MP_OKAY) { + mp_clear(ic); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } if ((err = mp_mod(ia, ib, ic)) != MP_OKAY) { + mp_clear(ic); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error getting the mod of two big integer: %s", mp_error_to_string(err)); } @@ -570,6 +598,8 @@ MVMObject *MVM_bigint_div(MVMThreadContext *tc, MVMObject *result_type, MVMObjec ic = MVM_malloc(sizeof(mp_int)); if ((err = mp_init(ic)) != MP_OKAY) { + mp_clear(ic); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } @@ -578,24 +608,33 @@ MVMObject *MVM_bigint_div(MVMThreadContext *tc, MVMObject *result_type, MVMObjec * zero, like C and libtommath would do. */ if ((cmp_a == MP_LT) ^ (cmp_b == MP_LT)) { if ((err = mp_init_multi(&remainder, &intermediate, NULL)) != MP_OKAY) { + mp_clear_multi(ic, &remainder, &intermediate, NULL); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error creating big integers: %s", mp_error_to_string(err)); } if ((err = mp_div(ia, ib, &intermediate, &remainder)) != MP_OKAY) { - mp_clear_multi(&remainder, &intermediate, NULL); + mp_clear_multi(ic, &remainder, &intermediate, NULL); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error dividing big integers: %s", mp_error_to_string(err)); } if (mp_iszero(&remainder) == 0) { if ((err = mp_sub_d(&intermediate, 1, ic)) != MP_OKAY) { + mp_clear_multi(ic, &remainder, &intermediate, NULL); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error subtracting a digit from a big integer: %s", mp_error_to_string(err)); } } else { if ((err = mp_copy(&intermediate, ic)) != MP_OKAY) { + mp_clear_multi(ic, &remainder, &intermediate, NULL); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error copying a big integer: %s", mp_error_to_string(err)); } } mp_clear_multi(&remainder, &intermediate, NULL); } else { if ((err = mp_div(ia, ib, ic, NULL)) != MP_OKAY) { + mp_clear(ic); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error dividing big integers: %s", mp_error_to_string(err)); } } @@ -661,10 +700,14 @@ MVMObject * MVM_bigint_pow(MVMThreadContext *tc, MVMObject *a, MVMObject *b, mp_int *ic = MVM_malloc(sizeof(mp_int)); MVMP6bigintBody *resbody; if ((err = mp_init(ic)) != MP_OKAY) { + mp_clear(ic); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } MVM_gc_mark_thread_blocked(tc); if ((err = mp_expt_u32(base, exponent_d, ic)) != MP_OKAY) { + mp_clear(ic); + MVM_free(ic); MVM_exception_throw_adhoc(tc, "Error in mp_expt_u32: %s", mp_error_to_string(err)); } MVM_gc_mark_thread_unblocked(tc); @@ -699,6 +742,8 @@ MVMObject *MVM_bigint_shl(MVMThreadContext *tc, MVMObject *result_type, MVMObjec mp_int *ia = force_bigint(tc, ba, 0); mp_int *ib = MVM_malloc(sizeof(mp_int)); if ((err = mp_init(ib)) != MP_OKAY) { + mp_clear(ib); + MVM_free(ib); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } two_complement_shl(tc, ib, ia, n); @@ -743,6 +788,8 @@ MVMObject *MVM_bigint_shr(MVMThreadContext *tc, MVMObject *result_type, MVMObjec mp_int *ia = force_bigint(tc, ba, 0); mp_int *ib = MVM_malloc(sizeof(mp_int)); if ((err = mp_init(ib)) != MP_OKAY) { + mp_clear(ib); + MVM_free(ib); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } two_complement_shl(tc, ib, ia, -n); @@ -776,13 +823,19 @@ MVMObject *MVM_bigint_not(MVMThreadContext *tc, MVMObject *result_type, MVMObjec mp_int *ia = ba->u.bigint; mp_int *ib = MVM_malloc(sizeof(mp_int)); if ((err = mp_init(ib)) != MP_OKAY) { + mp_clear(ib); + MVM_free(ib); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } /* two's complement not: add 1 and negate */ if ((err = mp_add_d(ia, 1, ib)) != MP_OKAY) { + mp_clear(ib); + MVM_free(ib); MVM_exception_throw_adhoc(tc, "Error adding a digit to a big integer: %s", mp_error_to_string(err)); } if ((err = mp_neg(ib, ib)) != MP_OKAY) { + mp_clear(ib); + MVM_free(ib); MVM_exception_throw_adhoc(tc, "Error negating a big integer: %s", mp_error_to_string(err)); } store_bigint_result(bb, ib); @@ -809,6 +862,8 @@ MVMObject *MVM_bigint_expmod(MVMThreadContext *tc, MVMObject *result_type, MVMOb mp_int *ic = force_bigint(tc, bc, 2); mp_int *id = MVM_malloc(sizeof(mp_int)); if ((err = mp_init(id)) != MP_OKAY) { + mp_clear(id); + MVM_free(id); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } @@ -819,6 +874,8 @@ MVMObject *MVM_bigint_expmod(MVMThreadContext *tc, MVMObject *result_type, MVMOb bd = get_bigint_body(tc, result); if ((err = mp_exptmod(ia, ib, ic, id)) != MP_OKAY) { + mp_clear(id); + MVM_free(id); MVM_exception_throw_adhoc(tc, "Error in mp_exptmod: %s", mp_error_to_string(err)); } store_bigint_result(bd, id); @@ -915,6 +972,8 @@ MVMObject * MVM_bigint_from_bigint(MVMThreadContext *tc, MVMObject *result_type, mp_err err; mp_int *i = MVM_malloc(sizeof(mp_int)); if ((err = mp_init_copy(i, a_body->u.bigint)) != MP_OKAY) { + mp_clear(i); + MVM_free(i); MVM_exception_throw_adhoc(tc, "Error creating a big integer from a copy of another: %s", mp_error_to_string(err)); } store_bigint_result(r_body, i); @@ -1039,6 +1098,7 @@ MVMString * MVM_bigint_to_str(MVMThreadContext *tc, MVMObject *a, int base) { MVMString *result; if ((err = mp_init(&i)) != MP_OKAY) { + mp_clear(&i); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } mp_set_i64(&i, body->u.smallint.value); @@ -1083,9 +1143,13 @@ MVMObject *MVM_bigint_from_num(MVMThreadContext *tc, MVMObject *result_type, MVM MVMP6bigintBody *ba = get_bigint_body(tc, result); mp_int *ia = MVM_malloc(sizeof(mp_int)); if ((err = mp_init(ia)) != MP_OKAY) { + mp_clear(ia); + MVM_free(ia); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } if ((err = mp_set_double(ia, n)) != MP_OKAY) { + mp_clear(ia); + MVM_free(ia); MVM_exception_throw_adhoc(tc, "Error storing an MVMnum64 (%f) in a big integer: %s", n, mp_error_to_string(err)); } store_bigint_result(ba, ia); @@ -1197,13 +1261,19 @@ MVMObject * MVM_bigint_rand(MVMThreadContext *tc, MVMObject *type, MVMObject *b) ba = get_bigint_body(tc, result); if ((err = mp_init(rnd)) != MP_OKAY) { + mp_clear(rnd); + MVM_free(rnd); MVM_exception_throw_adhoc(tc, "Error creating a big integer: %s", mp_error_to_string(err)); } if ((err = mp_rand(rnd, max->used + 1)) != MP_OKAY) { + mp_clear(rnd); + MVM_free(rnd); MVM_exception_throw_adhoc(tc, "Error randomizing a big integer: %s", mp_error_to_string(err)); } if ((err = mp_mod(rnd, max, rnd)) != MP_OKAY) { + mp_clear(rnd); + MVM_free(rnd); MVM_exception_throw_adhoc(tc, "Error in mp_mod: %s", mp_error_to_string(err)); } store_bigint_result(ba, rnd); @@ -1292,6 +1362,9 @@ MVMObject * MVM_bigint_radix(MVMThreadContext *tc, MVMint64 radix, MVMString *st base = MVM_malloc(sizeof(mp_int)); if ((err = mp_init_multi(value, base, NULL)) != MP_OKAY) { + mp_clear_multi(&zvalue, &zbase, value, base, NULL); + MVM_free(value); + MVM_free(base); MVM_exception_throw_adhoc(tc, "Error creating big integers: %s", mp_error_to_string(err)); } @@ -1325,20 +1398,35 @@ MVMObject * MVM_bigint_radix(MVMThreadContext *tc, MVMint64 radix, MVMString *st else break; if (ch >= radix) break; if ((err = mp_mul_d(&zvalue, radix, &zvalue)) != MP_OKAY) { + mp_clear_multi(&zvalue, &zbase, value, base, NULL); + MVM_free(value); + MVM_free(base); MVM_exception_throw_adhoc(tc, "Error multiplying a big integer by a digit: %s", mp_error_to_string(err)); } if ((err = mp_add_d(&zvalue, ch, &zvalue)) != MP_OKAY) { + mp_clear_multi(&zvalue, &zbase, value, base, NULL); + MVM_free(value); + MVM_free(base); MVM_exception_throw_adhoc(tc, "Error adding a big integer by a digit: %s", mp_error_to_string(err)); } if ((err = mp_mul_d(&zbase, radix, &zbase)) != MP_OKAY) { + mp_clear_multi(&zvalue, &zbase, value, base, NULL); + MVM_free(value); + MVM_free(base); MVM_exception_throw_adhoc(tc, "Error multiplying a big integer by a digit: %s", mp_error_to_string(err)); } offset++; pos = offset; if (ch != 0 || !(flag & 0x04)) { if ((err = mp_copy(&zvalue, value)) != MP_OKAY) { + mp_clear_multi(&zvalue, &zbase, value, base, NULL); + MVM_free(value); + MVM_free(base); MVM_exception_throw_adhoc(tc, "Error copying a big integer: %s", mp_error_to_string(err)); } if ((err = mp_copy(&zbase, base)) != MP_OKAY) { + mp_clear_multi(&zvalue, &zbase, value, base, NULL); + MVM_free(value); + MVM_free(base); MVM_exception_throw_adhoc(tc, "Error copying a big integer: %s", mp_error_to_string(err)); } } @@ -1354,6 +1442,9 @@ MVMObject * MVM_bigint_radix(MVMThreadContext *tc, MVMint64 radix, MVMString *st if (neg || flag & 0x01) { if ((err = mp_neg(value, value)) != MP_OKAY) { + mp_clear_multi(value, base, NULL); + MVM_free(value); + MVM_free(base); MVM_exception_throw_adhoc(tc, "Error negating a big integer: %s", mp_error_to_string(err)); } }