diff --git a/reviewboard/diffviewer/opcode_generator.py b/reviewboard/diffviewer/opcode_generator.py
index 0cc8b2418e7889832c7794ba3d321b5f2f577f93..bdc1eae84ea79f5a263703a881fcbe4f029a8a48 100644
--- a/reviewboard/diffviewer/opcode_generator.py
+++ b/reviewboard/diffviewer/opcode_generator.py
@@ -292,9 +292,9 @@ class DiffOpcodeGenerator(object):
         r_move_ranges = {}  # key -> (start, end, group)
         prev_key = None
 
-        # Loop through every location from ij1 through ij2 until we've
+        # Loop through every location from ij1 through ij2 - 1 until we've
         # reached the end.
-        while i_move_cur <= ij2:
+        while i_move_cur < ij2:
             try:
                 iline = self.differ.b[i_move_cur].strip()
             except IndexError:
@@ -380,7 +380,7 @@ class DiffOpcodeGenerator(object):
 
             i_move_cur += 1
 
-            if not updated_range:
+            if not updated_range or i_move_cur == ij2:
                 # We've reached the very end of the insert group. See if
                 # we have anything that looks like a move.
                 if r_move_ranges:
diff --git a/reviewboard/diffviewer/tests.py b/reviewboard/diffviewer/tests.py
index d91475ab8a8f27c65a5299f5669f847767a4ef56..ae75f65254b0e1136e27350a6c76ca8209d0209d 100644
--- a/reviewboard/diffviewer/tests.py
+++ b/reviewboard/diffviewer/tests.py
@@ -330,6 +330,34 @@ class DiffParserTest(TestCase):
             ]
         )
 
+    def test_move_detection_with_last_line_in_range(self):
+        """Testing diff viewer move detection with last line in a range"""
+        # The move detection rewrite in 2.0 introduced an off-by-one where
+        # the last line in a chunk wasn't being processed as a move unless
+        # the line after the chunk had content. That line should never have
+        # been processed either.
+        self._test_move_detection(
+            [
+                'this line will be replaced',
+                '',
+                'foo bar blah blah',
+                'this is line 1, and it is sufficiently long',
+                '',
+            ],
+            [
+                'this is line 1, and it is sufficiently long',
+                '',
+                'foo bar blah blah',
+                '',
+            ],
+            [
+                {1: 4},
+            ],
+            [
+                {4: 1},
+            ]
+        )
+
     def test_move_detection_with_adjacent_regions(self):
         """Testing diff viewer move detection with adjacent regions"""
         self._test_move_detection(
