crypto/bn/bn_rsa_fips186_4.c:284: error: BUFFER_OVERRUN_L3
  Offset: [-1, +oo] Size: [1, +oo] by call to `BN_mul`.
Showing all 40 steps of the trace


crypto/bn/bn_rsa_fips186_4.c:253:1: Parameter `ctx->stack.depth`
251.    *     Y, X, r1, r2, e are not NULL.
252.    */
253. > int bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
254.                                     const BIGNUM *r1, const BIGNUM *r2, int nlen,
255.                                     const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb)

crypto/bn/bn_rsa_fips186_4.c:265:5: Call
263.       if (checks == 0)
264.           return 0;
265.       BN_CTX_start(ctx);
           ^
266.   
267.       R = BN_CTX_get(ctx);

crypto/bn/bn_ctx.c:171:1: Parameter `ctx->stack.depth`
  169.   }
  170.   
  171. > void BN_CTX_start(BN_CTX *ctx)
  172.   {
  173.       CTXDBG("ENTER BN_CTX_start()", ctx);

crypto/bn/bn_rsa_fips186_4.c:267:9: Call
265.       BN_CTX_start(ctx);
266.   
267.       R = BN_CTX_get(ctx);
               ^
268.       tmp = BN_CTX_get(ctx);
269.       r1r2x2 = BN_CTX_get(ctx);

crypto/bn/bn_ctx.c:202:1: Parameter `ctx->stack.depth`
  200.   }
  201.   
  202. > BIGNUM *BN_CTX_get(BN_CTX *ctx)
  203.   {
  204.       BIGNUM *ret;

crypto/bn/bn_rsa_fips186_4.c:268:11: Call
266.   
267.       R = BN_CTX_get(ctx);
268.       tmp = BN_CTX_get(ctx);
                 ^
269.       r1r2x2 = BN_CTX_get(ctx);
270.       y1 = BN_CTX_get(ctx);

crypto/bn/bn_ctx.c:202:1: Parameter `ctx->stack.depth`
  200.   }
  201.   
  202. > BIGNUM *BN_CTX_get(BN_CTX *ctx)
  203.   {
  204.       BIGNUM *ret;

crypto/bn/bn_rsa_fips186_4.c:269:14: Call
267.       R = BN_CTX_get(ctx);
268.       tmp = BN_CTX_get(ctx);
269.       r1r2x2 = BN_CTX_get(ctx);
                    ^
270.       y1 = BN_CTX_get(ctx);
271.       r1x2 = BN_CTX_get(ctx);

crypto/bn/bn_ctx.c:202:1: Parameter `ctx->stack.depth`
  200.   }
  201.   
  202. > BIGNUM *BN_CTX_get(BN_CTX *ctx)
  203.   {
  204.       BIGNUM *ret;

crypto/bn/bn_rsa_fips186_4.c:270:10: Call
268.       tmp = BN_CTX_get(ctx);
269.       r1r2x2 = BN_CTX_get(ctx);
270.       y1 = BN_CTX_get(ctx);
                ^
271.       r1x2 = BN_CTX_get(ctx);
272.       if (r1x2 == NULL)

crypto/bn/bn_ctx.c:202:1: Parameter `ctx->stack.depth`
  200.   }
  201.   
  202. > BIGNUM *BN_CTX_get(BN_CTX *ctx)
  203.   {
  204.       BIGNUM *ret;

crypto/bn/bn_rsa_fips186_4.c:271:12: Call
269.       r1r2x2 = BN_CTX_get(ctx);
270.       y1 = BN_CTX_get(ctx);
271.       r1x2 = BN_CTX_get(ctx);
                  ^
272.       if (r1x2 == NULL)
273.           goto err;

crypto/bn/bn_ctx.c:202:1: Parameter `ctx->stack.depth`
  200.   }
  201.   
  202. > BIGNUM *BN_CTX_get(BN_CTX *ctx)
  203.   {
  204.       BIGNUM *ret;

crypto/bn/bn_rsa_fips186_4.c:280:16: Call
278.       if (!(BN_lshift1(r1x2, r1)
279.               /* (Step 1) GCD(2r1, r2) = 1 */
280.               && BN_gcd(tmp, r1x2, r2, ctx)
                      ^
281.               && BN_is_one(tmp)
282.               /* (Step 2) R = ((r2^-1 mod 2r1) * r2) - ((2r1^-1 mod r2)*2r1) */

crypto/bn/bn_gcd.c:15:1: Parameter `ctx->stack.depth`
  13.   static BIGNUM *euclid(BIGNUM *a, BIGNUM *b);
  14.   
  15. > int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
  16.   {
  17.       BIGNUM *a, *b, *t;

crypto/bn/bn_gcd.c:23:5: Call
  21.       bn_check_top(in_b);
  22.   
  23.       BN_CTX_start(ctx);
            ^
  24.       a = BN_CTX_get(ctx);
  25.       b = BN_CTX_get(ctx);

crypto/bn/bn_ctx.c:171:1: Parameter `ctx->stack.depth`
    169.   }
    170.   
    171. > void BN_CTX_start(BN_CTX *ctx)
    172.   {
    173.       CTXDBG("ENTER BN_CTX_start()", ctx);

crypto/bn/bn_gcd.c:24:9: Call
  22.   
  23.       BN_CTX_start(ctx);
  24.       a = BN_CTX_get(ctx);
                ^
  25.       b = BN_CTX_get(ctx);
  26.       if (b == NULL)

crypto/bn/bn_ctx.c:202:1: Parameter `ctx->stack.depth`
    200.   }
    201.   
    202. > BIGNUM *BN_CTX_get(BN_CTX *ctx)
    203.   {
    204.       BIGNUM *ret;

crypto/bn/bn_gcd.c:25:9: Call
  23.       BN_CTX_start(ctx);
  24.       a = BN_CTX_get(ctx);
  25.       b = BN_CTX_get(ctx);
                ^
  26.       if (b == NULL)
  27.           goto err;

crypto/bn/bn_ctx.c:202:1: Parameter `ctx->stack.depth`
    200.   }
    201.   
    202. > BIGNUM *BN_CTX_get(BN_CTX *ctx)
    203.   {
    204.       BIGNUM *ret;

crypto/bn/bn_gcd.c:49:5: Call
  47.       ret = 1;
  48.    err:
  49.       BN_CTX_end(ctx);
            ^
  50.       bn_check_top(r);
  51.       return ret;

crypto/bn/bn_ctx.c:185:1: Parameter `ctx->stack.depth`
    183.   }
    184.   
    185. > void BN_CTX_end(BN_CTX *ctx)
    186.   {
    187.       CTXDBG("ENTER BN_CTX_end()", ctx);

crypto/bn/bn_rsa_fips186_4.c:283:16: Call
281.               && BN_is_one(tmp)
282.               /* (Step 2) R = ((r2^-1 mod 2r1) * r2) - ((2r1^-1 mod r2)*2r1) */
283.               && BN_mod_inverse(R, r2, r1x2, ctx)
                      ^
284.               && BN_mul(R, R, r2, ctx) /* R = (r2^-1 mod 2r1) * r2 */
285.               && BN_mod_inverse(tmp, r1x2, r2, ctx)

crypto/bn/bn_gcd.c:124:1: Parameter `ctx->stack.depth`
  122.                                           BN_CTX *ctx);
  123.   
  124. > BIGNUM *BN_mod_inverse(BIGNUM *in,
  125.                          const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
  126.   {

crypto/bn/bn_gcd.c:129:10: Call
  127.       BIGNUM *rv;
  128.       int noinv;
  129.       rv = int_bn_mod_inverse(in, a, n, ctx, &noinv);
                  ^
  130.       if (noinv)
  131.           BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE);

crypto/bn/bn_gcd.c:135:1: Parameter `ctx->stack.depth`
    133.   }
    134.   
    135. > BIGNUM *int_bn_mod_inverse(BIGNUM *in,
    136.                              const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx,
    137.                              int *pnoinv)

crypto/bn/bn_rsa_fips186_4.c:284:16: Call
282.               /* (Step 2) R = ((r2^-1 mod 2r1) * r2) - ((2r1^-1 mod r2)*2r1) */
283.               && BN_mod_inverse(R, r2, r1x2, ctx)
284.               && BN_mul(R, R, r2, ctx) /* R = (r2^-1 mod 2r1) * r2 */
                      ^
285.               && BN_mod_inverse(tmp, r1x2, r2, ctx)
286.               && BN_mul(tmp, tmp, r1x2, ctx) /* tmp = (2r1^-1 mod r2)*2r1 */

crypto/bn/bn_mul.c:497:1: Parameter `ctx->stack.depth`
  495.   #endif                          /* BN_RECURSION */
  496.   
  497. > int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
  498.   {
  499.       int ret = bn_mul_fixed_top(r, a, b, ctx);

crypto/bn/bn_mul.c:499:15: Call
  497.   int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
  498.   {
  499.       int ret = bn_mul_fixed_top(r, a, b, ctx);
                       ^
  500.   
  501.       bn_correct_top(r);

crypto/bn/bn_mul.c:533:5: Call
    531.       top = al + bl;
    532.   
    533.       BN_CTX_start(ctx);
               ^
    534.       if ((r == a) || (r == b)) {
    535.           if ((rr = BN_CTX_get(ctx)) == NULL)

crypto/bn/bn_ctx.c:171:1: Parameter `*ctx->stack.indexes`
      169.   }
      170.   
      171. > void BN_CTX_start(BN_CTX *ctx)
      172.   {
      173.       CTXDBG("ENTER BN_CTX_start()", ctx);

crypto/bn/bn_mul.c:618:5: Call
    616.    err:
    617.       bn_check_top(r);
    618.       BN_CTX_end(ctx);
               ^
    619.       return ret;
    620.   }

crypto/bn/bn_ctx.c:185:1: Parameter `*ctx->stack.indexes`
      183.   }
      184.   
      185. > void BN_CTX_end(BN_CTX *ctx)
      186.   {
      187.       CTXDBG("ENTER BN_CTX_end()", ctx);

crypto/bn/bn_ctx.c:191:27: Call
      189.           ctx->err_stack--;
      190.       else {
      191.           unsigned int fp = BN_STACK_pop(&ctx->stack);
                                       ^
      192.           /* Does this stack frame have anything to release? */
      193.           if (fp < ctx->used)

crypto/bn/bn_ctx.c:266:1: <Offset trace>
264.   }
265.   
266. > static unsigned int BN_STACK_pop(BN_STACK *st)
267.   {
268.       return st->indexes[--(st->depth)];

crypto/bn/bn_ctx.c:266:1: Parameter `st->depth`
        264.   }
        265.   
        266. > static unsigned int BN_STACK_pop(BN_STACK *st)
        267.   {
        268.       return st->indexes[--(st->depth)];

crypto/bn/bn_ctx.c:266:1: <Length trace>
264.   }
265.   
266. > static unsigned int BN_STACK_pop(BN_STACK *st)
267.   {
268.       return st->indexes[--(st->depth)];

crypto/bn/bn_ctx.c:266:1: Parameter `*st->indexes`
        264.   }
        265.   
        266. > static unsigned int BN_STACK_pop(BN_STACK *st)
        267.   {
        268.       return st->indexes[--(st->depth)];

crypto/bn/bn_ctx.c:268:12: Array access: Offset: [-1, +oo] Size: [1, +oo] by call to `BN_mul` 
        266.   static unsigned int BN_STACK_pop(BN_STACK *st)
        267.   {
        268.       return st->indexes[--(st->depth)];
                          ^
        269.   }
        270.   

static unsigned int BN_STACK_pop(BN_STACK *st)
{
    return st->indexes[--(st->depth)];
}
['int bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,\n                                  const BIGNUM *r1, const BIGNUM *r2, int nlen,\n                                  const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb)\n{\n    int ret = 0;\n    int i, imax;\n    int bits = nlen >> 1;\n    int checks = bn_rsa_fips186_4_prime_MR_min_checks(nlen);\n    BIGNUM *tmp, *R, *r1r2x2, *y1, *r1x2;\n    if (checks == 0)\n        return 0;\n    BN_CTX_start(ctx);\n    R = BN_CTX_get(ctx);\n    tmp = BN_CTX_get(ctx);\n    r1r2x2 = BN_CTX_get(ctx);\n    y1 = BN_CTX_get(ctx);\n    r1x2 = BN_CTX_get(ctx);\n    if (r1x2 == NULL)\n        goto err;\n    if (Xin != NULL && BN_copy(X, Xin) == NULL)\n        goto err;\n    if (!(BN_lshift1(r1x2, r1)\n            && BN_gcd(tmp, r1x2, r2, ctx)\n            && BN_is_one(tmp)\n            && BN_mod_inverse(R, r2, r1x2, ctx)\n            && BN_mul(R, R, r2, ctx)\n            && BN_mod_inverse(tmp, r1x2, r2, ctx)\n            && BN_mul(tmp, tmp, r1x2, ctx)\n            && BN_sub(R, R, tmp)\n            && BN_mul(r1r2x2, r1x2, r2, ctx)))\n        goto err;\n    if (BN_is_negative(R) && !BN_add(R, R, r1r2x2))\n        goto err;\n    imax = 5 * bits;\n    for (;;) {\n        if (Xin == NULL) {\n            if (!BN_priv_rand(X, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY))\n                goto end;\n        }\n        if (!BN_mod_sub(Y, R, X, r1r2x2, ctx) || !BN_add(Y, Y, X))\n            goto err;\n        i = 0;\n        for (;;) {\n            if (BN_num_bits(Y) > bits) {\n                if (Xin == NULL)\n                    break;\n                else\n                    goto err;\n            }\n            BN_GENCB_call(cb, 0, 2);\n            if (BN_copy(y1, Y) == NULL\n                    || !BN_sub_word(y1, 1)\n                    || !BN_gcd(tmp, y1, e, ctx))\n                goto err;\n            if (BN_is_one(tmp)\n                    && BN_is_prime_fasttest_ex(Y, checks, ctx, 1, cb))\n                goto end;\n            if (++i >= imax || !BN_add(Y, Y, r1r2x2))\n                goto err;\n        }\n    }\nend:\n    ret = 1;\n    BN_GENCB_call(cb, 3, 0);\nerr:\n    BN_clear(y1);\n    BN_CTX_end(ctx);\n    return ret;\n}', 'void BN_CTX_start(BN_CTX *ctx)\n{\n    CTXDBG("ENTER BN_CTX_start()", ctx);\n    if (ctx->err_stack || ctx->too_many)\n        ctx->err_stack++;\n    else if (!BN_STACK_push(&ctx->stack, ctx->used)) {\n        BNerr(BN_F_BN_CTX_START, BN_R_TOO_MANY_TEMPORARY_VARIABLES);\n        ctx->err_stack++;\n    }\n    CTXDBG("LEAVE BN_CTX_start()", ctx);\n}', 'BIGNUM *BN_CTX_get(BN_CTX *ctx)\n{\n    BIGNUM *ret;\n    CTXDBG("ENTER BN_CTX_get()", ctx);\n    if (ctx->err_stack || ctx->too_many)\n        return NULL;\n    if ((ret = BN_POOL_get(&ctx->pool, ctx->flags)) == NULL) {\n        ctx->too_many = 1;\n        BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES);\n        return NULL;\n    }\n    BN_zero(ret);\n    ret->flags &= (~BN_FLG_CONSTTIME);\n    ctx->used++;\n    CTXDBG("LEAVE BN_CTX_get()", ctx);\n    return ret;\n}', 'int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)\n{\n    BIGNUM *a, *b, *t;\n    int ret = 0;\n    bn_check_top(in_a);\n    bn_check_top(in_b);\n    BN_CTX_start(ctx);\n    a = BN_CTX_get(ctx);\n    b = BN_CTX_get(ctx);\n    if (b == NULL)\n        goto err;\n    if (BN_copy(a, in_a) == NULL)\n        goto err;\n    if (BN_copy(b, in_b) == NULL)\n        goto err;\n    a->neg = 0;\n    b->neg = 0;\n    if (BN_cmp(a, b) < 0) {\n        t = a;\n        a = b;\n        b = t;\n    }\n    t = euclid(a, b);\n    if (t == NULL)\n        goto err;\n    if (BN_copy(r, t) == NULL)\n        goto err;\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    bn_check_top(r);\n    return ret;\n}', 'void BN_CTX_end(BN_CTX *ctx)\n{\n    CTXDBG("ENTER BN_CTX_end()", ctx);\n    if (ctx->err_stack)\n        ctx->err_stack--;\n    else {\n        unsigned int fp = BN_STACK_pop(&ctx->stack);\n        if (fp < ctx->used)\n            BN_POOL_release(&ctx->pool, ctx->used - fp);\n        ctx->used = fp;\n        ctx->too_many = 0;\n    }\n    CTXDBG("LEAVE BN_CTX_end()", ctx);\n}', 'BIGNUM *BN_mod_inverse(BIGNUM *in,\n                       const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)\n{\n    BIGNUM *rv;\n    int noinv;\n    rv = int_bn_mod_inverse(in, a, n, ctx, &noinv);\n    if (noinv)\n        BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE);\n    return rv;\n}', 'BIGNUM *int_bn_mod_inverse(BIGNUM *in,\n                           const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx,\n                           int *pnoinv)\n{\n    BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;\n    BIGNUM *ret = NULL;\n    int sign;\n    if (BN_abs_is_word(n, 1) || BN_is_zero(n)) {\n        if (pnoinv != NULL)\n            *pnoinv = 1;\n        return NULL;\n    }\n    if (pnoinv != NULL)\n        *pnoinv = 0;\n    if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0)\n        || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) {\n        return BN_mod_inverse_no_branch(in, a, n, ctx);\n    }\n    bn_check_top(a);\n    bn_check_top(n);\n    BN_CTX_start(ctx);\n    A = BN_CTX_get(ctx);\n    B = BN_CTX_get(ctx);\n    X = BN_CTX_get(ctx);\n    D = BN_CTX_get(ctx);\n    M = BN_CTX_get(ctx);\n    Y = BN_CTX_get(ctx);\n    T = BN_CTX_get(ctx);\n    if (T == NULL)\n        goto err;\n    if (in == NULL)\n        R = BN_new();\n    else\n        R = in;\n    if (R == NULL)\n        goto err;\n    BN_one(X);\n    BN_zero(Y);\n    if (BN_copy(B, a) == NULL)\n        goto err;\n    if (BN_copy(A, n) == NULL)\n        goto err;\n    A->neg = 0;\n    if (B->neg || (BN_ucmp(B, A) >= 0)) {\n        if (!BN_nnmod(B, B, A, ctx))\n            goto err;\n    }\n    sign = -1;\n    if (BN_is_odd(n) && (BN_num_bits(n) <= 2048)) {\n        int shift;\n        while (!BN_is_zero(B)) {\n            shift = 0;\n            while (!BN_is_bit_set(B, shift)) {\n                shift++;\n                if (BN_is_odd(X)) {\n                    if (!BN_uadd(X, X, n))\n                        goto err;\n                }\n                if (!BN_rshift1(X, X))\n                    goto err;\n            }\n            if (shift > 0) {\n                if (!BN_rshift(B, B, shift))\n                    goto err;\n            }\n            shift = 0;\n            while (!BN_is_bit_set(A, shift)) {\n                shift++;\n                if (BN_is_odd(Y)) {\n                    if (!BN_uadd(Y, Y, n))\n                        goto err;\n                }\n                if (!BN_rshift1(Y, Y))\n                    goto err;\n            }\n            if (shift > 0) {\n                if (!BN_rshift(A, A, shift))\n                    goto err;\n            }\n            if (BN_ucmp(B, A) >= 0) {\n                if (!BN_uadd(X, X, Y))\n                    goto err;\n                if (!BN_usub(B, B, A))\n                    goto err;\n            } else {\n                if (!BN_uadd(Y, Y, X))\n                    goto err;\n                if (!BN_usub(A, A, B))\n                    goto err;\n            }\n        }\n    } else {\n        while (!BN_is_zero(B)) {\n            BIGNUM *tmp;\n            if (BN_num_bits(A) == BN_num_bits(B)) {\n                if (!BN_one(D))\n                    goto err;\n                if (!BN_sub(M, A, B))\n                    goto err;\n            } else if (BN_num_bits(A) == BN_num_bits(B) + 1) {\n                if (!BN_lshift1(T, B))\n                    goto err;\n                if (BN_ucmp(A, T) < 0) {\n                    if (!BN_one(D))\n                        goto err;\n                    if (!BN_sub(M, A, B))\n                        goto err;\n                } else {\n                    if (!BN_sub(M, A, T))\n                        goto err;\n                    if (!BN_add(D, T, B))\n                        goto err;\n                    if (BN_ucmp(A, D) < 0) {\n                        if (!BN_set_word(D, 2))\n                            goto err;\n                    } else {\n                        if (!BN_set_word(D, 3))\n                            goto err;\n                        if (!BN_sub(M, M, B))\n                            goto err;\n                    }\n                }\n            } else {\n                if (!BN_div(D, M, A, B, ctx))\n                    goto err;\n            }\n            tmp = A;\n            A = B;\n            B = M;\n            if (BN_is_one(D)) {\n                if (!BN_add(tmp, X, Y))\n                    goto err;\n            } else {\n                if (BN_is_word(D, 2)) {\n                    if (!BN_lshift1(tmp, X))\n                        goto err;\n                } else if (BN_is_word(D, 4)) {\n                    if (!BN_lshift(tmp, X, 2))\n                        goto err;\n                } else if (D->top == 1) {\n                    if (!BN_copy(tmp, X))\n                        goto err;\n                    if (!BN_mul_word(tmp, D->d[0]))\n                        goto err;\n                } else {\n                    if (!BN_mul(tmp, D, X, ctx))\n                        goto err;\n                }\n                if (!BN_add(tmp, tmp, Y))\n                    goto err;\n            }\n            M = Y;\n            Y = X;\n            X = tmp;\n            sign = -sign;\n        }\n    }\n    if (sign < 0) {\n        if (!BN_sub(Y, n, Y))\n            goto err;\n    }\n    if (BN_is_one(A)) {\n        if (!Y->neg && BN_ucmp(Y, n) < 0) {\n            if (!BN_copy(R, Y))\n                goto err;\n        } else {\n            if (!BN_nnmod(R, Y, n, ctx))\n                goto err;\n        }\n    } else {\n        if (pnoinv)\n            *pnoinv = 1;\n        goto err;\n    }\n    ret = R;\n err:\n    if ((ret == NULL) && (in == NULL))\n        BN_free(R);\n    BN_CTX_end(ctx);\n    bn_check_top(ret);\n    return ret;\n}', 'int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)\n{\n    int ret = bn_mul_fixed_top(r, a, b, ctx);\n    bn_correct_top(r);\n    bn_check_top(r);\n    return ret;\n}', 'int bn_mul_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)\n{\n    int ret = 0;\n    int top, al, bl;\n    BIGNUM *rr;\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n    int i;\n#endif\n#ifdef BN_RECURSION\n    BIGNUM *t = NULL;\n    int j = 0, k;\n#endif\n    bn_check_top(a);\n    bn_check_top(b);\n    bn_check_top(r);\n    al = a->top;\n    bl = b->top;\n    if ((al == 0) || (bl == 0)) {\n        BN_zero(r);\n        return 1;\n    }\n    top = al + bl;\n    BN_CTX_start(ctx);\n    if ((r == a) || (r == b)) {\n        if ((rr = BN_CTX_get(ctx)) == NULL)\n            goto err;\n    } else\n        rr = r;\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n    i = al - bl;\n#endif\n#ifdef BN_MUL_COMBA\n    if (i == 0) {\n# if 0\n        if (al == 4) {\n            if (bn_wexpand(rr, 8) == NULL)\n                goto err;\n            rr->top = 8;\n            bn_mul_comba4(rr->d, a->d, b->d);\n            goto end;\n        }\n# endif\n        if (al == 8) {\n            if (bn_wexpand(rr, 16) == NULL)\n                goto err;\n            rr->top = 16;\n            bn_mul_comba8(rr->d, a->d, b->d);\n            goto end;\n        }\n    }\n#endif\n#ifdef BN_RECURSION\n    if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {\n        if (i >= -1 && i <= 1) {\n            if (i >= 0) {\n                j = BN_num_bits_word((BN_ULONG)al);\n            }\n            if (i == -1) {\n                j = BN_num_bits_word((BN_ULONG)bl);\n            }\n            j = 1 << (j - 1);\n            assert(j <= al || j <= bl);\n            k = j + j;\n            t = BN_CTX_get(ctx);\n            if (t == NULL)\n                goto err;\n            if (al > j || bl > j) {\n                if (bn_wexpand(t, k * 4) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 4) == NULL)\n                    goto err;\n                bn_mul_part_recursive(rr->d, a->d, b->d,\n                                      j, al - j, bl - j, t->d);\n            } else {\n                if (bn_wexpand(t, k * 2) == NULL)\n                    goto err;\n                if (bn_wexpand(rr, k * 2) == NULL)\n                    goto err;\n                bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d);\n            }\n            rr->top = top;\n            goto end;\n        }\n    }\n#endif\n    if (bn_wexpand(rr, top) == NULL)\n        goto err;\n    rr->top = top;\n    bn_mul_normal(rr->d, a->d, al, b->d, bl);\n#if defined(BN_MUL_COMBA) || defined(BN_RECURSION)\n end:\n#endif\n    rr->neg = a->neg ^ b->neg;\n    rr->flags |= BN_FLG_FIXED_TOP;\n    if (r != rr && BN_copy(r, rr) == NULL)\n        goto err;\n    ret = 1;\n err:\n    bn_check_top(r);\n    BN_CTX_end(ctx);\n    return ret;\n}', 'static unsigned int BN_STACK_pop(BN_STACK *st)\n{\n    return st->indexes[--(st->depth)];\n}']