8287101: CDS should check for file truncation for all regions
Reviewed-by: iklam, coleenp
This commit is contained in:
parent
0e06bf3b04
commit
124ba45fb8
src/hotspot/share/cds
test
hotspot/jtreg/runtime/cds/appcds
lib/jdk/test/lib/cds
@ -1370,12 +1370,10 @@ bool FileMapInfo::init_from_file(int fd) {
|
||||
|
||||
_file_offset = header()->header_size(); // accounts for the size of _base_archive_name
|
||||
|
||||
if (is_static()) {
|
||||
// just checking the last region is sufficient since the archive is written
|
||||
// in sequential order
|
||||
size_t len = os::lseek(fd, 0, SEEK_END);
|
||||
FileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
|
||||
// The last space might be empty
|
||||
size_t len = os::lseek(fd, 0, SEEK_END);
|
||||
|
||||
for (int i = 0; i <= MetaspaceShared::last_valid_region; i++) {
|
||||
FileMapRegion* si = space_at(i);
|
||||
if (si->file_offset() > len || len - si->file_offset() < si->used()) {
|
||||
fail_continue("The shared archive file has been truncated.");
|
||||
return false;
|
||||
|
@ -76,7 +76,7 @@ public class SharedArchiveConsistency {
|
||||
return newArchiveName;
|
||||
}
|
||||
|
||||
public static void testAndCheck(String[] execArgs) throws Exception {
|
||||
public static void testAndCheck(String[] execArgs, String... expectedMessages) throws Exception {
|
||||
OutputAnalyzer output = shareAuto ? TestCommon.execAuto(execArgs) : TestCommon.execCommon(execArgs);
|
||||
String stdtxt = output.getOutput();
|
||||
System.out.println("Note: this test may fail in very rare occasions due to CRC32 checksum collision");
|
||||
@ -88,6 +88,9 @@ public class SharedArchiveConsistency {
|
||||
output.shouldNotContain("A fatal error has been detected by the Java Runtime Environment");
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < expectedMessages.length; i++) {
|
||||
output.shouldContain(expectedMessages[i]);
|
||||
}
|
||||
for (String message : matchMessages) {
|
||||
if (stdtxt.contains(message)) {
|
||||
// match any to return
|
||||
@ -236,11 +239,17 @@ public class SharedArchiveConsistency {
|
||||
testAndCheck(verifyExecArgs);
|
||||
|
||||
// delete bytes in data section forward
|
||||
System.out.println("\n6. Delete bytes at beginning of data section, should fail\n");
|
||||
System.out.println("\n6a. Delete bytes at beginning of data section, should fail\n");
|
||||
String deleteBytes = startNewArchive("delete-bytes");
|
||||
CDSArchiveUtils.deleteBytesAtRandomPositionAfterHeader(orgJsaFile, deleteBytes, 4096 /*bytes*/);
|
||||
testAndCheck(verifyExecArgs);
|
||||
|
||||
// delete bytes at the end
|
||||
System.out.println("\n6b. Delete bytes at the end, should fail\n");
|
||||
deleteBytes = startNewArchive("delete-bytes-end");
|
||||
CDSArchiveUtils.deleteBytesAtTheEnd(orgJsaFile, deleteBytes);
|
||||
testAndCheck(verifyExecArgs, "The shared archive file has been truncated.");
|
||||
|
||||
// modify contents in random area
|
||||
System.out.println("\n7. modify Content in random areas, should fail\n");
|
||||
String randomAreas = startNewArchive("random-areas");
|
||||
|
@ -461,6 +461,35 @@ public class CDSArchiveUtils {
|
||||
return dstFile;
|
||||
}
|
||||
|
||||
// returns the size of the last region with used bytes > 0.
|
||||
private static long getLastUsedRegionSize(File jsaFile) throws Exception {
|
||||
int i = num_regions - 1;
|
||||
long regionSize = 0;
|
||||
while (i >= 0) {
|
||||
regionSize = usedRegionSizeAligned(jsaFile, i);
|
||||
if (regionSize > 0) {
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
return regionSize;
|
||||
}
|
||||
|
||||
// delete last regions's used bytes at the end, so new file will be smaller than the original
|
||||
public static File deleteBytesAtTheEnd(File orgFile, String newFileName) throws Exception {
|
||||
long offset = fileHeaderSize(orgFile);
|
||||
long bytesToDelete = getLastUsedRegionSize(orgFile);
|
||||
File dstFile = new File(newFileName);
|
||||
try (FileChannel inputChannel = new FileInputStream(orgFile).getChannel();
|
||||
FileChannel outputChannel = new FileOutputStream(dstFile).getChannel()) {
|
||||
long orgSize = inputChannel.size();
|
||||
transferFrom(inputChannel, outputChannel, 0, offset);
|
||||
inputChannel.position(offset);
|
||||
transferFrom(inputChannel, outputChannel, offset, orgSize - bytesToDelete);
|
||||
}
|
||||
return dstFile;
|
||||
}
|
||||
|
||||
// used region size
|
||||
public static long usedRegionSizeAligned(File archiveFile, int region) throws Exception {
|
||||
long offset = spOffset + cdsFileMapRegionSize * region + spUsedOffset;
|
||||
|
Loading…
x
Reference in New Issue
Block a user