Program: 171858
Project: 171858
Buggy source:
/** 
 * Performs multiplication of two bignats x and y and stores result into this.  RSA engine is used to speedup operation for large values. Idea of speedup:  We need to mutiply x.y where both x and y are 32B  (x + y)^2 == x^2 + y^2 + 2xy  Fast RSA engine is available (a^b mod n)  n can be set bigger than 64B => a^b mod n == a^b  [(x + y)^2 mod n] - [x^2 mod n] - [y^2 mod n] => 2xy where [] means single RSA operation  2xy / 2 => result of mult(x,y)  Note: if multiplication is used with either x or y argument same repeatedly,  [x^2 mod n] or [y^2 mod n] can be precomputed and passed as arguments x_pow_2 or y_pow_2
 * @param x first value to multiply
 * @param y second value to multiply
 * @param x_pow_2 if not null, array with precomputed value x^2 is expected
 * @param y_pow_2 if not null, array with precomputed value y^2 is expected
 */
public void mult_rsa_trick(Bignat x,Bignat y,byte[] x_pow_2,byte[] y_pow_2){
  short xOffset;
  short yOffset;
  bnh.lock(bnh.fnc_mult_resultArray1);
  Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray1,(short)0,(short)bnh.fnc_mult_resultArray1.length,(byte)0);
  if (x.size > y.size) {
    xOffset=(short)(bnh.fnc_mult_resultArray1.length - x.length());
    Util.arrayCopyNonAtomic(x.value,(short)0,bnh.fnc_mult_resultArray1,xOffset,x.length());
    if (add(bnh.fnc_mult_resultArray1,xOffset,x.size,y.value,(short)0,y.size)) {
      xOffset--;
      bnh.fnc_mult_resultArray1[xOffset]=0x01;
    }
  }
 else {
    yOffset=(short)(bnh.fnc_mult_resultArray1.length - y.length());
    Util.arrayCopyNonAtomic(y.value,(short)0,bnh.fnc_mult_resultArray1,yOffset,y.length());
    if (add(bnh.fnc_mult_resultArray1,yOffset,y.size,x.value,(short)0,x.size)) {
      yOffset--;
      bnh.fnc_mult_resultArray1[yOffset]=0x01;
    }
  }
  bnh.fnc_mult_cipher.doFinal(bnh.fnc_mult_resultArray1,(byte)0,(short)bnh.fnc_mult_resultArray1.length,bnh.fnc_mult_resultArray1,(short)0);
  bnh.lock(bnh.fnc_mult_resultArray2);
  if (x_pow_2 == null) {
    Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length,(byte)0);
    xOffset=(short)(bnh.fnc_mult_resultArray2.length - x.length());
    Util.arrayCopyNonAtomic(x.value,(short)0,bnh.fnc_mult_resultArray2,xOffset,x.length());
    bnh.fnc_mult_cipher.doFinal(bnh.fnc_mult_resultArray2,(byte)0,(short)bnh.fnc_mult_resultArray2.length,bnh.fnc_mult_resultArray2,(short)0);
  }
 else {
    if ((short)x_pow_2.length != (short)bnh.fnc_mult_resultArray2.length) {
      Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length,(byte)0);
      xOffset=(short)((short)bnh.fnc_mult_resultArray2.length - (short)x_pow_2.length);
    }
 else {
      xOffset=0;
    }
    Util.arrayCopyNonAtomic(x_pow_2,(short)0,bnh.fnc_mult_resultArray2,xOffset,(short)x_pow_2.length);
  }
  subtract(bnh.fnc_mult_resultArray1,(short)0,(short)bnh.fnc_mult_resultArray1.length,bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length);
  if (x_pow_2 == null) {
    Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length,(byte)0);
    yOffset=(short)(bnh.fnc_mult_resultArray2.length - y.length());
    Util.arrayCopyNonAtomic(y.value,(short)0,bnh.fnc_mult_resultArray2,yOffset,y.length());
    bnh.fnc_mult_cipher.doFinal(bnh.fnc_mult_resultArray2,(byte)0,(short)bnh.fnc_mult_resultArray2.length,bnh.fnc_mult_resultArray2,(short)0);
  }
 else {
    if ((short)y_pow_2.length != (short)bnh.fnc_mult_resultArray2.length) {
      Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length,(byte)0);
      yOffset=(short)((short)bnh.fnc_mult_resultArray2.length - (short)y_pow_2.length);
    }
 else {
      yOffset=0;
    }
    Util.arrayCopyNonAtomic(y_pow_2,(short)0,bnh.fnc_mult_resultArray2,yOffset,(short)y_pow_2.length);
  }
  subtract(bnh.fnc_mult_resultArray1,(short)0,(short)bnh.fnc_mult_resultArray1.length,bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length);
  short multOffset=(short)((short)bnh.fnc_mult_resultArray1.length - 1);
  short res=0;
  short res2=0;
  short stopOffset=0;
  if (this.length() > multOffset) {
    stopOffset=(short)(this.length() - multOffset);
  }
 else {
    stopOffset=0;
  }
  if (stopOffset > 0) {
    Util.arrayFillNonAtomic(this.value,(short)0,stopOffset,(byte)0);
  }
  for (short i=(short)(this.length() - 1); i >= stopOffset; i--) {
    res=(short)(bnh.fnc_mult_resultArray1[multOffset] & 0xff);
    res=(short)(res >> 1);
    res2=(short)(bnh.fnc_mult_resultArray1[(short)(multOffset - 1)] & 0xff);
    res2=(short)(res2 << 7);
    this.value[i]=(byte)(short)(res | res2);
    multOffset--;
  }
  bnh.unlock(bnh.fnc_mult_resultArray1);
  bnh.unlock(bnh.fnc_mult_resultArray2);
}

Fixed version (ground truth):
/** 
 * Performs multiplication of two bignats x and y and stores result into this.  RSA engine is used to speedup operation for large values. Idea of speedup:  We need to mutiply x.y where both x and y are 32B  (x + y)^2 == x^2 + y^2 + 2xy  Fast RSA engine is available (a^b mod n)  n can be set bigger than 64B => a^b mod n == a^b  [(x + y)^2 mod n] - [x^2 mod n] - [y^2 mod n] => 2xy where [] means single RSA operation  2xy / 2 => result of mult(x,y)  Note: if multiplication is used with either x or y argument same repeatedly,  [x^2 mod n] or [y^2 mod n] can be precomputed and passed as arguments x_pow_2 or y_pow_2
 * @param x first value to multiply
 * @param y second value to multiply
 * @param x_pow_2 if not null, array with precomputed value x^2 is expected
 * @param y_pow_2 if not null, array with precomputed value y^2 is expected
 */
public void mult_rsa_trick(Bignat x,Bignat y,byte[] x_pow_2,byte[] y_pow_2){
  short xOffset;
  short yOffset;
  bnh.lock(bnh.fnc_mult_resultArray1);
  Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray1,(short)0,(short)bnh.fnc_mult_resultArray1.length,(byte)0);
  if (x.size > y.size) {
    xOffset=(short)(bnh.fnc_mult_resultArray1.length - x.length());
    Util.arrayCopyNonAtomic(x.value,(short)0,bnh.fnc_mult_resultArray1,xOffset,x.length());
    if (add(bnh.fnc_mult_resultArray1,xOffset,x.size,y.value,(short)0,y.size)) {
      xOffset--;
      bnh.fnc_mult_resultArray1[xOffset]=0x01;
    }
  }
 else {
    yOffset=(short)(bnh.fnc_mult_resultArray1.length - y.length());
    Util.arrayCopyNonAtomic(y.value,(short)0,bnh.fnc_mult_resultArray1,yOffset,y.length());
    if (add(bnh.fnc_mult_resultArray1,yOffset,y.size,x.value,(short)0,x.size)) {
      yOffset--;
      bnh.fnc_mult_resultArray1[yOffset]=0x01;
    }
  }
  bnh.fnc_mult_cipher.doFinal(bnh.fnc_mult_resultArray1,(byte)0,(short)bnh.fnc_mult_resultArray1.length,bnh.fnc_mult_resultArray1,(short)0);
  bnh.lock(bnh.fnc_mult_resultArray2);
  if (x_pow_2 == null) {
    Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length,(byte)0);
    xOffset=(short)(bnh.fnc_mult_resultArray2.length - x.length());
    Util.arrayCopyNonAtomic(x.value,(short)0,bnh.fnc_mult_resultArray2,xOffset,x.length());
    bnh.fnc_mult_cipher.doFinal(bnh.fnc_mult_resultArray2,(byte)0,(short)bnh.fnc_mult_resultArray2.length,bnh.fnc_mult_resultArray2,(short)0);
  }
 else {
    if ((short)x_pow_2.length != (short)bnh.fnc_mult_resultArray2.length) {
      Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length,(byte)0);
      xOffset=(short)((short)bnh.fnc_mult_resultArray2.length - (short)x_pow_2.length);
    }
 else {
      xOffset=0;
    }
    Util.arrayCopyNonAtomic(x_pow_2,(short)0,bnh.fnc_mult_resultArray2,xOffset,(short)x_pow_2.length);
  }
  subtract(bnh.fnc_mult_resultArray1,(short)0,(short)bnh.fnc_mult_resultArray1.length,bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length);
  if (y_pow_2 == null) {
    Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length,(byte)0);
    yOffset=(short)(bnh.fnc_mult_resultArray2.length - y.length());
    Util.arrayCopyNonAtomic(y.value,(short)0,bnh.fnc_mult_resultArray2,yOffset,y.length());
    bnh.fnc_mult_cipher.doFinal(bnh.fnc_mult_resultArray2,(byte)0,(short)bnh.fnc_mult_resultArray2.length,bnh.fnc_mult_resultArray2,(short)0);
  }
 else {
    if ((short)y_pow_2.length != (short)bnh.fnc_mult_resultArray2.length) {
      Util.arrayFillNonAtomic(bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length,(byte)0);
      yOffset=(short)((short)bnh.fnc_mult_resultArray2.length - (short)y_pow_2.length);
    }
 else {
      yOffset=0;
    }
    Util.arrayCopyNonAtomic(y_pow_2,(short)0,bnh.fnc_mult_resultArray2,yOffset,(short)y_pow_2.length);
  }
  subtract(bnh.fnc_mult_resultArray1,(short)0,(short)bnh.fnc_mult_resultArray1.length,bnh.fnc_mult_resultArray2,(short)0,(short)bnh.fnc_mult_resultArray2.length);
  short multOffset=(short)((short)bnh.fnc_mult_resultArray1.length - 1);
  short res=0;
  short res2=0;
  short stopOffset=0;
  if (this.length() > multOffset) {
    stopOffset=(short)(this.length() - multOffset);
  }
 else {
    stopOffset=0;
  }
  if (stopOffset > 0) {
    Util.arrayFillNonAtomic(this.value,(short)0,stopOffset,(byte)0);
  }
  for (short i=(short)(this.length() - 1); i >= stopOffset; i--) {
    res=(short)(bnh.fnc_mult_resultArray1[multOffset] & 0xff);
    res=(short)(res >> 1);
    res2=(short)(bnh.fnc_mult_resultArray1[(short)(multOffset - 1)] & 0xff);
    res2=(short)(res2 << 7);
    this.value[i]=(byte)(short)(res | res2);
    multOffset--;
  }
  bnh.unlock(bnh.fnc_mult_resultArray1);
  bnh.unlock(bnh.fnc_mult_resultArray2);
}