Fix builtin functions incorrectly exposing descriptor attributes (#2983)

Fix builtin functions incorrectly exposing descriptor attributes

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>
diff --git a/ChangeLog b/ChangeLog
index 8c7a1f7..a6d6335 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -26,6 +26,10 @@
 
   Closes #2628
 
+* Fix ``FunctionModel`` returning descriptor attributes for builtin functions.
+
+  Closes #2743
+
 * Catch ``MemoryError`` when inferring f-strings with extremely large format
   widths (e.g. ``f'{0:11111111111}'``) so that inference yields ``Uninferable``
   instead of crashing.
diff --git a/astroid/interpreter/objectmodel.py b/astroid/interpreter/objectmodel.py
index 62cc02e..148e7d7 100644
--- a/astroid/interpreter/objectmodel.py
+++ b/astroid/interpreter/objectmodel.py
@@ -272,6 +272,10 @@
 
 
 class FunctionModel(ObjectModel):
+    def _is_builtin_func(self) -> bool:
+        func = self._instance
+        return isinstance(func.parent, nodes.Module) and not func.root().pure_python
+
     @property
     def attr___name__(self):
         return node_classes.Const(value=self._instance.name, parent=self._instance)
@@ -290,6 +294,8 @@
     @property
     def attr___defaults__(self):
         func = self._instance
+        if self._is_builtin_func():
+            raise AttributeInferenceError(target=func, attribute="__defaults__")
         if not func.args.defaults:
             return node_classes.Const(value=None, parent=func)
 
@@ -299,6 +305,10 @@
 
     @property
     def attr___annotations__(self):
+        if self._is_builtin_func():
+            raise AttributeInferenceError(
+                target=self._instance, attribute="__annotations__"
+            )
         obj = node_classes.Dict(
             parent=self._instance,
             lineno=self._instance.lineno,
@@ -339,6 +349,8 @@
 
     @property
     def attr___dict__(self):
+        if self._is_builtin_func():
+            raise AttributeInferenceError(target=self._instance, attribute="__dict__")
         return node_classes.Dict(
             parent=self._instance,
             lineno=self._instance.lineno,
@@ -347,10 +359,27 @@
             end_col_offset=self._instance.end_col_offset,
         )
 
-    attr___globals__ = attr___dict__
+    @property
+    def attr___globals__(self):
+        if self._is_builtin_func():
+            raise AttributeInferenceError(
+                target=self._instance, attribute="__globals__"
+            )
+        return node_classes.Dict(
+            parent=self._instance,
+            lineno=self._instance.lineno,
+            col_offset=self._instance.col_offset,
+            end_lineno=self._instance.end_lineno,
+            end_col_offset=self._instance.end_col_offset,
+        )
 
     @property
     def attr___kwdefaults__(self):
+        if self._is_builtin_func():
+            raise AttributeInferenceError(
+                target=self._instance, attribute="__kwdefaults__"
+            )
+
         def _default_args(args, parent):
             for arg in args.kwonlyargs:
                 try:
@@ -382,6 +411,9 @@
     def attr___get__(self):
         func = self._instance
 
+        if self._is_builtin_func():
+            raise AttributeInferenceError(target=func, attribute="__get__")
+
         class DescriptorBoundMethod(bases.BoundMethod):
             """Bound method which knows how to understand calling descriptor
             binding.
diff --git a/tests/test_object_model.py b/tests/test_object_model.py
index 86298c4..89d27ae 100644
--- a/tests/test_object_model.py
+++ b/tests/test_object_model.py
@@ -998,3 +998,21 @@
     thisclass_inferred = next(thisclass_node.infer())
     assert isinstance(thisclass_inferred, nodes.ClassDef)
     assert thisclass_inferred.name == "Base"
+
+
+@pytest.mark.parametrize(
+    "attr",
+    [
+        "__get__",
+        "__defaults__",
+        "__annotations__",
+        "__dict__",
+        "__globals__",
+        "__kwdefaults__",
+    ],
+)
+def test_builtin_func_no_descriptor_attrs(attr: str) -> None:
+    """Test builtin functions lack descriptor protocol attributes."""
+    node = builder.extract_node(f"eval.{attr}")
+    with pytest.raises(InferenceError):
+        next(node.infer())
diff --git a/tests/test_regrtest.py b/tests/test_regrtest.py
index 26bc452..a207057 100644
--- a/tests/test_regrtest.py
+++ b/tests/test_regrtest.py
@@ -486,9 +486,8 @@
     assert node.name == "c"
 
 
-@pytest.mark.xfail(reason="Not fixed yet")
 def test_regression_eval_get_of_arg() -> None:
-    """Regression test for #2743"""
+    """Regression test for #2743."""
     node = _extract_single_node("eval.__get__(1)")
     with pytest.raises(InferenceError):
         next(node.infer())