Reputation: 29
I am very close to finally creating a CAP file for the JCDK 2.2.2 using command line. I first compile the source file Transfer.java into a class file Transfer.class and then try to generate the CAP file. Everything is fine except that I get the error
error: line 56: smartTransfer.Transfer: unsupported int type of intermediate value, must cast intermediate value to type short or byte.
from the CAP converter tool when trying to build my Java Card applet from the class file. I do not have a clue where this error comes from and as such can not assign the value to a byte or short.
I remember when I had Eclipse Neon installed with JCDK 3.0.5, there was a int error of an unknown location, but the applet still ran. I guess due to the JRE on my system.
Here is my applet code:
package smartTransfer;
import javacard.framework.*;
public class Transfer extends Applet {
final static byte CLASS = (byte) 0x80;
final static byte WRITE_USER_INFO_INS = 0x07;
final static byte WRITEIT_USER_INFO_INS = 0x08;
final static byte READ_USER_INFO_INS = 0x09;
final static byte READIT_USER_INFO_INS = 0x06;
final static byte SIZE_MEMORY = (short) 127;
static byte[] memory;
static byte[] memoryy;
public static void install(byte[] bArray, short bOffset, byte bLength) throws ISOException {
new Transfer().register();
memory = new byte[SIZE_MEMORY];
memoryy = new byte[SIZE_MEMORY];
}
public void process(APDU apdu)
throws ISOException {
if (selectingApplet()) return;
byte[] buffer = apdu.getBuffer();
if (buffer[ISO7816.OFFSET_CLA] !=CLASS) {
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
byte ins = buffer[ISO7816.OFFSET_INS];
switch (ins) {
case READ_USER_INFO_INS:
readUserInfo(apdu);
break;
case READIT_USER_INFO_INS:
readitUserInfo(apdu);
break;
case WRITE_USER_INFO_INS:
writeUserInfo(apdu);
break;
case WRITEIT_USER_INFO_INS:
writeitUserInfo(apdu);
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
private void writeUserInfo(APDU apdu) {
byte[] cmd_apdu = apdu.getBuffer();
if (cmd_apdu[ISO7816.OFFSET_P1] != 0x00)
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
short offset = (short) (cmd_apdu[ISO7816.OFFSET_P2] & 0x00FF);
if (offset >= SIZE_MEMORY)
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
short lc = (short)(cmd_apdu[ISO7816.OFFSET_LC] & 0x00FF);
if ((offset + lc) > SIZE_MEMORY)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
if (lc == 0x00)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
getAPDUBody(apdu);
Util.arrayCopy(cmd_apdu, (short)((ISO7816.OFFSET_CDATA) & 0x00FF),
memory, offset, lc);
ISOException.throwIt(ISO7816.SW_NO_ERROR);
}
public void getAPDUBody(APDU apdu) {
byte[] buffer = apdu.getBuffer();
short lc = (short)(buffer[ISO7816.OFFSET_LC] & 0x00FF);
if (lc != apdu.setIncomingAndReceive())
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
private void readUserInfo(APDU apdu) {
byte[] cmd_apdu = apdu.getBuffer();
if (cmd_apdu[ISO7816.OFFSET_P1] != 0x00) ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
short offset = (short) (cmd_apdu[ISO7816.OFFSET_P2] & 0x00FF);
if (offset >= SIZE_MEMORY) ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
short le = (short)(cmd_apdu[ISO7816.OFFSET_LC] & 0x00FF);
if (le == 0x00) le = (short)(SIZE_MEMORY - offset);
if ((offset + le) > SIZE_MEMORY) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
apdu.setOutgoing();
apdu.setOutgoingLength((short)le);
apdu.sendBytesLong(memory, (short)offset, (short)le);
}
private void writeitUserInfo(APDU apdu) {
byte[] cmd_apdu = apdu.getBuffer();
if (cmd_apdu[ISO7816.OFFSET_P1] != 0)
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
short offset = (short) (cmd_apdu[ISO7816.OFFSET_P2] & 0x00FF);
if (offset >= SIZE_MEMORY)
ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
short lc = (short)(cmd_apdu[ISO7816.OFFSET_LC] & 0x00FF);
if ((offset + lc) > SIZE_MEMORY)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
if (lc == 0x00)
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
getAPDUBody(apdu);
Util.arrayCopy(cmd_apdu, (short)((ISO7816.OFFSET_CDATA) & 0x00FF),
memoryy, offset, lc);
ISOException.throwIt(ISO7816.SW_NO_ERROR);
}
private void readitUserInfo(APDU apdu) {
byte[] cmd_apdu = apdu.getBuffer();
if (cmd_apdu[ISO7816.OFFSET_P1] != 0x00) ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
short offset = (short) (cmd_apdu[ISO7816.OFFSET_P2] & 0x00FF);
if (offset >= SIZE_MEMORY) ISOException.throwIt(ISO7816.SW_WRONG_P1P2);
short le = (short)(cmd_apdu[ISO7816.OFFSET_LC] & 0x00FF);
if (le == 0x00) le = (short)(SIZE_MEMORY - offset);
if ((offset + le) > SIZE_MEMORY) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
apdu.setOutgoing();
apdu.setOutgoingLength((short)le);
apdu.sendBytesLong(memoryy, (short)offset, (short)le);
}
}
I know the error is at line 56, but I guess that would be from the Transfer.class file (which I can't open to read) and not in the source code. But the only unassigned intermediate value that I can think of would be with the instruction case, when reading the incoming APDU header.
Where could this error come from?
Upvotes: 2
Views: 1241
Reputation: 40831
The error already clearly tells you the line in the source file that contains the problematic code. In your case the error is caused by all the lines with the if statement
if ((offset + lc) > SIZE_MEMORY)
The intermediate value of type integer in this case is offset + lc
. Eventhough both operands of the plus operator are shorts, the result of the plus operator is an int. Hence, you need to explicitly cast this value back into a short:
if ((short)(offset + lc) > SIZE_MEMORY)
Also note that the constant SIZE_MEMORY
should probably have been of type short instead of byte:
final static short SIZE_MEMORY = (short) 127;
Upvotes: 3