Fixed or accounted for nearly all errors in message_test.
diff --git a/python/message.c b/python/message.c
index b0df698..fd0d37e 100644
--- a/python/message.c
+++ b/python/message.c
@@ -847,9 +847,12 @@
   PyObject* ret = PyObject_GenericGetAttr(_self, attr);
   if (ret) return ret;
 
-  // If the attribute wasn't found, look for attributes on the class. But if a
-  // different kind of error (other than AttributeError) was found, return that.
-  if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+  // Swallow AttributeError if it occurred and try again on the metaclass
+  // to pick up class attributes.  But we have to special-case "Extensions"
+  // which affirmatively returns AttributeError when a message is not
+  // extendable.
+  if (PyErr_ExceptionMatches(PyExc_AttributeError) &&
+      strcmp(PyUpb_GetStrData(attr), "Extensions") != 0) {
     PyErr_Clear();
     return PyUpb_MessageMeta_GetAttr((PyObject*)Py_TYPE(_self), attr);
   }
@@ -986,11 +989,14 @@
   const upb_extreg* extreg = upb_symtab_extreg(upb_filedef_symtab(file));
   const upb_msglayout* layout = upb_msgdef_layout(msgdef);
   upb_arena* arena = PyUpb_Arena_Get(self->arena);
+  int options = 0;
+  PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
+  options |=
+      UPB_DECODE_MAXDEPTH(state->allow_oversize_protos ? UINT32_MAX : 100);
   upb_DecodeStatus status =
-      _upb_decode(buf, size, self->ptr.msg, layout, extreg, 0, arena);
+      _upb_decode(buf, size, self->ptr.msg, layout, extreg, options, arena);
   Py_XDECREF(bytes);
   if (status != kUpb_DecodeStatus_Ok) {
-    PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
     PyErr_Format(state->decode_error_class, "Error parsing message");
     return NULL;
   }
@@ -1183,6 +1189,8 @@
   int options = 0;
   if (check_required) options |= UPB_ENCODE_CHECKREQUIRED;
   if (deterministic) options |= UPB_ENCODE_DETERMINISTIC;
+  // Python does not currently have any effective limit on serialization depth.
+  options |= UPB_ENCODE_MAXDEPTH(UINT32_MAX);
   char* pb = upb_encode_ex(self->ptr.msg, layout, options, arena, &size);
   PyObject* ret = NULL;
 
@@ -1248,10 +1256,6 @@
 
 static PyGetSetDef PyUpb_CMessage_Getters[] = {
     {"Extensions", PyUpb_CMessage_GetExtensionDict, NULL, "Extension dict"},
-    /*
-    {"_extensions_by_name", (getter)GetExtensionsByName, NULL},
-    {"_extensions_by_number", (getter)GetExtensionsByNumber, NULL},
-    */
     {NULL}};
 
 static PyMethodDef PyUpb_CMessage_Methods[] = {
diff --git a/python/minimal_test.py b/python/minimal_test.py
index 26d6553..01eef6e 100644
--- a/python/minimal_test.py
+++ b/python/minimal_test.py
@@ -32,6 +32,9 @@
 from google.protobuf.internal import api_implementation
 from google.protobuf import unittest_pb2
 from google.protobuf import descriptor_pool
+from google.protobuf import text_format
+from google.protobuf import message_factory
+from google.protobuf import message
 from google.protobuf.internal import factory_test1_pb2
 from google.protobuf.internal import factory_test2_pb2
 from google.protobuf import descriptor_pb2
@@ -72,9 +75,35 @@
         test_slice(11, 3, -2)
         test_slice(11, 3, -3)
         test_slice(10, 25, 4)
+    
+    def testExtensionsErrors(self):
+        msg = unittest_pb2.TestAllTypes()
+        self.assertRaises(AttributeError, getattr, msg, 'Extensions')
 
 #TestMessageExtension.test_descriptor_pool.__unittest_expecting_failure__ = True
 
+class OversizeProtosTest(unittest.TestCase):
+  def setUp(self):
+    msg = unittest_pb2.NestedTestAllTypes()
+    m = msg
+    for i in range(101):
+      m = m.child
+    m.Clear()
+    self.p_serialized = msg.SerializeToString()
+    
+  def testAssertOversizeProto(self):
+    from google.protobuf.pyext._message import SetAllowOversizeProtos
+    SetAllowOversizeProtos(False)
+    q = unittest_pb2.NestedTestAllTypes()
+    with self.assertRaises(message.DecodeError):
+      q.ParseFromString(self.p_serialized)
+      print(q)
+  
+  def testSucceedOversizeProto(self):
+    from google.protobuf.pyext._message import SetAllowOversizeProtos
+    SetAllowOversizeProtos(True)
+    q = unittest_pb2.NestedTestAllTypes()
+    q.ParseFromString(self.p_serialized)
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/message_test_wrapper.py b/python/pb_unit_tests/message_test_wrapper.py
index 993f8e0..d73997b 100644
--- a/python/pb_unit_tests/message_test_wrapper.py
+++ b/python/pb_unit_tests/message_test_wrapper.py
@@ -26,28 +26,29 @@
 from google.protobuf.internal import message_test
 import unittest
 
-message_test.MessageTest.testBadUtf8String_proto2.__unittest_expecting_failure__ = True
-message_test.MessageTest.testBadUtf8String_proto3.__unittest_expecting_failure__ = True
+# We don't want to support extending repeated fields with nothing; this behavior
+# is marked for deprecation in the existing library.
 message_test.MessageTest.testExtendFloatWithNothing_proto2.__unittest_expecting_failure__ = True
 message_test.MessageTest.testExtendFloatWithNothing_proto3.__unittest_expecting_failure__ = True
 message_test.MessageTest.testExtendInt32WithNothing_proto2.__unittest_expecting_failure__ = True
 message_test.MessageTest.testExtendInt32WithNothing_proto3.__unittest_expecting_failure__ = True
 message_test.MessageTest.testExtendStringWithNothing_proto2.__unittest_expecting_failure__ = True
 message_test.MessageTest.testExtendStringWithNothing_proto3.__unittest_expecting_failure__ = True
+
+# Our float printing suffers from not having dtoa().
 message_test.MessageTest.testFloatPrinting_proto2.__unittest_expecting_failure__ = True
 message_test.MessageTest.testFloatPrinting_proto3.__unittest_expecting_failure__ = True
 message_test.MessageTest.testHighPrecisionDoublePrinting_proto2.__unittest_expecting_failure__ = True
 message_test.MessageTest.testHighPrecisionDoublePrinting_proto3.__unittest_expecting_failure__ = True
-message_test.MessageTest.testInsertRepeatedCompositeField_proto2.__unittest_expecting_failure__ = True
-message_test.MessageTest.testInsertRepeatedCompositeField_proto3.__unittest_expecting_failure__ = True
-message_test.Proto2Test.testExtensionsErrors.__unittest_expecting_failure__ = True
+
+# For these tests we are throwing the correct error, only the text of the error
+# message is a mismatch.  For technical reasons around the limited API, matching
+# the existing error message exactly is not feasible.
+message_test.Proto3Test.testCopyFromBadType.__unittest_expecting_failure__ = True
+message_test.Proto3Test.testMergeFromBadType.__unittest_expecting_failure__ = True
+
 message_test.Proto2Test.testPythonicInit.__unittest_expecting_failure__ = True
 message_test.Proto2Test.test_documentation.__unittest_expecting_failure__ = True
-message_test.Proto3Test.testCopyFromBadType.__unittest_expecting_failure__ = True
-message_test.Proto3Test.testMapDeterministicSerialization.__unittest_expecting_failure__ = True
-message_test.Proto3Test.testMergeFromBadType.__unittest_expecting_failure__ = True
-message_test.OversizeProtosTest.testAssertOversizeProto.__unittest_expecting_failure__ = True
-message_test.OversizeProtosTest.testSucceedOversizeProto.__unittest_expecting_failure__ = True
 
 if __name__ == '__main__':
   unittest.main(module=message_test, verbosity=2)
diff --git a/python/pb_unit_tests/well_known_types_test_wrapper.py b/python/pb_unit_tests/well_known_types_test_wrapper.py
index 22a35d5..6ded8d4 100644
--- a/python/pb_unit_tests/well_known_types_test_wrapper.py
+++ b/python/pb_unit_tests/well_known_types_test_wrapper.py
@@ -26,7 +26,5 @@
 from google.protobuf.internal import well_known_types_test
 import unittest
 
-well_known_types_test.AnyTest.testPackDeterministic.__unittest_expecting_failure__ = True
-
 if __name__ == '__main__':
   unittest.main(module=well_known_types_test, verbosity=2)
diff --git a/python/protobuf.c b/python/protobuf.c
index c577281..8eb49a4 100644
--- a/python/protobuf.c
+++ b/python/protobuf.c
@@ -40,11 +40,28 @@
   PyUpb_WeakMap_Free(s->obj_cache);
 }
 
+PyObject* PyUpb_SetAllowOversizeProtos(PyObject* m, PyObject* arg) {
+  if (!arg || !PyBool_Check(arg)) {
+    PyErr_SetString(PyExc_TypeError,
+                    "Argument to SetAllowOversizeProtos must be boolean");
+    return NULL;
+  }
+  PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
+  state->allow_oversize_protos = PyObject_IsTrue(arg);
+  Py_INCREF(arg);
+  return arg;
+}
+
+static PyMethodDef PyUpb_ModuleMethods[] = {
+    {"SetAllowOversizeProtos", PyUpb_SetAllowOversizeProtos, METH_O,
+     "Enable/disable oversize proto parsing."},
+    {NULL, NULL}};
+
 static struct PyModuleDef module_def = {PyModuleDef_HEAD_INIT,
                                         PYUPB_MODULE_NAME,
                                         "Protobuf Module",
                                         sizeof(PyUpb_ModuleState),
-                                        NULL,  // m_methods
+                                        PyUpb_ModuleMethods,  // m_methods
                                         NULL,  // m_slots
                                         NULL,  // m_traverse
                                         NULL,  // m_clear
@@ -302,6 +319,7 @@
 
   PyUpb_ModuleState *state = PyUpb_ModuleState_GetFromModule(m);
 
+  state->allow_oversize_protos = false;
   state->wkt_bases = NULL;
   state->obj_cache = PyUpb_WeakMap_New();
 
diff --git a/python/protobuf.h b/python/protobuf.h
index fa9785a..75c8e01 100644
--- a/python/protobuf.h
+++ b/python/protobuf.h
@@ -83,6 +83,7 @@
   PyTypeObject *message_meta_type;
 
   // From protobuf.c
+  bool allow_oversize_protos;
   PyObject *wkt_bases;
   PyTypeObject *arena_type;
   PyUpb_WeakMap *obj_cache;