test/bntest.c:290: error: BUFFER_OVERRUN_L3
  Offset: [1, +oo] Size: [0, 8388607] by call to `BN_div_recp`.
Showing all 16 steps of the trace


test/bntest.c:289:15: Call
287.           BN_set_negative(a, rand_neg());
288.           BN_set_negative(b, rand_neg());
289.           if (!(TEST_true(BN_RECP_CTX_set(recp, b, ctx))
                     ^
290.                   && TEST_true(BN_div_recp(d, c, a, recp, ctx))
291.                   && TEST_true(BN_mul(e, d, b, ctx))

crypto/bn/bn_recp.c:45:1: Parameter `*recp->Nr.d`
  43.   }
  44.   
  45. > int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx)
  46.   {
  47.       if (!BN_copy(&(recp->N), d))

test/bntest.c:290:20: Call
288.           BN_set_negative(b, rand_neg());
289.           if (!(TEST_true(BN_RECP_CTX_set(recp, b, ctx))
290.                   && TEST_true(BN_div_recp(d, c, a, recp, ctx))
                          ^
291.                   && TEST_true(BN_mul(e, d, b, ctx))
292.                   && TEST_true(BN_add(d, e, c))

crypto/bn/bn_recp.c:84:1: Parameter `*recp->Nr.d`
  82.   }
  83.   
  84. > int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
  85.                   BN_RECP_CTX *recp, BN_CTX *ctx)
  86.   {

crypto/bn/bn_recp.c:121:23: Call
  119.       /* Nr := round(2^i / N) */
  120.       if (i != recp->shift)
  121.           recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx);
                               ^
  122.       /* BN_reciprocal could have returned -1 for an error */
  123.       if (recp->shift == -1)

crypto/bn/bn_recp.c:174:1: Parameter `*r->d`
    172.    */
    173.   /* r := 2^len / m */
    174. > int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx)
    175.   {
    176.       int ret = -1;

crypto/bn/bn_recp.c:186:10: Call
    184.           goto err;
    185.   
    186.       if (!BN_div(r, NULL, t, m, ctx))
                    ^
    187.           goto err;
    188.   

crypto/bn/bn_div.c:229:11: Call
      227.       }
      228.   
      229.       ret = bn_div_fixed_top(dv, rm, num, divisor, ctx);
                       ^
      230.   
      231.       if (ret) {

crypto/bn/bn_div.c:264:1: Parameter `dv->top`
        262.    *       divisor's length is considered public;
        263.    */
        264. > int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
        265.                        const BIGNUM *divisor, BN_CTX *ctx)
        266.   {

crypto/bn/bn_div.c:233:13: Call
      231.       if (ret) {
      232.           if (dv != NULL)
      233.               bn_correct_top(dv);
                         ^
      234.           if (rm != NULL)
      235.               bn_correct_top(rm);

crypto/bn/bn_lib.c:965:1: <Offset trace>
963.   }
964.   
965. > void bn_correct_top(BIGNUM *a)
966.   {
967.       BN_ULONG *ftl;

crypto/bn/bn_lib.c:965:1: Parameter `a->top`
        963.   }
        964.   
        965. > void bn_correct_top(BIGNUM *a)
        966.   {
        967.       BN_ULONG *ftl;

crypto/bn/bn_lib.c:968:5: Assignment
        966.   {
        967.       BN_ULONG *ftl;
        968.       int tmp_top = a->top;
                   ^
        969.   
        970.       if (tmp_top > 0) {

crypto/bn/bn_lib.c:965:1: <Length trace>
963.   }
964.   
965. > void bn_correct_top(BIGNUM *a)
966.   {
967.       BN_ULONG *ftl;

crypto/bn/bn_lib.c:965:1: Parameter `*a->d`
        963.   }
        964.   
        965. > void bn_correct_top(BIGNUM *a)
        966.   {
        967.       BN_ULONG *ftl;

crypto/bn/bn_lib.c:971:14: Array access: Offset: [1, +oo] Size: [0, 8388607] by call to `BN_div_recp` 
        969.   
        970.       if (tmp_top > 0) {
        971.           for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) {
                            ^
        972.               ftl--;
        973.               if (*ftl != 0)

void bn_correct_top(BIGNUM *a)
{
    BN_ULONG *ftl;
    int tmp_top = a->top;
    if (tmp_top > 0) {
        for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) {
            ftl--;
            if (*ftl != 0)
                break;
        }
        a->top = tmp_top;
    }
    if (a->top == 0)
        a->neg = 0;
    a->flags &= ~BN_FLG_FIXED_TOP;
    bn_pollute(a);
}
['static int test_div_recip(void)\n{\n    BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;\n    BN_RECP_CTX *recp = NULL;\n    int st = 0, i;\n    if (!TEST_ptr(a = BN_new())\n            || !TEST_ptr(b = BN_new())\n            || !TEST_ptr(c = BN_new())\n            || !TEST_ptr(d = BN_new())\n            || !TEST_ptr(e = BN_new())\n            || !TEST_ptr(recp = BN_RECP_CTX_new()))\n        goto err;\n    for (i = 0; i < NUM0 + NUM1; i++) {\n        if (i < NUM1) {\n            if (!(TEST_true(BN_bntest_rand(a, 400, 0, 0))\n                    && TEST_ptr(BN_copy(b, a))\n                    && TEST_true(BN_lshift(a, a, i))\n                    && TEST_true(BN_add_word(a, i))))\n                goto err;\n        } else {\n            if (!(TEST_true(BN_bntest_rand(b, 50 + 3 * (i - NUM1), 0, 0))))\n                goto err;\n        }\n        BN_set_negative(a, rand_neg());\n        BN_set_negative(b, rand_neg());\n        if (!(TEST_true(BN_RECP_CTX_set(recp, b, ctx))\n                && TEST_true(BN_div_recp(d, c, a, recp, ctx))\n                && TEST_true(BN_mul(e, d, b, ctx))\n                && TEST_true(BN_add(d, e, c))\n                && TEST_true(BN_sub(d, d, a))\n                && TEST_BN_eq_zero(d)))\n            goto err;\n    }\n    st = 1;\n err:\n    BN_free(a);\n    BN_free(b);\n    BN_free(c);\n    BN_free(d);\n    BN_free(e);\n    BN_RECP_CTX_free(recp);\n    return st;\n}', 'int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx)\n{\n    if (!BN_copy(&(recp->N), d))\n        return 0;\n    BN_zero(&(recp->Nr));\n    recp->num_bits = BN_num_bits(d);\n    recp->shift = 0;\n    return 1;\n}', 'int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,\n                BN_RECP_CTX *recp, BN_CTX *ctx)\n{\n    int i, j, ret = 0;\n    BIGNUM *a, *b, *d, *r;\n    BN_CTX_start(ctx);\n    d = (dv != NULL) ? dv : BN_CTX_get(ctx);\n    r = (rem != NULL) ? rem : BN_CTX_get(ctx);\n    a = BN_CTX_get(ctx);\n    b = BN_CTX_get(ctx);\n    if (b == NULL)\n        goto err;\n    if (BN_ucmp(m, &(recp->N)) < 0) {\n        BN_zero(d);\n        if (!BN_copy(r, m)) {\n            BN_CTX_end(ctx);\n            return 0;\n        }\n        BN_CTX_end(ctx);\n        return 1;\n    }\n    i = BN_num_bits(m);\n    j = recp->num_bits << 1;\n    if (j > i)\n        i = j;\n    if (i != recp->shift)\n        recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx);\n    if (recp->shift == -1)\n        goto err;\n    if (!BN_rshift(a, m, recp->num_bits))\n        goto err;\n    if (!BN_mul(b, a, &(recp->Nr), ctx))\n        goto err;\n    if (!BN_rshift(d, b, i - recp->num_bits))\n        goto err;\n    d->neg = 0;\n    if (!BN_mul(b, &(recp->N), d, ctx))\n        goto err;\n    if (!BN_usub(r, m, b))\n        goto err;\n    r->neg = 0;\n    j = 0;\n    while (BN_ucmp(r, &(recp->N)) >= 0) {\n        if (j++ > 2) {\n            BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL);\n            goto err;\n        }\n        if (!BN_usub(r, r, &(recp->N)))\n            goto err;\n        if (!BN_add_word(d, 1))\n            goto err;\n    }\n    r->neg = BN_is_zero(r) ? 0 : m->neg;\n    d->neg = m->neg ^ recp->N.neg;\n    ret = 1;\n err:\n    BN_CTX_end(ctx);\n    bn_check_top(dv);\n    bn_check_top(rem);\n    return ret;\n}', 'int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx)\n{\n    int ret = -1;\n    BIGNUM *t;\n    BN_CTX_start(ctx);\n    if ((t = BN_CTX_get(ctx)) == NULL)\n        goto err;\n    if (!BN_set_bit(t, len))\n        goto err;\n    if (!BN_div(r, NULL, t, m, ctx))\n        goto err;\n    ret = len;\n err:\n    bn_check_top(r);\n    BN_CTX_end(ctx);\n    return ret;\n}', 'int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,\n           BN_CTX *ctx)\n{\n    int ret;\n    if (BN_is_zero(divisor)) {\n        BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO);\n        return 0;\n    }\n    if (divisor->d[divisor->top - 1] == 0) {\n        BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED);\n        return 0;\n    }\n    ret = bn_div_fixed_top(dv, rm, num, divisor, ctx);\n    if (ret) {\n        if (dv != NULL)\n            bn_correct_top(dv);\n        if (rm != NULL)\n            bn_correct_top(rm);\n    }\n    return ret;\n}', 'int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,\n                     const BIGNUM *divisor, BN_CTX *ctx)\n{\n    int norm_shift, i, j, loop;\n    BIGNUM *tmp, *snum, *sdiv, *res;\n    BN_ULONG *resp, *wnum, *wnumtop;\n    BN_ULONG d0, d1;\n    int num_n, div_n;\n    assert(divisor->top > 0 && divisor->d[divisor->top - 1] != 0);\n    bn_check_top(num);\n    bn_check_top(divisor);\n    bn_check_top(dv);\n    bn_check_top(rm);\n    BN_CTX_start(ctx);\n    res = (dv == NULL) ? BN_CTX_get(ctx) : dv;\n    tmp = BN_CTX_get(ctx);\n    snum = BN_CTX_get(ctx);\n    sdiv = BN_CTX_get(ctx);\n    if (sdiv == NULL)\n        goto err;\n    if (!BN_copy(sdiv, divisor))\n        goto err;\n    norm_shift = bn_left_align(sdiv);\n    sdiv->neg = 0;\n    if (!(bn_lshift_fixed_top(snum, num, norm_shift)))\n        goto err;\n    div_n = sdiv->top;\n    num_n = snum->top;\n    if (num_n <= div_n) {\n        if (bn_wexpand(snum, div_n + 1) == NULL)\n            goto err;\n        memset(&(snum->d[num_n]), 0, (div_n - num_n + 1) * sizeof(BN_ULONG));\n        snum->top = num_n = div_n + 1;\n    }\n    loop = num_n - div_n;\n    wnum = &(snum->d[loop]);\n    wnumtop = &(snum->d[num_n - 1]);\n    d0 = sdiv->d[div_n - 1];\n    d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2];\n    if (!bn_wexpand(res, loop))\n        goto err;\n    res->neg = (num->neg ^ divisor->neg);\n    res->top = loop;\n    res->flags |= BN_FLG_FIXED_TOP;\n    resp = &(res->d[loop]);\n    if (!bn_wexpand(tmp, (div_n + 1)))\n        goto err;\n    for (i = 0; i < loop; i++, wnumtop--) {\n        BN_ULONG q, l0;\n# if defined(BN_DIV3W)\n        q = bn_div_3_words(wnumtop, d1, d0);\n# else\n        BN_ULONG n0, n1, rem = 0;\n        n0 = wnumtop[0];\n        n1 = wnumtop[-1];\n        if (n0 == d0)\n            q = BN_MASK2;\n        else {\n            BN_ULONG n2 = (wnumtop == wnum) ? 0 : wnumtop[-2];\n#  ifdef BN_LLONG\n            BN_ULLONG t2;\n#   if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)\n            q = (BN_ULONG)(((((BN_ULLONG) n0) << BN_BITS2) | n1) / d0);\n#   else\n            q = bn_div_words(n0, n1, d0);\n#   endif\n#   ifndef REMAINDER_IS_ALREADY_CALCULATED\n            rem = (n1 - q * d0) & BN_MASK2;\n#   endif\n            t2 = (BN_ULLONG) d1 *q;\n            for (;;) {\n                if (t2 <= ((((BN_ULLONG) rem) << BN_BITS2) | n2))\n                    break;\n                q--;\n                rem += d0;\n                if (rem < d0)\n                    break;\n                t2 -= d1;\n            }\n#  else\n            BN_ULONG t2l, t2h;\n            q = bn_div_words(n0, n1, d0);\n#   ifndef REMAINDER_IS_ALREADY_CALCULATED\n            rem = (n1 - q * d0) & BN_MASK2;\n#   endif\n#   if defined(BN_UMULT_LOHI)\n            BN_UMULT_LOHI(t2l, t2h, d1, q);\n#   elif defined(BN_UMULT_HIGH)\n            t2l = d1 * q;\n            t2h = BN_UMULT_HIGH(d1, q);\n#   else\n            {\n                BN_ULONG ql, qh;\n                t2l = LBITS(d1);\n                t2h = HBITS(d1);\n                ql = LBITS(q);\n                qh = HBITS(q);\n                mul64(t2l, t2h, ql, qh);\n            }\n#   endif\n            for (;;) {\n                if ((t2h < rem) || ((t2h == rem) && (t2l <= n2)))\n                    break;\n                q--;\n                rem += d0;\n                if (rem < d0)\n                    break;\n                if (t2l < d1)\n                    t2h--;\n                t2l -= d1;\n            }\n#  endif\n        }\n# endif\n        l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);\n        tmp->d[div_n] = l0;\n        wnum--;\n        l0 = bn_sub_words(wnum, wnum, tmp->d, div_n + 1);\n        q -= l0;\n        for (l0 = 0 - l0, j = 0; j < div_n; j++)\n            tmp->d[j] = sdiv->d[j] & l0;\n        l0 = bn_add_words(wnum, wnum, tmp->d, div_n);\n        (*wnumtop) += l0;\n        assert((*wnumtop) == 0);\n        *--resp = q;\n    }\n    snum->neg = num->neg;\n    snum->top = div_n;\n    snum->flags |= BN_FLG_FIXED_TOP;\n    if (rm != NULL)\n        bn_rshift_fixed_top(rm, snum, norm_shift);\n    BN_CTX_end(ctx);\n    return 1;\n err:\n    bn_check_top(rm);\n    BN_CTX_end(ctx);\n    return 0;\n}', 'void bn_correct_top(BIGNUM *a)\n{\n    BN_ULONG *ftl;\n    int tmp_top = a->top;\n    if (tmp_top > 0) {\n        for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) {\n            ftl--;\n            if (*ftl != 0)\n                break;\n        }\n        a->top = tmp_top;\n    }\n    if (a->top == 0)\n        a->neg = 0;\n    a->flags &= ~BN_FLG_FIXED_TOP;\n    bn_pollute(a);\n}']