You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by bb...@apache.org on 2022/12/15 17:04:47 UTC

[hbase] 67/91: HubSpot Backport: HBASE-26777 BufferedDataBlockEncoder$OffheapDecodedExtendedCell.deepC… (#4139)

This is an automated email from the ASF dual-hosted git repository.

bbeaudreault pushed a commit to branch hubspot-2
in repository https://gitbox.apache.org/repos/asf/hbase.git

commit 421db7914a431bac0383eab5885f7fa56105f85a
Author: Istvan Toth <st...@stoty.hu>
AuthorDate: Fri Mar 4 22:49:19 2022 +0100

    HubSpot Backport: HBASE-26777 BufferedDataBlockEncoder$OffheapDecodedExtendedCell.deepC… (#4139)
    
    Signed-off-by: Andrew Purtell <ap...@apache.org>
---
 .../java/org/apache/hadoop/hbase/KeyValueUtil.java |  8 +++++++-
 .../apache/hadoop/hbase/regionserver/HRegion.java  |  3 ++-
 .../client/TestCheckAndMutateWithByteBuff.java     | 24 ++++++++++++++++++----
 3 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java
index 8a17ce975dc..bdac750a0dc 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java
@@ -128,7 +128,13 @@ public class KeyValueUtil {
   }
 
   public static byte[] copyToNewByteArray(final Cell cell) {
-    int v1Length = cell.getSerializedSize();
+    //Cell#getSerializedSize returns the serialized size of the Source cell, which may
+    //not serialize all fields. We are constructing a KeyValue backing array here,
+    //which does include all fields, and must allocate accordingly.
+    //TODO we could probably use Cell#getSerializedSize safely, the errors were
+    //caused by cells corrupted by use-after-free bugs
+    int v1Length = length(cell.getRowLength(), cell.getFamilyLength(),
+      cell.getQualifierLength(), cell.getValueLength(), cell.getTagsLength(), true);
     byte[] backingBytes = new byte[v1Length];
     appendToByteArray(cell, backingBytes, 0, true);
     return backingBytes;
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
index d304fa3c8fd..2f767d685f0 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
@@ -93,6 +93,7 @@ import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HConstants.OperationStatusCode;
 import org.apache.hadoop.hbase.HDFSBlocksDistribution;
 import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.KeyValueUtil;
 import org.apache.hadoop.hbase.MetaCellComparator;
 import org.apache.hadoop.hbase.NamespaceDescriptor;
 import org.apache.hadoop.hbase.NotServingRegionException;
@@ -8272,7 +8273,7 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi
       // See more details in HBASE-26036.
       for (Cell cell : tmp) {
         results.add(cell instanceof ByteBufferExtendedCell ?
-          ((ByteBufferExtendedCell) cell).deepClone(): cell);
+            KeyValueUtil.copyToNewKeyValue(cell) : cell);
       }
     }
 
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCheckAndMutateWithByteBuff.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCheckAndMutateWithByteBuff.java
index 876259f4e81..813ff2eeb1d 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCheckAndMutateWithByteBuff.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCheckAndMutateWithByteBuff.java
@@ -31,6 +31,7 @@ import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.io.ByteBuffAllocator;
 import org.apache.hadoop.hbase.io.DeallocateRewriteByteBuffAllocator;
+import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
 import org.apache.hadoop.hbase.io.hfile.BlockCacheFactory;
 import org.apache.hadoop.hbase.regionserver.HRegion;
 import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
@@ -86,8 +87,20 @@ public class TestCheckAndMutateWithByteBuff {
   }
 
   @Test
-  public void testCheckAndMutateWithByteBuff() throws Exception {
-    Table testTable = createTable(TableName.valueOf(name.getMethodName()));
+  public void testCheckAndMutateWithByteBuffNoEncode() throws Exception {
+    testCheckAndMutateWithByteBuff(TableName.valueOf(name.getMethodName()), DataBlockEncoding.NONE);
+  }
+
+  @Test
+  public void testCheckAndMutateWithByteBuffEncode() throws Exception {
+    // Tests for HBASE-26777.
+    // As most HBase.getRegion() calls have been factored out from HBase, you'd need to revert
+    // both HBASE-26777, and the HBase.get() replacements from HBASE-26036 for this test to fail
+    testCheckAndMutateWithByteBuff(TableName.valueOf(name.getMethodName()), DataBlockEncoding.FAST_DIFF);
+  }
+
+  private void testCheckAndMutateWithByteBuff(TableName tableName, DataBlockEncoding dbe) throws Exception {
+    Table testTable = createTable(tableName, dbe);
     byte[] checkRow = Bytes.toBytes("checkRow");
     byte[] checkQualifier = Bytes.toBytes("cq");
     byte[] checkValue = Bytes.toBytes("checkValue");
@@ -103,10 +116,13 @@ public class TestCheckAndMutateWithByteBuff {
         Bytes.toBytes("testValue"))));
   }
 
-  private Table createTable(TableName tableName)
+  private Table createTable(TableName tableName, DataBlockEncoding dbe)
     throws IOException {
     TableDescriptor td = TableDescriptorBuilder.newBuilder(tableName)
-      .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(CF).setBlocksize(100).build())
+      .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(CF)
+        .setBlocksize(100)
+        .setDataBlockEncoding(dbe)
+        .build())
       .build();
     return TEST_UTIL.createTable(td, null);
   }