diff --git a/pre_commit_hooks/end_of_file_fixer.py b/pre_commit_hooks/end_of_file_fixer.py
index 4fe82b7..5ab1b7b 100644
--- a/pre_commit_hooks/end_of_file_fixer.py
+++ b/pre_commit_hooks/end_of_file_fixer.py
@@ -15,13 +15,13 @@ def fix_file(file_obj):
         return 0
     last_character = file_obj.read(1)
     # last_character will be '' for an empty file
-    if last_character != b'\n' and last_character != b'':
+    if last_character not in {b'\n', b'\r'} and last_character != b'':
         # Needs this seek for windows, otherwise IOError
         file_obj.seek(0, os.SEEK_END)
         file_obj.write(b'\n')
         return 1
 
-    while last_character == b'\n':
+    while last_character in {b'\n', b'\r'}:
         # Deal with the beginning of the file
         if file_obj.tell() == 1:
             # If we've reached the beginning of the file and it is all
@@ -35,13 +35,16 @@ def fix_file(file_obj):
         last_character = file_obj.read(1)
 
     # Our current position is at the end of the file just before any amount of
-    # newlines.  If we read two characters and get two newlines back we know
-    # there are extraneous newlines at the ned of the file.  Then backtrack and
-    # trim the end off.
-    if len(file_obj.read(2)) == 2:
-        file_obj.seek(-1, os.SEEK_CUR)
-        file_obj.truncate()
-        return 1
+    # newlines.  If we find extraneous newlines, then backtrack and trim them.
+    position = file_obj.tell()
+    remaining = file_obj.read()
+    for sequence in (b'\n', b'\r\n', b'\r'):
+        if remaining == sequence:
+            return 0
+        elif remaining.startswith(sequence):
+            file_obj.seek(position + len(sequence))
+            file_obj.truncate()
+            return 1
 
     return 0
 

end-of-file-fixer doesn't handle CRLF
When comparing the last two characters for consecutive `\n`, since `\r` doesn't match, it won't fix `\r\n\r\n\r\n` and so on. Noticed this in an old version (0.7.0), but it still applies to the latest (2.0.0) as well.
diff --git a/tests/end_of_file_fixer_test.py b/tests/end_of_file_fixer_test.py
index ae899d2..f8710af 100644
--- a/tests/end_of_file_fixer_test.py
+++ b/tests/end_of_file_fixer_test.py
@@ -15,6 +15,10 @@ TESTS = (
     (b'foo', 1, b'foo\n'),
     (b'foo\n\n\n', 1, b'foo\n'),
     (b'\xe2\x98\x83', 1, b'\xe2\x98\x83\n'),
+    (b'foo\r\n', 0, b'foo\r\n'),
+    (b'foo\r\n\r\n\r\n', 1, b'foo\r\n'),
+    (b'foo\r', 0, b'foo\r'),
+    (b'foo\r\r\r\r', 1, b'foo\r'),
 )
 
 

pip install -e .
parse_log_pytest
requirements.txt
pytest
3.6
requirements-dev.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
cfgv==3.3.1
coverage==6.2
distlib==0.3.9
filelock==3.4.1
flake8==5.0.4
identify==2.4.4
importlib-metadata==4.2.0
importlib-resources==5.2.3
iniconfig==1.1.1
mccabe==0.7.0
mock==5.2.0
nodeenv==1.6.0
packaging==21.3
platformdirs==2.4.0
pluggy==1.0.0
pre-commit==2.17.0
-e git+https://github.com/pre-commit/pre-commit-hooks.git@e01bc2c2a1dc289eca5e41ea73f0942efe6e95ca#egg=pre_commit_hooks
py==1.11.0
pycodestyle==2.9.1
pyflakes==2.5.0
pyparsing==3.1.4
pytest==7.0.1
PyYAML==6.0.1
six==1.17.0
toml==0.10.2
tomli==1.2.3
typing_extensions==4.1.1
virtualenv==20.16.2
zipp==3.6.0

name: pre-commit-hooks
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - cfgv==3.3.1
      - coverage==6.2
      - distlib==0.3.9
      - filelock==3.4.1
      - flake8==5.0.4
      - identify==2.4.4
      - importlib-metadata==4.2.0
      - importlib-resources==5.2.3
      - iniconfig==1.1.1
      - mccabe==0.7.0
      - mock==5.2.0
      - nodeenv==1.6.0
      - packaging==21.3
      - platformdirs==2.4.0
      - pluggy==1.0.0
      - pre-commit==2.17.0
      - py==1.11.0
      - pycodestyle==2.9.1
      - pyflakes==2.5.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - pyyaml==6.0.1
      - six==1.17.0
      - toml==0.10.2
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - virtualenv==20.16.2
      - zipp==3.6.0
prefix: /opt/conda/envs/pre-commit-hooks

tests/end_of_file_fixer_test.py::test_fix_file[foo\r\n\r\n\r\n-1-foo\r\n] tests/end_of_file_fixer_test.py::test_fix_file[foo\r-0-foo\r] tests/end_of_file_fixer_test.py::test_fix_file[foo\r\r\r\r-1-foo\r] tests/end_of_file_fixer_test.py::test_integration[foo\r\n\r\n\r\n-1-foo\r\n] tests/end_of_file_fixer_test.py::test_integration[foo\r-0-foo\r] tests/end_of_file_fixer_test.py::test_integration[foo\r\r\r\r-1-foo\r]
tests/end_of_file_fixer_test.py::test_fix_file[foo\n-0-foo\n] tests/end_of_file_fixer_test.py::test_fix_file[-0-] tests/end_of_file_fixer_test.py::test_fix_file[\n\n-1-] tests/end_of_file_fixer_test.py::test_fix_file[\n\n\n\n-1-] tests/end_of_file_fixer_test.py::test_fix_file[foo-1-foo\n] tests/end_of_file_fixer_test.py::test_fix_file[foo\n\n\n-1-foo\n] tests/end_of_file_fixer_test.py::test_fix_file[\xe2\x98\x83-1-\xe2\x98\x83\n] tests/end_of_file_fixer_test.py::test_fix_file[foo\r\n-0-foo\r\n] tests/end_of_file_fixer_test.py::test_integration[foo\n-0-foo\n] tests/end_of_file_fixer_test.py::test_integration[-0-] tests/end_of_file_fixer_test.py::test_integration[\n\n-1-] tests/end_of_file_fixer_test.py::test_integration[\n\n\n\n-1-] tests/end_of_file_fixer_test.py::test_integration[foo-1-foo\n] tests/end_of_file_fixer_test.py::test_integration[foo\n\n\n-1-foo\n] tests/end_of_file_fixer_test.py::test_integration[\xe2\x98\x83-1-\xe2\x98\x83\n] tests/end_of_file_fixer_test.py::test_integration[foo\r\n-0-foo\r\n]
pre_commit_hooks/end_of_file_fixer.py
pre_commit_hooks/end_of_file_fixer.py