HBASE-25368 Filter out more invalid encoded name in isEncodedRegionName(byte[] regionName) (#2753)

Signed-off-by: stack <stack@apache.com>
This commit is contained in:
huaxiangsun 2020-12-15 21:52:54 -08:00 committed by GitHub
parent 1c217da2ff
commit c327680125
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 42 deletions

View File

@ -2388,51 +2388,56 @@ class RawAsyncHBaseAdmin implements AsyncAdmin {
if (regionNameOrEncodedRegionName == null) {
return failedFuture(new IllegalArgumentException("Passed region name can't be null"));
}
try {
CompletableFuture<Optional<HRegionLocation>> future;
if (RegionInfo.isEncodedRegionName(regionNameOrEncodedRegionName)) {
String encodedName = Bytes.toString(regionNameOrEncodedRegionName);
if (encodedName.length() < RegionInfo.MD5_HEX_LENGTH) {
// old format encodedName, should be meta region
future = connection.registry.getMetaRegionLocations()
.thenApply(locs -> Stream.of(locs.getRegionLocations())
.filter(loc -> loc.getRegion().getEncodedName().equals(encodedName)).findFirst());
} else {
future = ClientMetaTableAccessor.getRegionLocationWithEncodedName(metaTable,
regionNameOrEncodedRegionName);
}
CompletableFuture<Optional<HRegionLocation>> future;
if (RegionInfo.isEncodedRegionName(regionNameOrEncodedRegionName)) {
String encodedName = Bytes.toString(regionNameOrEncodedRegionName);
if (encodedName.length() < RegionInfo.MD5_HEX_LENGTH) {
// old format encodedName, should be meta region
future = connection.registry.getMetaRegionLocations()
.thenApply(locs -> Stream.of(locs.getRegionLocations())
.filter(loc -> loc.getRegion().getEncodedName().equals(encodedName)).findFirst());
} else {
RegionInfo regionInfo =
CatalogFamilyFormat.parseRegionInfoFromRegionName(regionNameOrEncodedRegionName);
if (regionInfo.isMetaRegion()) {
future = connection.registry.getMetaRegionLocations()
.thenApply(locs -> Stream.of(locs.getRegionLocations())
.filter(loc -> loc.getRegion().getReplicaId() == regionInfo.getReplicaId())
.findFirst());
} else {
future =
ClientMetaTableAccessor.getRegionLocation(metaTable, regionNameOrEncodedRegionName);
}
future = ClientMetaTableAccessor.getRegionLocationWithEncodedName(metaTable,
regionNameOrEncodedRegionName);
}
} else {
// Not all regionNameOrEncodedRegionName here is going to be a valid region name,
// it needs to throw out IllegalArgumentException in case tableName is passed in.
RegionInfo regionInfo;
try {
regionInfo = CatalogFamilyFormat.parseRegionInfoFromRegionName(
regionNameOrEncodedRegionName);
} catch (IOException ioe) {
throw new IllegalArgumentException(ioe.getMessage());
}
CompletableFuture<HRegionLocation> returnedFuture = new CompletableFuture<>();
addListener(future, (location, err) -> {
if (err != null) {
returnedFuture.completeExceptionally(err);
return;
}
if (!location.isPresent() || location.get().getRegion() == null) {
returnedFuture.completeExceptionally(
new UnknownRegionException("Invalid region name or encoded region name: " +
Bytes.toStringBinary(regionNameOrEncodedRegionName)));
} else {
returnedFuture.complete(location.get());
}
});
return returnedFuture;
} catch (IOException e) {
return failedFuture(e);
if (regionInfo.isMetaRegion()) {
future = connection.registry.getMetaRegionLocations()
.thenApply(locs -> Stream.of(locs.getRegionLocations())
.filter(loc -> loc.getRegion().getReplicaId() == regionInfo.getReplicaId())
.findFirst());
} else {
future =
ClientMetaTableAccessor.getRegionLocation(metaTable, regionNameOrEncodedRegionName);
}
}
CompletableFuture<HRegionLocation> returnedFuture = new CompletableFuture<>();
addListener(future, (location, err) -> {
if (err != null) {
returnedFuture.completeExceptionally(err);
return;
}
if (!location.isPresent() || location.get().getRegion() == null) {
returnedFuture.completeExceptionally(
new UnknownRegionException("Invalid region name or encoded region name: " +
Bytes.toStringBinary(regionNameOrEncodedRegionName)));
} else {
returnedFuture.complete(location.get());
}
});
return returnedFuture;
}
/**

View File

@ -363,7 +363,23 @@ public interface RegionInfo extends Comparable<RegionInfo> {
@InterfaceAudience.Private // For use by internals only.
public static boolean isEncodedRegionName(byte[] regionName) {
// If not parseable as region name, presume encoded. TODO: add stringency; e.g. if hex.
return parseRegionNameOrReturnNull(regionName) == null && regionName.length <= MD5_HEX_LENGTH;
if (parseRegionNameOrReturnNull(regionName) == null) {
if (regionName.length > MD5_HEX_LENGTH) {
return false;
} else if (regionName.length == MD5_HEX_LENGTH) {
return true;
} else {
String encodedName = Bytes.toString(regionName);
try {
Integer.parseInt(encodedName);
// If this is a valid integer, it could be hbase:meta's encoded region name.
return true;
} catch(NumberFormatException er) {
return false;
}
}
}
return false;
}
/**

View File

@ -99,6 +99,25 @@ public class TestAdmin1 extends TestAdminBase {
assertTrue(exception instanceof TableNotFoundException);
}
@Test
public void testCompactATableWithSuperLongTableName() throws Exception {
TableName tableName = TableName.valueOf(name.getMethodName());
TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName)
.setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build();
try {
ADMIN.createTable(htd);
try {
ADMIN.majorCompactRegion(tableName.getName());
ADMIN.majorCompactRegion(Bytes.toBytes("abcd"));
} catch (IllegalArgumentException iae) {
LOG.info("This is expected");
}
} finally {
ADMIN.disableTable(tableName);
ADMIN.deleteTable(tableName);
}
}
@Test
public void testCompactionTimestamps() throws Exception {
TableName tableName = TableName.valueOf(name.getMethodName());