Jelajahi Sumber

Add two more checks looking for log index out of bounds.

Jing Yang 4 tahun lalu
induk
melakukan
94f08fdc5f
3 mengubah file dengan 39 tambahan dan 0 penghapusan
  1. 7 0
      src/daemon_env.rs
  2. 20 0
      src/process_append_entries.rs
  3. 12 0
      src/sync_log_entries.rs

+ 7 - 0
src/daemon_env.rs

@@ -74,6 +74,13 @@ pub(crate) enum ErrorKind {
     /// opportunistic check that looks for log mismatches, missing committed log
     /// entries or other corruptions.
     DivergedAtCommitted(usize),
+    /// A follower received an AppendEntries RPC with a `prev_log_index` that
+    /// is inconsistent with the index of entries included in the same RPC.
+    AppendEntriesIndexMismatch(usize, Vec<IndexTerm>),
+    /// A follower committed a log entry that is beyond the log end of the
+    /// leader. An opportunistic check that looks for log mismatches, missing
+    /// committed log entries or other corruptions.
+    CommittedBeyondEnd(usize),
 }
 
 impl DaemonEnv {

+ 20 - 0
src/process_append_entries.rs

@@ -1,4 +1,5 @@
 use crate::daemon_env::ErrorKind;
+use crate::index_term::IndexTerm;
 use crate::{
     check_or_record, AppendEntriesArgs, AppendEntriesReply, Raft, State,
 };
@@ -48,6 +49,25 @@ where
                 committed: Some(rf.log.first_after(rf.commit_index).into()),
             };
         }
+        let index_matches = args
+            .entries
+            .iter()
+            .enumerate()
+            .all(|(i, entry)| entry.index == i + args.prev_log_index + 1);
+        if !index_matches {
+            let indexes: Vec<IndexTerm> =
+                args.entries.iter().map(|e| e.into()).collect();
+
+            check_or_record!(
+                index_matches,
+                ErrorKind::AppendEntriesIndexMismatch(
+                    args.prev_log_index,
+                    indexes
+                ),
+                "Entries in AppendEntries request shows index mismatch",
+                &rf
+            );
+        }
 
         // COMMIT_INDEX_INVARIANT: Before this loop, we can safely assume that
         // commit_index < log.end().

+ 12 - 0
src/sync_log_entries.rs

@@ -299,6 +299,18 @@ where
         if committed.index < rf.log.start() {
             return;
         }
+        check_or_record!(
+            committed.index < rf.log.end(),
+            ErrorKind::CommittedBeyondEnd(committed.index),
+            format!(
+                "Follower {:?} committed a log entry {:?} that is
+                beyond the end of the leader log at {:?}",
+                peer,
+                committed,
+                rf.log.end(),
+            ),
+            rf
+        );
         let local_term = rf.log.at(committed.index).term;
         check_or_record!(
             committed.term == local_term,