only catch AttributeError in hasattr() #9666
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index 15f7dd1..814bf66 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -463,10 +463,10 @@
 
 .. function:: hasattr(object, name)
 
-   The arguments are an object and a string.  The result is ``True`` if the string
-   is the name of one of the object's attributes, ``False`` if not. (This is
-   implemented by calling ``getattr(object, name)`` and seeing whether it raises an
-   exception or not.)
+   The arguments are an object and a string.  The result is ``True`` if the
+   string is the name of one of the object's attributes, ``False`` if not. (This
+   is implemented by calling ``getattr(object, name)`` and seeing whether it
+   raises an :exc:`AttributeError` or not.)
 
 
 .. function:: hash(object)
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index aef5de8..4e09ca5 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -495,15 +495,16 @@
         self.assertRaises(TypeError, hasattr)
         self.assertEqual(False, hasattr(sys, chr(sys.maxunicode)))
 
-        # Check that hasattr allows SystemExit and KeyboardInterrupts by
+        # Check that hasattr propagates all exceptions outside of
+        # AttributeError.
         class A:
             def __getattr__(self, what):
-                raise KeyboardInterrupt
-        self.assertRaises(KeyboardInterrupt, hasattr, A(), "b")
+                raise SystemExit
+        self.assertRaises(SystemExit, hasattr, A(), "b")
         class B:
             def __getattr__(self, what):
-                raise SystemExit
-        self.assertRaises(SystemExit, hasattr, B(), "b")
+                raise ValueError
+        self.assertRaises(ValueError, hasattr, B(), "b")
 
     def test_hash(self):
         hash(None)
diff --git a/Misc/ACKS b/Misc/ACKS
index eef51e3..d1fc416 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -730,6 +730,7 @@
 Barry Scott
 Nick Seidenman
 Žiga Seilnach
+Yury Selivanov
 Fred Sells
 Jiwon Seo
 Roger D. Serwy
diff --git a/Misc/NEWS b/Misc/NEWS
index 944df93..5d23464 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@
 Core and Builtins
 -----------------
 
+- Issue #9666: Only catch AttributeError in hasattr(). All other exceptions that
+  occur during attribute lookup are now propagated to the caller.
+
 - Issue #8622: Add PYTHONFSENCODING environment variable to override the
   filesystem encoding.
 
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index e1f2931..3bcb08e 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -893,24 +893,21 @@
     }
     v = PyObject_GetAttr(v, name);
     if (v == NULL) {
-        if (!PyErr_ExceptionMatches(PyExc_Exception))
-            return NULL;
-        else {
+        if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
             PyErr_Clear();
-            Py_INCREF(Py_False);
-            return Py_False;
+            Py_RETURN_FALSE;
         }
+        return NULL;
     }
     Py_DECREF(v);
-    Py_INCREF(Py_True);
-    return Py_True;
+    Py_RETURN_TRUE;
 }
 
 PyDoc_STRVAR(hasattr_doc,
 "hasattr(object, name) -> bool\n\
 \n\
 Return whether the object has an attribute with the given name.\n\
-(This is done by calling getattr(object, name) and catching exceptions.)");
+(This is done by calling getattr(object, name) and catching AttributeError.)");
 
 
 static PyObject *