Uploaded image for project: 'Harmony'
  1. Harmony
  2. HARMONY-6686

Wrong calculations of java.awt.geom.Area.add(Rectangle) and ArrayIndexOutOfBoundsException: bad arrayCopy

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Open
    • Priority: Critical
    • Resolution: Unresolved
    • Affects Version/s: 6.0M4, 5.0M15, 5.0M16
    • Fix Version/s: None
    • Component/s: Classlib
    • Labels:
      None
    • Environment:
      Ubuntu 11.04 tested;

      Additionally Source java.awt and java.awt.geom extracted from Harmony and compiled with OpenJDK 6, Sun-Java 6 brings the same error
    • Estimated Complexity:
      Unknown

      Description

      Assume, you want to create an area with the size of e.g. 500x500 out of 100x100 tiles.

      You create an Area and randomly add 100x100 tiles until the area is complete. One expected result would be like this (OpenJDK6):

      added java.awt.Rectangle[x=400,y=300,width=100,height=100]
      added java.awt.Rectangle[x=200,y=400,width=100,height=100]
      added java.awt.Rectangle[x=300,y=400,width=100,height=100]
      added java.awt.Rectangle[x=200,y=200,width=100,height=100]
      added java.awt.Rectangle[x=200,y=0,width=100,height=100]
      added java.awt.Rectangle[x=400,y=0,width=100,height=100]
      added java.awt.Rectangle[x=0,y=300,width=100,height=100]
      added java.awt.Rectangle[x=100,y=0,width=100,height=100]
      added java.awt.Rectangle[x=400,y=400,width=100,height=100]
      added java.awt.Rectangle[x=300,y=0,width=100,height=100]
      added java.awt.Rectangle[x=100,y=100,width=100,height=100]
      added java.awt.Rectangle[x=200,y=300,width=100,height=100]
      added java.awt.Rectangle[x=0,y=100,width=100,height=100]
      added java.awt.Rectangle[x=300,y=200,width=100,height=100]
      added java.awt.Rectangle[x=100,y=300,width=100,height=100]
      added java.awt.Rectangle[x=0,y=200,width=100,height=100]
      added java.awt.Rectangle[x=400,y=200,width=100,height=100]
      added java.awt.Rectangle[x=100,y=200,width=100,height=100]
      added java.awt.Rectangle[x=300,y=300,width=100,height=100]
      added java.awt.Rectangle[x=200,y=100,width=100,height=100]
      added java.awt.Rectangle[x=400,y=100,width=100,height=100]
      added java.awt.Rectangle[x=100,y=400,width=100,height=100]
      added java.awt.Rectangle[x=300,y=100,width=100,height=100]
      added java.awt.Rectangle[x=0,y=400,width=100,height=100]
      added java.awt.Rectangle[x=0,y=0,width=100,height=100]

      Output via Path-Iterator:
      move to 0.0, 0.0
      line to 0.0, 100.0
      line to 0.0, 200.0
      line to 0.0, 300.0
      line to 0.0, 400.0
      line to 0.0, 500.0
      line to 500.0, 500.0
      line to 500.0, 400.0
      line to 500.0, 300.0
      line to 500.0, 200.0
      line to 500.0, 100.0
      line to 500.0, 0.0
      close

      This is the output with Apache Harmony JRE:

      added java.awt.Rectangle[x=200,y=100,width=100,height=100]
      added java.awt.Rectangle[x=100,y=300,width=100,height=100]
      added java.awt.Rectangle[x=0,y=200,width=100,height=100]
      added java.awt.Rectangle[x=0,y=300,width=100,height=100]
      Uncaught exception in main:
      java.lang.ArrayIndexOutOfBoundsException: bad arrayCopy
      at java.lang.VMMemoryManager.arrayCopy(VMMemoryManager.java)
      at java.lang.System.arraycopy(System.java:87)
      at java.awt.geom.Area.addPolygon(Area.java:480)
      at java.awt.geom.Area.add(Area.java:253)
      at com.pcbdev.test.Test.main(Test.java:64)

      My sample-Code is randomised and this above is the shortest sequence I found which produces this error.

      Moreover, if the execution doesn't abort with an exception, there are strange miscalculations like this:

      added java.awt.Rectangle[x=400,y=300,width=100,height=100]
      added java.awt.Rectangle[x=400,y=400,width=100,height=100]
      added java.awt.Rectangle[x=300,y=0,width=100,height=100]
      added java.awt.Rectangle[x=300,y=300,width=100,height=100]
      added java.awt.Rectangle[x=400,y=200,width=100,height=100]
      added java.awt.Rectangle[x=100,y=300,width=100,height=100]
      added java.awt.Rectangle[x=100,y=0,width=100,height=100]
      added java.awt.Rectangle[x=0,y=400,width=100,height=100]
      added java.awt.Rectangle[x=200,y=200,width=100,height=100]
      added java.awt.Rectangle[x=300,y=400,width=100,height=100]
      added java.awt.Rectangle[x=300,y=100,width=100,height=100]
      added java.awt.Rectangle[x=100,y=200,width=100,height=100]
      added java.awt.Rectangle[x=400,y=0,width=100,height=100]
      added java.awt.Rectangle[x=200,y=300,width=100,height=100]
      added java.awt.Rectangle[x=300,y=200,width=100,height=100]
      added java.awt.Rectangle[x=0,y=100,width=100,height=100]
      added java.awt.Rectangle[x=400,y=100,width=100,height=100]
      added java.awt.Rectangle[x=100,y=400,width=100,height=100]
      added java.awt.Rectangle[x=200,y=400,width=100,height=100]
      added java.awt.Rectangle[x=0,y=200,width=100,height=100]
      added java.awt.Rectangle[x=200,y=100,width=100,height=100]
      added java.awt.Rectangle[x=100,y=100,width=100,height=100]
      added java.awt.Rectangle[x=0,y=300,width=100,height=100]
      added java.awt.Rectangle[x=0,y=0,width=100,height=100]
      added java.awt.Rectangle[x=200,y=0,width=100,height=100]
      move to 200.0, -0.0
      line to 200.0, 0.0
      line to 200.0, 100.0
      line to 200.0, 100.0
      line to 200.0, 100.0
      line to 200.0, 100.0
      line to 100.0, 100.0
      line to 200.0, 166.66666666666666
      line to 250.0, 200.0
      line to 200.0, 200.0
      line to 200.0, 200.0
      line to 200.0, 166.66666666666669
      line to 200.0, 166.66666666666669
      line to 300.0, 233.33333333333334
      line to 300.0, 233.33333333333334
      line to 300.0, 300.0
      line to 300.0, 300.0
      line to 200.0, 300.0
      line to 200.0, 300.0
      line to 300.0, 400.0
      line to 300.0, 400.0
      line to 300.0, 400.0
      line to 400.0, 400.0
      line to 400.0, 500.0
      line to 300.0, 500.0
      line to 300.0, 500.0
      line to 300.0, 300.0
      line to 300.0, 100.0
      line to 300.0, 100.0
      line to 400.0, 100.0
      line to 400.0, 100.0
      line to 400.0, 100.0
      line to 400.0, 200.0
      line to 400.0, 200.0
      line to 400.0, 200.0
      line to 300.0, 200.0
      line to 300.0, 200.0
      line to 300.0, 200.0
      line to 200.0, 300.0
      line to 200.0, 300.0
      line to 200.0, 400.0
      line to 200.0, 400.0
      line to 200.0, 400.0
      line to 200.0, 400.0
      line to 100.0, 400.0
      line to 100.0, 400.0
      line to 100.0, 400.0
      line to 100.0, 400.0
      line to 100.0, 300.0
      line to 100.0, 300.0
      line to 100.0, 300.0
      line to 100.0, 200.0
      line to 100.0, 200.0
      line to 100.0, 200.0
      line to 100.0, 200.0
      line to 100.0, 200.0
      line to 0.0, 200.0
      line to 0.0, 200.0
      line to 0.0, 100.0
      line to 0.0, 100.0
      line to 100.0, 100.0
      line to 100.0, 100.0
      line to 100.0, 100.0
      line to 100.0, 0.0
      line to 100.0, 0.0
      close

      So, these 233.3333something values are absolutely impossible and also occure when java.awt.geom source is compiled with OpenJDK, so it's not a VM bug, it seems to be a bug in the library.

      I tested with released and unreleased versions of Harmony 5 and 6 and it keeps broken even with the newest release.

      Here is my sample code for testing:

      import java.awt.Rectangle;
      import java.awt.geom.Area;
      import java.awt.geom.PathIterator;
      import java.util.ArrayList;
      import java.util.Random;

      public class Test {

      public static void describeCurrentSegment(PathIterator pi) {
      double[] coordinates = new double[6];
      int type = pi.currentSegment(coordinates);
      switch (type)

      { case PathIterator.SEG_MOVETO: System.out.println("move to " + coordinates[0] + ", " + coordinates[1]); break; case PathIterator.SEG_LINETO: System.out.println("line to " + coordinates[0] + ", " + coordinates[1]); break; case PathIterator.SEG_QUADTO: System.out.println("quadratic to " + coordinates[0] + ", " + coordinates[1] + ", " + coordinates[2] + ", " + coordinates[3]); break; case PathIterator.SEG_CUBICTO: System.out.println("cubic to " + coordinates[0] + ", " + coordinates[1] + ", " + coordinates[2] + ", " + coordinates[3] + ", " + coordinates[4] + ", " + coordinates[5]); break; case PathIterator.SEG_CLOSE: System.out.println("close"); break; default: break; }

      }

      /**

      • @param args
        */
        public static void main(String[] args) {
        final int NUM_X = 5;
        final int NUM_Y = 5;

      Random rnd = new Random();

      ArrayList<Rectangle> list = new ArrayList<Rectangle>();

      Area a = new Area();

      for (int y = 0; y < NUM_Y; y++) {
      for (int x = 0; x < NUM_X; x++)

      { list.add(new Rectangle(x * 100, y * 100, 100, 100)); }

      }

      while (list.size() != 0)

      { int r = Math.abs(rnd.nextInt()) % list.size(); System.out.println("added " + list.get(r).toString()); a.add(new Area(list.get(r))); list.remove(r); }

      PathIterator pi = a.getPathIterator(null);

      while (pi.isDone() == false)

      { describeCurrentSegment(pi); pi.next(); }

      }
      }

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              pcbdev Thomas Pototschnig
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated: