py: Check that arg to object.__new__ is a user-defined type.

Addresses issue #1203.
diff --git a/py/objobject.c b/py/objobject.c
index c5675c0..7288ac9 100644
--- a/py/objobject.c
+++ b/py/objobject.c
@@ -26,10 +26,9 @@
 
 #include <stdlib.h>
 
+#include "py/objtype.h"
 #include "py/runtime.h"
 
-mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
-
 typedef struct _mp_obj_object_t {
     mp_obj_base_t base;
 } mp_obj_object_t;
@@ -50,8 +49,12 @@
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__);
 
 STATIC mp_obj_t object___new__(mp_obj_t cls) {
+    if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)cls)) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                    "__new__ arg must be a user-type"));
+    }
     mp_obj_t o = MP_OBJ_SENTINEL;
-    mp_obj_t res = instance_make_new(cls, 1, 0, &o);
+    mp_obj_t res = mp_obj_instance_make_new(cls, 1, 0, &o);
     return res;
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__);
diff --git a/py/objtype.c b/py/objtype.c
index ed2d688..c2c8d2e 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -48,10 +48,6 @@
 /******************************************************************************/
 // instance object
 
-#define is_instance_type(type) ((type)->make_new == instance_make_new)
-#define is_native_type(type) ((type)->make_new != instance_make_new)
-mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
-
 STATIC mp_obj_t mp_obj_new_instance(mp_obj_t class, uint subobjs) {
     mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs);
     o->base.type = class;
@@ -73,7 +69,7 @@
             // Not a "real" type
             continue;
         }
-        if (is_native_type(bt)) {
+        if (mp_obj_is_native_type(bt)) {
             *last_native_base = bt;
             count++;
         } else {
@@ -114,7 +110,7 @@
         // This avoids extra method_name => slot lookup. On the other hand,
         // this should not be applied to class types, as will result in extra
         // lookup either.
-        if (lookup->meth_offset != 0 && is_native_type(type)) {
+        if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) {
             if (*(void**)((char*)type + lookup->meth_offset) != NULL) {
                 DEBUG_printf("mp_obj_class_lookup: matched special meth slot for %s\n", qstr_str(lookup->attr));
                 lookup->dest[0] = MP_OBJ_SENTINEL;
@@ -135,7 +131,7 @@
                     mp_convert_member_lookup(NULL, org_type, elem->value, lookup->dest);
                 } else {
                     mp_obj_instance_t *obj = lookup->obj;
-                    if (obj != MP_OBJ_NULL && is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
+                    if (obj != MP_OBJ_NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
                         // If we're dealing with native base class, then it applies to native sub-object
                         obj = obj->subobj[0];
                     }
@@ -153,7 +149,7 @@
         // Previous code block takes care about attributes defined in .locals_dict,
         // but some attributes of native types may be handled using .load_attr method,
         // so make sure we try to lookup those too.
-        if (lookup->obj != MP_OBJ_NULL && !lookup->is_type && is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
+        if (lookup->obj != MP_OBJ_NULL && !lookup->is_type && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
             mp_load_method_maybe(lookup->obj->subobj[0], lookup->attr, lookup->dest);
             if (lookup->dest[0] != MP_OBJ_NULL) {
                 return;
@@ -238,9 +234,10 @@
     mp_printf(print, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in);
 }
 
-mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
+mp_obj_t mp_obj_instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
     mp_obj_type_t *self = self_in;
+    assert(mp_obj_is_instance_type(self));
 
     const mp_obj_type_t *native_base;
     uint num_native_bases = instance_count_native_bases(self, &native_base);
@@ -442,7 +439,7 @@
 
 STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
     // logic: look in instance members then class locals
-    assert(is_instance_type(mp_obj_get_type(self_in)));
+    assert(mp_obj_is_instance_type(mp_obj_get_type(self_in)));
     mp_obj_instance_t *self = self_in;
 
     mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
@@ -870,7 +867,7 @@
     o->base.type = &mp_type_type;
     o->name = name;
     o->print = instance_print;
-    o->make_new = instance_make_new;
+    o->make_new = mp_obj_instance_make_new;
     o->call = mp_obj_instance_call;
     o->unary_op = instance_unary_op;
     o->binary_op = instance_binary_op;
diff --git a/py/objtype.h b/py/objtype.h
index de1909b..6023e8d 100644
--- a/py/objtype.h
+++ b/py/objtype.h
@@ -44,4 +44,9 @@
 bool mp_obj_instance_is_callable(mp_obj_t self_in);
 mp_obj_t mp_obj_instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
 
+#define mp_obj_is_instance_type(type) ((type)->make_new == mp_obj_instance_make_new)
+#define mp_obj_is_native_type(type) ((type)->make_new != mp_obj_instance_make_new)
+// this needs to be exposed for the above macros to work correctly
+mp_obj_t mp_obj_instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
+
 #endif // __MICROPY_INCLUDED_PY_OBJTYPE_H__
diff --git a/tests/basics/object_new.py b/tests/basics/object_new.py
index 6131ed3..befb5bf 100644
--- a/tests/basics/object_new.py
+++ b/tests/basics/object_new.py
@@ -18,3 +18,13 @@
 #print(dir(o))
 print(hasattr(o, "attr"))
 print(o.attr)
+
+# should only be able to call __new__ on user types
+try:
+    object.__new__(1)
+except TypeError:
+    print("TypeError")
+try:
+    object.__new__(int)
+except TypeError:
+    print("TypeError")