Backport CPython PR 107584 (#275)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f67da87..8cd9876 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
 # Release 4.8.0 (???)
 
 - Drop support for Python 3.7 (including PyPy-3.7). Patch by Alex Waygood.
+- Fix bug where `get_original_bases()` would return incorrect results when
+  called on a concrete subclass of a generic class. Patch by Alex Waygood
+  (backporting https://github.com/python/cpython/pull/107584, by James
+  Hilton-Balfe).
 
 # Release 4.7.1 (July 2, 2023)
 
diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py
index 78fe0c0..e741d69 100644
--- a/src/test_typing_extensions.py
+++ b/src/test_typing_extensions.py
@@ -5704,6 +5704,25 @@
         self.assertEqual(get_original_bases(E), (list[T],))
         self.assertEqual(get_original_bases(F), (list[int],))
 
+    @skipIf(
+        sys.version_info[:3] == (3, 12, 0) and sys.version_info[3] in {"alpha", "beta"},
+        "Early versions of py312 had a bug"
+    )
+    def test_concrete_subclasses_of_generic_classes(self):
+        T = TypeVar("T")
+
+        class FirstBase(Generic[T]): pass
+        class SecondBase(Generic[T]): pass
+        class First(FirstBase[int]): pass
+        class Second(SecondBase[int]): pass
+        class G(First, Second): pass
+        self.assertEqual(get_original_bases(G), (First, Second))
+
+        class First_(Generic[T]): pass
+        class Second_(Generic[T]): pass
+        class H(First_, Second_): pass
+        self.assertEqual(get_original_bases(H), (First_, Second_))
+
     def test_namedtuples(self):
         # On 3.12, this should work well with typing.NamedTuple and typing_extensions.NamedTuple
         # On lower versions, it will only work fully with typing_extensions.NamedTuple
diff --git a/src/typing_extensions.py b/src/typing_extensions.py
index 0978c5f..b0b1bce 100644
--- a/src/typing_extensions.py
+++ b/src/typing_extensions.py
@@ -2570,14 +2570,11 @@
             assert get_original_bases(int) == (object,)
         """
         try:
-            return cls.__orig_bases__
+            return cls.__dict__.get("__orig_bases__", cls.__bases__)
         except AttributeError:
-            try:
-                return cls.__bases__
-            except AttributeError:
-                raise TypeError(
-                    f'Expected an instance of type, not {type(cls).__name__!r}'
-                ) from None
+            raise TypeError(
+                f'Expected an instance of type, not {type(cls).__name__!r}'
+            ) from None
 
 
 # NewType is a class on Python 3.10+, making it pickleable