Catch AttributeError in utils.super_len
diff --git a/HISTORY.md b/HISTORY.md
index ccf4e17400..99d195a798 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -11,6 +11,9 @@ dev
   backwards compatible as it inherits from previously thrown exceptions.
   Can be caught from `requests.exceptions.RequestException` as well.
 
+- Catch `AttributeError` when calculating length of files obtained by
+  `Tarfile.extractfile()`
+
 2.26.0 (2021-07-13)
 -------------------
 
@@ -1702,7 +1705,7 @@ This is not a backwards compatible change.
 -   Automatic Authentication API Change
 -   Smarter Query URL Parameterization
 -   Allow file uploads and POST data together
--   
+-
 
     New Authentication Manager System
 
@@ -1721,7 +1724,7 @@ This is not a backwards compatible change.
 0.2.3 (2011-02-15)
 ------------------
 
--   
+-
 
     New HTTPHandling Methods
 
diff --git a/requests/utils.py b/requests/utils.py
index 41bfb82fe0..6a9f549934 100644
--- a/requests/utils.py
+++ b/requests/utils.py
@@ -124,7 +124,10 @@ def super_len(o):
     elif hasattr(o, 'fileno'):
         try:
             fileno = o.fileno()
-        except io.UnsupportedOperation:
+        except (io.UnsupportedOperation, AttributeError):
+            # AttributeError is a surprising exception, seeing as how we've just checked
+            # that `hasattr(o, 'fileno')`.  It happens for objects obtained via
+            # `Tarfile.extractfile()`, per issue 5229.
             pass
         else:
             total_length = os.fstat(fileno).st_size
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 98ffb25a6c..559dee657f 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -4,6 +4,7 @@
 import copy
 import filecmp
 from io import BytesIO
+import tarfile
 import zipfile
 from collections import deque
 
@@ -86,6 +87,18 @@ def test_file(self, tmpdir, mode, warnings_num, recwarn):
             assert super_len(fd) == 4
         assert len(recwarn) == warnings_num
 
+    def test_tarfile_member(self, tmpdir):
+        file_obj = tmpdir.join('test.txt')
+        file_obj.write('Test')
+
+        tar_obj = str(tmpdir.join('test.tar'))
+        with tarfile.open(tar_obj, 'w') as tar:
+            tar.add(str(file_obj), arcname='test.txt')
+
+        with tarfile.open(tar_obj) as tar:
+            member = tar.extractfile('test.txt')
+            assert super_len(member) == 4
+
     def test_super_len_with__len__(self):
         foo = [1,2,3,4]
         len_foo = super_len(foo)

This allows it to handle files obtained via `Tarfile.extractfile()`.

Fixes #5229.