Uploaded image for project: 'Apache Cassandra'
  1. Apache Cassandra
  2. CASSANDRA-2684

IntergerType uses Thrift method that attempts to unsafely access backing array of ByteBuffer and fails

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Low
    • Resolution: Fixed
    • 0.7.7, 0.8.0
    • None
    • None
    • Low

    Description

      I get the following exception:

      ERROR 13:27:38,153 Fatal exception in thread Thread[ReadStage:36,5,main]
      java.lang.RuntimeException: java.lang.UnsupportedOperationException
      	at org.apache.cassandra.utils.WrappedRunnable.run(WrappedRunnable.java:34)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
      	at java.lang.Thread.run(Thread.java:680)
      Caused by: java.lang.UnsupportedOperationException
      	at java.nio.ByteBuffer.array(ByteBuffer.java:940)
      	at org.apache.thrift.TBaseHelper.byteBufferToByteArray(TBaseHelper.java:264)
      	at org.apache.thrift.TBaseHelper.byteBufferToByteArray(TBaseHelper.java:251)
      	at org.apache.cassandra.db.marshal.IntegerType.getString(IntegerType.java:136)
      	at org.apache.cassandra.db.marshal.AbstractCompositeType.getString(AbstractCompositeType.java:131)
      	at org.apache.cassandra.db.Column.getString(Column.java:228)
      	at org.apache.cassandra.db.filter.SliceQueryFilter.collectReducedColumns(SliceQueryFilter.java:123)
      	at org.apache.cassandra.db.filter.QueryFilter.collectCollatedColumns(QueryFilter.java:130)
      	at org.apache.cassandra.db.ColumnFamilyStore.getTopLevelColumns(ColumnFamilyStore.java:1303)
      	at org.apache.cassandra.db.ColumnFamilyStore.getColumnFamily(ColumnFamilyStore.java:1188)
      	at org.apache.cassandra.db.ColumnFamilyStore.getColumnFamily(ColumnFamilyStore.java:1145)
      	at org.apache.cassandra.db.Table.getRow(Table.java:385)
      	at org.apache.cassandra.db.SliceFromReadCommand.getRow(SliceFromReadCommand.java:61)
      	at org.apache.cassandra.service.StorageProxy$LocalReadRunnable.runMayThrow(StorageProxy.java:641)
      	at org.apache.cassandra.utils.WrappedRunnable.run(WrappedRunnable.java:30)
      	... 3 more
      

      Tracing it down, I find that IntegerType's getString method() looks like this:

      IntegerType.java
          public String getString(ByteBuffer bytes)
          {
              if (bytes == null)
                  return "null";
              if (bytes.remaining() == 0)
                  return "empty";
      
              return new java.math.BigInteger(TBaseHelper.byteBufferToByteArray(bytes)).toString(10);
          }
      

      TBaseHelper.byteBufferToByteArray() looks like this:

      TBaseHelper.java
        public static byte[] byteBufferToByteArray(ByteBuffer byteBuffer) {
          if (wrapsFullArray(byteBuffer)) {
            return byteBuffer.array();
          }
          byte[] target = new byte[byteBuffer.remaining()];
          byteBufferToByteArray(byteBuffer, target, 0);
          return target;
        }
      
        public static boolean wrapsFullArray(ByteBuffer byteBuffer) {
          return byteBuffer.hasArray()
            && byteBuffer.position() == 0
            && byteBuffer.arrayOffset() == 0
            && byteBuffer.remaining() == byteBuffer.capacity();
        }
      
        public static int byteBufferToByteArray(ByteBuffer byteBuffer, byte[] target, int offset) {
          int remaining = byteBuffer.remaining();
          System.arraycopy(byteBuffer.array(),
              byteBuffer.arrayOffset() + byteBuffer.position(),
              target,
              offset,
              remaining);
          return remaining;
        }
      

      The second overloaded implementation of byteBufferToByteArray is calling the bytebuffer's array() method.

      Suggested fixes:

      1) Don't use TBaseHelper in IntegerType.getString(), use ByteBufferUtil.getArray()

      2) Report problem upstream to Thrift.

      3) Find a better way to deserialize BigIntegers that doesn't require an array copy.

      Attachments

        1. 2684.txt
          0.6 kB
          Ed Anuff

        Activity

          People

            edanuff Ed Anuff
            edanuff Ed Anuff
            Ed Anuff
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: