Program: 150232
Project: 150232
Buggy source:
/** 
 * This method supports var args passed from C. In the Linux Intel C convention, the caller places the args immediately above the saved return address, starting with the first arg. <br> For the JNI functions that takes var args, their prolog code will save the var arg in the glue frame because the values in the register may be lost by  subsequent calls. <br> This method copies the var arg values that were saved earlier in glue frame into the spill area of the original caller, thereby doing the work that the callee normally performs in the AIX C convention. <br> NOTE: This method contains internal stack pointer. For now we assume that the stack will not be relocatable while native code is running because native code can hold an address into the stack, so this code is OK, but this is an issue to be resolved later. <br> NOTE:  this method assumes that it is immediately above the  invokeWithDotDotVarArg frame, the JNI frame, the glue frame and  the C caller frame in the respective order.   Therefore, this method will not work if called from anywhere else. <pre> low address |  fp  | <- VM_JNIEnvironment.getVarArgAddress | mid  | |      | |      | |------|    |  fp  | <- VM_JNIEnvironment.invokeWithDotDotVarArg frame | mid  | | ...  | |      | |      | |------|    |  fp  | <- JNI method frame | mid  | | ...  | | arg 0|    args copied by JNI prolog (3 for static, nonvirtual,  | arg 1|    or 4 for virtual) | arg 2| |      | |      | |------| | fp   | <- Native C caller frame |return| | arg 0|     | arg 1|     | arg 2| | arg 3| | arg 4| | arg 5| | arg 6| | arg 7| | arg 8|     | arg 9| |      | |      | |      | high address </pre>
 * @param skip4Args if true, the calling JNI function has 4 args before the varargif false, the calling JNI function has 3 args before the vararg
 * @return the starting address of the vararg in the caller stack frame
 */
private static VM_Address getVarArgAddress(boolean skip4Args){
  VM_Address fp=VM_Magic.getFramePointer();
  fp=VM_Magic.getMemoryAddress(fp);
  fp=VM_Magic.getMemoryAddress(fp);
  return (fp.add(2 * 4 + (skip4Args ? 4 * 4 : 3 * 4)));
}

Fixed version (ground truth):
/** 
 * This method supports var args passed from C. In the Linux Intel C convention, the caller places the args immediately above the saved return address, starting with the first arg. <br> For the JNI functions that takes var args, their prolog code will save the var arg in the glue frame because the values in the register may be lost by  subsequent calls. <br> This method copies the var arg values that were saved earlier in glue frame into the spill area of the original caller, thereby doing the work that the callee normally performs in the AIX C convention. <br> NOTE: This method contains internal stack pointer. For now we assume that the stack will not be relocatable while native code is running because native code can hold an address into the stack, so this code is OK, but this is an issue to be resolved later. <br> NOTE:  this method assumes that it is immediately above the  invokeWithDotDotVarArg frame, the JNI frame, the glue frame and  the C caller frame in the respective order.   Therefore, this method will not work if called from anywhere else. <pre> low address |  fp  | <- VM_JNIEnvironment.getVarArgAddress | mid  | |      | |      | |------|    |  fp  | <- VM_JNIEnvironment.invokeWithDotDotVarArg frame | mid  | | ...  | |      | |      | |------|    |  fp  | <- JNI method frame | mid  | | ...  | | arg 0|    args copied by JNI prolog (3 for static, nonvirtual,  | arg 1|    or 4 for virtual) | arg 2| |      | |      | |------| | fp   | <- Native C caller frame |return| | arg 0|     | arg 1|     | arg 2| | arg 3| | arg 4| | arg 5| | arg 6| | arg 7| | arg 8|     | arg 9| |      | |      | |      | high address </pre>
 * @param skip4Args if true, the calling JNI function has 4 args before the varargif false, the calling JNI function has 3 args before the vararg
 * @return the starting address of the vararg in the caller stack frame
 */
private static VM_Address getVarArgAddress(boolean skip4Args) throws VM_PragmaNoInline {
  VM_Address fp=VM_Magic.getFramePointer();
  fp=VM_Magic.getMemoryAddress(fp);
  fp=VM_Magic.getMemoryAddress(fp);
  return (fp.add(2 * 4 + (skip4Args ? 4 * 4 : 3 * 4)));
}