Sort ListFields() results.
diff --git a/python/message.c b/python/message.c
index d7c44ba..cf88bae 100644
--- a/python/message.c
+++ b/python/message.c
@@ -954,6 +954,14 @@
   }
 }
 
+static PyObject* PyUpb_CMessage_ListFieldsLessThan(PyObject* self,
+                                                   PyObject* val) {
+  assert(PyTuple_Check(val));
+  PyObject* field = PyTuple_GetItem(val, 0);
+  const upb_fielddef* f = PyUpb_FieldDescriptor_GetDef(field);
+  return PyLong_FromLong(upb_fielddef_number(f));
+}
+
 static PyObject* PyUpb_CMessage_ListFields(PyObject* _self, PyObject* arg) {
   PyObject* list = PyList_New(0);
   upb_msg* msg = PyUpb_CMessage_GetIfReified(_self);
@@ -967,7 +975,12 @@
   PyObject* py_val = NULL;
   PyObject* tuple = NULL;
   upb_msgval val;
+  uint32_t last_field = 0;
+  bool in_order = true;
   while (upb_msg_next(msg, m, symtab, &f, &val, &iter1)) {
+    const uint32_t field_number = upb_fielddef_number(f);
+    if (field_number < last_field) in_order = false;
+    last_field = field_number;
     PyObject* field_desc = PyUpb_FieldDescriptor_Get(f);
     PyObject* py_val = PyUpb_CMessage_GetFieldValue(_self, f);
     if (!field_desc || !py_val) goto err;
@@ -980,6 +993,23 @@
     tuple = NULL;
   }
 
+  if (!in_order) {
+    PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
+    PyObject* args = PyList_New(0);
+    PyObject* kwargs = PyDict_New();
+    PyDict_SetItemString(kwargs, "key", state->listfields_cmp_lt);
+    PyObject* m = PyObject_GetAttrString(list, "sort");
+    assert(m);
+    assert(args);
+    assert(kwargs);
+    PyObject* ret = PyObject_Call(m, args, kwargs);
+    Py_XDECREF(ret);
+    Py_XDECREF(m);
+    Py_XDECREF(args);
+    Py_XDECREF(kwargs);
+    if (!ret) return NULL;
+  }
+
   return list;
 
 err:
@@ -1194,7 +1224,6 @@
   if (upb_util_HasUnsetRequired(msg, msgdef, ext_pool, &fields)) {
     char* buf = NULL;
     size_t size = 0;
-    size_t i = 0;
     assert(fields->field);
     while (fields->field) {
       upb_FieldPathEntry* field = fields;
@@ -1416,11 +1445,9 @@
     {"WhichOneof", PyUpb_CMessage_WhichOneof, METH_O,
      "Returns the name of the field set inside a oneof, "
      "or None if no field is set."},
-    // TODO(https://github.com/protocolbuffers/upb/issues/459)
-    //{ "_CheckCalledFromGeneratedFile",
-    //(PyCFunction)_CheckCalledFromGeneratedFile,
-    //  METH_NOARGS | METH_STATIC,
-    //  "Raises TypeError if the caller is not in a _pb2.py file."},
+    {"_ListFieldsLessThan", PyUpb_CMessage_ListFieldsLessThan,
+     METH_O | METH_STATIC,
+     "Compares ListFields() list entries by field number"},
     {NULL, NULL}};
 
 static PyType_Slot PyUpb_CMessage_Slots[] = {
@@ -1664,6 +1691,8 @@
 
   if (!state->cmessage_type || !state->message_meta_type) return false;
   if (PyModule_AddObject(m, "MessageMeta", message_meta_type)) return false;
+  state->listfields_cmp_lt =
+      PyObject_GetAttrString((PyObject*)state->cmessage_type, "_ListFieldsLessThan");
 
   PyObject* mod = PyImport_ImportModule("google.protobuf.message");
   if (mod == NULL) return false;
@@ -1682,7 +1711,8 @@
   Py_DECREF(enum_type_wrapper);
 
   if (!state->encode_error_class || !state->decode_error_class ||
-      !state->message_class || !state->enum_type_wrapper_class) {
+      !state->message_class || !state->listfields_cmp_lt ||
+      !state->enum_type_wrapper_class) {
     return false;
   }