Index: base/files/file_posix.cc |
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc |
index 43684b5dabfe3df9b2a6907cd5dfbecb8e3582c3..3d229e4155e6e3fea41c7f2725e07be24ebef368 100644 |
--- a/base/files/file_posix.cc |
+++ b/base/files/file_posix.cc |
@@ -483,6 +483,49 @@ File::Error File::OSErrorToFileError(int saved_errno) { |
} |
} |
+File::MemoryCheckingScopedFD::MemoryCheckingScopedFD() { |
+ UpdateChecksum(); |
+} |
+ |
+File::MemoryCheckingScopedFD::MemoryCheckingScopedFD(int fd) : file_(fd) { |
+ UpdateChecksum(); |
+} |
+ |
+File::MemoryCheckingScopedFD::~MemoryCheckingScopedFD() {} |
+ |
+// static |
+void File::MemoryCheckingScopedFD::ComputeMemoryChecksum( |
+ unsigned int* out_checksum) const { |
+ // Use a single iteration of a linear congruentional generator (lcg) to |
+ // provide a cheap checksum unlikely to be accidentally matched by a random |
+ // memory corruption. |
+ |
+ // By choosing constants that satisfy the Hull-Duebell Theorem on lcg cycle |
+ // length, we insure that each distinct fd value maps to a distinct checksum, |
+ // which maximises the utility of our checksum. |
+ |
+ // This code uses "unsigned int" throughout for its defined modular semantics, |
+ // which implicitly gives us a divisor that is a power of two. |
+ |
+ const unsigned int kMultiplier = 13035 * 4 + 1; |
+ COMPILE_ASSERT(((kMultiplier - 1) & 3) == 0, pred_must_be_multiple_of_four); |
+ const unsigned int kIncrement = 1595649551; |
+ COMPILE_ASSERT(kIncrement & 1, must_be_coprime_to_powers_of_two); |
+ |
+ *out_checksum = |
+ static_cast<unsigned int>(file_.get()) * kMultiplier + kIncrement; |
+} |
+ |
+void File::MemoryCheckingScopedFD::Check() const { |
+ unsigned int computed_checksum; |
+ ComputeMemoryChecksum(&computed_checksum); |
+ CHECK_EQ(file_memory_checksum_, computed_checksum) << "corrupted fd memory"; |
+} |
+ |
+void File::MemoryCheckingScopedFD::UpdateChecksum() { |
+ ComputeMemoryChecksum(&file_memory_checksum_); |
+} |
+ |
void File::SetPlatformFile(PlatformFile file) { |
DCHECK(!file_.is_valid()); |
file_.reset(file); |