Signalling Integer Overflows in Java
by Frederic Bapst and Francois Kilchoer

Example 1:

(a)  
int a, b, r;
 ...
r = a + b;
 ...

(b)
int a, b, r;
 ...
r = checkedIADD(a,b);
 ...

(c)
package utils;
public class SecuredArithmetics {
  static int checkedIADD(int a, int b) {
    int r=a+b;
    if (( (a^r) & (b^r) ) < 0)
      System.err.println("Overflow!");
    return r;
  }
}
// (a^r)&(b^r))<0) is a shorthand for:
// (a<0 && b<0 && x>=0) ||
// (a>0 && b>0 && x<=0) )

Example 2: 

(a)
public static double arraySum(double [] t) {
  double sum=0.0;
   for(int i=0; i<t.length; i++)
    sum+=t[i];
   return sum;
}

(b)
public static arraySum(double[]):double
L0 (0) LINENUMBER 11 L0
       DCONST_0
       DSTORE 1: result
L1 (3) LINENUMBER 12 L1
       ICONST_0
       ISTORE 3: i
L2 (6) GOTO L3
L4 (8) LINENUMBER 13 L4
       DLOAD 1: result
       ALOAD 0: t
       ILOAD 3: i
       DALOAD
       DADD
       DSTORE 1: result
L5 (15) LINENUMBER 12 L5
       IINC 3: i 1
L3 (17) ILOAD 3: i
       ALOAD 0: t
       ARRAYLENGTH
       IF_ICMPLT L4
L6 (22) LINENUMBER 14 L6
       DLOAD 1: result
       DRETURN
L7 (25) LOCALVARIABLE t double[] L0 L7 0
       LOCALVARIABLE sum double L1 L7 1
       LOCALVARIABLE i int L2 L6 3
       MAXSTACK = 4
       MAXLOCALS = 4

(c)
MethodVisitor mv;
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, 
  "arraySum", "([D)D", null, null);
mv.visitCode();
  Label l0=new Label(), l1=new Label(), l2=new Label(),...;
mv.visitLabel(l0); mv.visitLineNumber(11, l0);
mv.visitInsn(DCONST_0);
mv.visitVarInsn(DSTORE, 1);
mv.visitLabel(l1); mv.visitLineNumber(12, l1);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 3);
mv.visitJumpInsn(GOTO, l3);
mv.visitLabel(l4); mv.visitLineNumber(13, l4);
mv.visitVarInsn(DLOAD, 1);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 3);
mv.visitInsn(DALOAD);
mv.visitInsn(DADD);
mv.visitVarInsn(DSTORE, 1);
mv.visitLabel(l5); mv.visitLineNumber(12, l5);
mv.visitIincInsn(3, 1);
mv.visitLabel(l3);
mv.visitVarInsn(ILOAD, 3);
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(ARRAYLENGTH);
mv.visitJumpInsn(IF_ICMPLT, l4);
mv.visitLabel(l6); mv.visitLineNumber(14, l6);
mv.visitVarInsn(DLOAD, 1);
mv.visitInsn(DRETURN);
mv.visitLabel(l7);
mv.visitLocalVariable("t", "[D", null, l0, l7, 0);
mv.visitLocalVariable("sum", "D", null, l1, l7, 1);
mv.visitLocalVariable("i", "I", null, l2, l6, 3);
mv.visitMaxs(4, 4);
mv.visitEnd();

Example 3: 

(a)
import org.objectweb.asm.*;
import java.io.*;
public class MyInstrumentation {
  public static void main(String[] args) throws IOException {
    String filename = args[0];
    FileInputStream fis = new FileInputStream(filename);
    ClassReader cr = new ClassReader(fis);
    ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
    ClassAdapter ca = new MyClassAdapter(cw);
    cr.accept(ca, 0);
    byte[] newByteCode = cw.toByteArray();
    fis.close();
    FileOutputStream fos = new FileOutputStream(filename);
    fos.write(newByteCode);
    fos.close();
  }
}
//-----------------------------------------
class MyMethodAdapter extends MethodAdapter implements Opcodes {
  public MyMethodAdapter(MethodVisitor mv) { super(mv); }
   //------------------------------------------------------
   public void visitInsn(int opcode) {
     final String METHOD_NAME= "checkedIADD";
     final String METHOD_LOCATION="utils/SecuredArithmetics";
     final String METHOD_SIGNATURE="(II)I";
     if (opcode == IADD) {
       mv.visitMethodInsn(INVOKESTATIC, METHOD_LOCATION,
               METHOD_NAME, METHOD_SIGNATURE);
     } else {
       mv.visitInsn(opcode);
     }
  }
}
//-----------------------------------------
class MyClassAdapter extends ClassAdapter {
   public MyClassAdapter(ClassVisitor cv) { super(cv); }
   //------------------------------------------------------
   public MethodVisitor visitMethod(int access, String name, 
          String desc, String signature, String[] exceptions) {
     MethodVisitor mv;
     mv = cv.visitMethod(access, name, desc, signature, exceptions);
     if (mv != null) {
       mv = new MyMethodAdapter(mv);
   }
   return mv;
 }
}

(b)
public class Hello {
  public static void main(String[] args) {
   int a=3, b=5, c=Integer.MAX_VALUE;
   System.out.println(a+c);
   System.out.println(a+b);
 }
}

(c)
prompt> javac Hello.java
prompt> java Hello
  -2147483646
  8
prompt> java MyInstrumentation "Hello.class"
prompt> java Hello
  Overflow!
  -2147483646
  8


Example 4: 

import java.util.HashSet;
package logging;
public class BetterLogger {
   private static HashSet<String> allMsgOccurrences = 
                                  new HashSet<String>();
   public static void log(String instructionName) {
     final String cojacCheckPrefix="cojacCheck";
     Exception e= new Exception();
     StackTraceElement[] t= e.getStackTrace();
     int i=1;
     if (t.length>1 && t[1].getMethodName().
                         startsWith(cojacCheckPrefix))
        i=2;
     String where = instructionName+" "+t[i].toString();
     if (allMsgOccurrences.contains(where)) return;
     allMsgOccurrences.add(where);
     System.err.print("COJAC: Overflow: "+where);
  }
}


1


