just sort the items tuple directly (closes #24094)
diff --git a/Lib/test/test_json/test_dump.py b/Lib/test/test_json/test_dump.py
index af19258..fd0d86b 100644
--- a/Lib/test/test_json/test_dump.py
+++ b/Lib/test/test_json/test_dump.py
@@ -28,6 +28,25 @@
         self.assertEqual(self.dumps(a, default=crasher),
                  '[null, null, null, null, null]')
 
+    # Issue 24094
+    def test_encode_evil_dict(self):
+        class D(dict):
+            def keys(self):
+                return L
+
+        class X:
+            def __hash__(self):
+                del L[0]
+                return 1337
+
+            def __lt__(self, o):
+                return 0
+
+        L = [X() for i in range(1122)]
+        d = D()
+        d[1337] = "true.dat"
+        self.assertEqual(self.dumps(d, sort_keys=True), '{"1337": "true.dat"}')
+
 
 class TestPyDump(TestDump, PyTest): pass
 
diff --git a/Misc/NEWS b/Misc/NEWS
index 1a313db..ca923fb 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -19,6 +19,9 @@
 Library
 -------
 
+- Issue #24094: Fix possible crash in json.encode with poorly behaved dict
+  subclasses.
+
 - Issue #23367: Fix possible overflows in the unicodedata module.
 
 - Issue #23361: Fix possible overflow in Windows subprocess creation code.
diff --git a/Modules/_json.c b/Modules/_json.c
index 397037e..6df08b5 100644
--- a/Modules/_json.c
+++ b/Modules/_json.c
@@ -1527,35 +1527,11 @@
         */
     }
 
-    if (PyObject_IsTrue(s->sort_keys)) {
-        /* First sort the keys then replace them with (key, value) tuples. */
-        Py_ssize_t i, nitems;
-        items = PyMapping_Keys(dct);
-        if (items == NULL)
-            goto bail;
-        if (!PyList_Check(items)) {
-            PyErr_SetString(PyExc_ValueError, "keys must return list");
-            goto bail;
-        }
-        if (PyList_Sort(items) < 0)
-            goto bail;
-        nitems = PyList_GET_SIZE(items);
-        for (i = 0; i < nitems; i++) {
-            PyObject *key, *value;
-            key = PyList_GET_ITEM(items, i);
-            value = PyDict_GetItem(dct, key);
-            item = PyTuple_Pack(2, key, value);
-            if (item == NULL)
-                goto bail;
-            PyList_SET_ITEM(items, i, item);
-            Py_DECREF(key);
-        }
-    }
-    else {
-        items = PyMapping_Items(dct);
-    }
+    items = PyMapping_Items(dct);
     if (items == NULL)
         goto bail;
+    if (PyObject_IsTrue(s->sort_keys) && PyList_Sort(items) < 0)
+        goto bail;
     it = PyObject_GetIter(items);
     Py_DECREF(items);
     if (it == NULL)