diff src/share/vm/memory/filemap.cpp @ 20730:8210e5f2e21b

8044269: Analysis of archive files. Summary: Add checksum verification. Reviewed-by: iklam, dholmes, mschoene
author jiangli
date Tue, 12 Aug 2014 17:46:16 -0400
parents 78bbf4d43a14
children 8cb56c8cb30d
line wrap: on
line diff
--- a/src/share/vm/memory/filemap.cpp	Fri Aug 08 15:15:52 2014 -0700
+++ b/src/share/vm/memory/filemap.cpp	Tue Aug 12 17:46:16 2014 -0400
@@ -177,7 +177,14 @@
     fail_continue("The shared archive file has the wrong version.");
     return false;
   }
-  _file_offset = (long)n;
+  size_t len = lseek(fd, 0, SEEK_END);
+  struct FileMapInfo::FileMapHeader::space_info* si =
+    &_header._space[MetaspaceShared::mc];
+  if (si->_file_offset >= len || len - si->_file_offset < si->_used) {
+    fail_continue("The shared archive file has been truncated.");
+    return false;
+  }
+  _file_offset = n;
   return true;
 }
 
@@ -268,6 +275,7 @@
   si->_capacity = capacity;
   si->_read_only = read_only;
   si->_allow_exec = allow_exec;
+  si->_crc = ClassLoader::crc32(0, base, (jint)size);
   write_bytes_aligned(base, (int)size);
 }
 
@@ -292,14 +300,15 @@
 // Align file position to an allocation unit boundary.
 
 void FileMapInfo::align_file_position() {
-  long new_file_offset = align_size_up(_file_offset, os::vm_allocation_granularity());
+  size_t new_file_offset = align_size_up(_file_offset,
+                                         os::vm_allocation_granularity());
   if (new_file_offset != _file_offset) {
     _file_offset = new_file_offset;
     if (_file_open) {
       // Seek one byte back from the target and write a byte to insure
       // that the written file is the correct length.
       _file_offset -= 1;
-      if (lseek(_fd, _file_offset, SEEK_SET) < 0) {
+      if (lseek(_fd, (long)_file_offset, SEEK_SET) < 0) {
         fail_stop("Unable to seek.", NULL);
       }
       char zero = 0;
@@ -406,6 +415,19 @@
   return base;
 }
 
+bool FileMapInfo::verify_region_checksum(int i) {
+  if (!VerifySharedSpaces) {
+    return true;
+  }
+  const char* buf = _header._space[i]._base;
+  size_t sz = _header._space[i]._used;
+  int crc = ClassLoader::crc32(0, buf, (jint)sz);
+  if (crc != _header._space[i]._crc) {
+    fail_continue("Checksum verification failed.");
+    return false;
+  }
+  return true;
+}
 
 // Unmap a memory region in the address space.
 
@@ -457,8 +479,20 @@
   return true;
 }
 
+int FileMapInfo::compute_header_crc() {
+  char* header = (char*)&_header;
+  // start computing from the field after _crc
+  char* buf = (char*)&_header._crc + sizeof(int);
+  size_t sz = sizeof(FileMapInfo::FileMapHeader) - (buf - header);
+  int crc = ClassLoader::crc32(0, buf, (jint)sz);
+  return crc;
+}
 
 bool FileMapInfo::validate() {
+  if (VerifySharedSpaces && compute_header_crc() != _header._crc) {
+    fail_continue("Header checksum verification failed.");
+    return false;
+  }
   if (_header._version != current_version()) {
     fail_continue("The shared archive file is the wrong version.");
     return false;