summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/bc.c7
-rw-r--r--py/binary.c16
-rw-r--r--py/gc_long_lived.c6
-rw-r--r--py/mpconfig.h6
-rw-r--r--py/objarray.c35
-rw-r--r--py/objgenerator.c2
-rw-r--r--py/objint_mpz.c4
-rw-r--r--py/objstr.c5
-rw-r--r--py/objtype.c47
9 files changed, 118 insertions, 10 deletions
diff --git a/py/bc.c b/py/bc.c
index 381daa24d..442a29771 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -190,6 +190,13 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw
for (size_t i = 0; i < n_kw; i++) {
// the keys in kwargs are expected to be qstr objects
mp_obj_t wanted_arg_name = kwargs[2 * i];
+ if(MP_UNLIKELY(!MP_OBJ_IS_QSTR(wanted_arg_name))) {
+ #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
+ mp_raise_TypeError("unexpected keyword argument");
+ #else
+ mp_raise_TypeError("keywords must be strings");
+ #endif
+ }
for (size_t j = 0; j < n_pos_args + n_kwonly_args; j++) {
if (wanted_arg_name == arg_names[j]) {
if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) {
diff --git a/py/binary.c b/py/binary.c
index 62cb384f1..bb334ed3d 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -57,8 +57,10 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) {
size = 4; break;
case 'q': case 'Q':
size = 8; break;
+#if MICROPY_NONSTANDARD_TYPECODES
case 'P': case 'O': case 'S':
size = sizeof(void*); break;
+#endif
case 'f':
size = sizeof(float); break;
case 'd':
@@ -89,9 +91,11 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) {
case 'q': case 'Q':
align = alignof(long long);
size = sizeof(long long); break;
+#if MICROPY_NONSTANDARD_TYPECODES
case 'P': case 'O': case 'S':
align = alignof(void*);
size = sizeof(void*); break;
+#endif
case 'f':
align = alignof(float);
size = sizeof(float); break;
@@ -148,12 +152,14 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) {
case 'd':
return mp_obj_new_float(((double*)p)[index]);
#endif
+#if MICROPY_NONSTANDARD_TYPECODES
// Extension to CPython: array of objects
case 'O':
return ((mp_obj_t*)p)[index];
// Extension to CPython: array of pointers
case 'P':
return mp_obj_new_int((mp_int_t)(uintptr_t)((void**)p)[index]);
+#endif
}
return MP_OBJ_NEW_SMALL_INT(val);
}
@@ -202,11 +208,13 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
- if (val_type == 'O') {
+ if (MICROPY_NONSTANDARD_TYPECODES && (val_type == 'O')) {
return (mp_obj_t)(mp_uint_t)val;
+#if MICROPY_NONSTANDARD_TYPECODES
} else if (val_type == 'S') {
const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val;
return mp_obj_new_str(s_val, strlen(s_val), false);
+#endif
#if MICROPY_PY_BUILTINS_FLOAT
} else if (val_type == 'f') {
union { uint32_t i; float f; } fpu = {val};
@@ -267,9 +275,11 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
mp_uint_t val;
switch (val_type) {
+#if MICROPY_NONSTANDARD_TYPECODES
case 'O':
val = (mp_uint_t)val_in;
break;
+#endif
#if MICROPY_PY_BUILTINS_FLOAT
case 'f': {
union { uint32_t i; float f; } fp_sp;
@@ -324,10 +334,12 @@ void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t v
((double*)p)[index] = mp_obj_get_float(val_in);
break;
#endif
+#if MICROPY_NONSTANDARD_TYPECODES
// Extension to CPython: array of objects
case 'O':
((mp_obj_t*)p)[index] = val_in;
break;
+#endif
default:
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
@@ -384,9 +396,11 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, m
((double*)p)[index] = val;
break;
#endif
+#if MICROPY_NONSTANDARD_TYPECODES
// Extension to CPython: array of pointers
case 'P':
((void**)p)[index] = (void*)(uintptr_t)val;
break;
+#endif
}
}
diff --git a/py/gc_long_lived.c b/py/gc_long_lived.c
index c50bbcd83..d34fde5d9 100644
--- a/py/gc_long_lived.c
+++ b/py/gc_long_lived.c
@@ -78,9 +78,9 @@ mp_obj_property_t *make_property_long_lived(mp_obj_property_t *prop, uint8_t max
if (max_depth == 0) {
return prop;
}
- prop->proxy[0] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[0], max_depth - 1);
- prop->proxy[1] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[1], max_depth - 1);
- prop->proxy[2] = make_fun_bc_long_lived((mp_obj_fun_bc_t*) prop->proxy[2], max_depth - 1);
+ prop->proxy[0] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[0], max_depth - 1);
+ prop->proxy[1] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[1], max_depth - 1);
+ prop->proxy[2] = make_obj_long_lived((mp_obj_fun_bc_t*) prop->proxy[2], max_depth - 1);
return gc_make_long_lived(prop);
}
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 252ab7f37..765ae1e8f 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -888,6 +888,12 @@ typedef double mp_float_t;
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (0)
#endif
+// Whether to support nonstandard typecodes "O", "P" and "S"
+// in array and struct modules.
+#ifndef MICROPY_NONSTANDARD_TYPECODES
+#define MICROPY_NONSTANDARD_TYPECODES (1)
+#endif
+
// Whether to support attrtuple type (MicroPython extension)
// It provides space-efficient tuples with attribute access
#ifndef MICROPY_PY_ATTRTUPLE
diff --git a/py/objarray.c b/py/objarray.c
index a1a979b56..c4c547e19 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -241,6 +241,39 @@ STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in);
switch (op) {
+ case MP_BINARY_OP_MULTIPLY:
+ case MP_BINARY_OP_INPLACE_MULTIPLY: {
+ if (!MP_OBJ_IS_INT(rhs_in)) {
+ return MP_OBJ_NULL; // op not supported
+ }
+ mp_uint_t repeat = mp_obj_get_int(rhs_in);
+ bool inplace = (op == MP_BINARY_OP_INPLACE_MULTIPLY);
+ mp_buffer_info_t lhs_bufinfo;
+ array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
+ mp_obj_array_t *res;
+ byte *ptr;
+ size_t orig_lhs_bufinfo_len = lhs_bufinfo.len;
+ if(inplace) {
+ res = lhs;
+ size_t item_sz = mp_binary_get_size('@', lhs->typecode, NULL);
+ lhs->items = m_renew(byte, lhs->items, (lhs->len + lhs->free) * item_sz, lhs->len * repeat * item_sz);
+ lhs->len = lhs->len * repeat;
+ lhs->free = 0;
+ if (!repeat)
+ return MP_OBJ_FROM_PTR(res);
+ repeat--;
+ ptr = (byte*)res->items + orig_lhs_bufinfo_len;
+ } else {
+ res = array_new(lhs_bufinfo.typecode, lhs->len * repeat);
+ ptr = (byte*)res->items;
+ }
+ if(orig_lhs_bufinfo_len) {
+ for(;repeat--; ptr += orig_lhs_bufinfo_len) {
+ memcpy(ptr, lhs_bufinfo.buf, orig_lhs_bufinfo_len);
+ }
+ }
+ return MP_OBJ_FROM_PTR(res);
+ }
case MP_BINARY_OP_ADD: {
// allow to add anything that has the buffer protocol (extension to CPython)
mp_buffer_info_t lhs_bufinfo;
@@ -437,9 +470,11 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
} else {
mp_seq_replace_slice_no_grow(dest_items, o->len,
slice.start, slice.stop, src_items, src_len, item_sz);
+#if MICROPY_NONSTANDARD_TYPECODES
// Clear "freed" elements at the end of list
// TODO: This is actually only needed for typecode=='O'
mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz);
+#endif
// TODO: alloc policy after shrinking
}
o->len += len_adj;
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 139452442..ff566c076 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -32,6 +32,7 @@
#include "py/bc.h"
#include "py/objgenerator.h"
#include "py/objfun.h"
+#include "py/stackctrl.h"
/******************************************************************************/
/* generator wrapper */
@@ -92,6 +93,7 @@ STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_pri
}
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
+ MP_STACK_CHECK();
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));
mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
if (self->code_state.ip == 0) {
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 7b5cb0b9d..808fae6e4 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -343,6 +343,10 @@ mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) {
mpz_t *rhs = mp_mpz_for_int(exponent, &r_temp);
mpz_t *mod = mp_mpz_for_int(modulus, &m_temp);
+ if (mpz_is_zero(mod)) {
+ mp_raise_msg(&mp_type_ValueError, "pow() 3rd argument cannot be 0");
+ }
+
mpz_pow3_inpl(&(res_p->mpz), lhs, rhs, mod);
if (lhs == &l_temp) { mpz_deinit(lhs); }
diff --git a/py/objstr.c b/py/objstr.c
index 64306f54f..7ace1cf73 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -692,8 +692,13 @@ STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, b
end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);
}
+ if (end < start) {
+ goto out_error;
+ }
+
const byte *p = find_subbytes(start, end - start, needle, needle_len, direction);
if (p == NULL) {
+ out_error:
// not found
if (is_index) {
mp_raise_ValueError("substring not found");
diff --git a/py/objtype.c b/py/objtype.c
index 1d6dc0b6c..5b70e8e48 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -567,6 +567,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
mp_obj_class_lookup(&lookup, self->base.type);
mp_obj_t member = dest[0];
if (member != MP_OBJ_NULL) {
+ // changes here may may require changes to super_attr, below
#if MICROPY_PY_BUILTINS_PROPERTY
if (MP_OBJ_IS_TYPE(member, &mp_type_property)) {
// object member is a property; delegate the load to the property
@@ -980,8 +981,14 @@ const mp_obj_type_t mp_type_type = {
};
mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) {
- assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // MicroPython restriction, for now
- assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // MicroPython restriction, for now
+ if(!MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)) {
+ // MicroPython restriction, for now
+ mp_raise_TypeError("type() argument 2 must be tuple");
+ }
+ if(!MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)) {
+ // MicroPython restriction, for now
+ mp_raise_TypeError("type() argument 3 must be dict");
+ }
// TODO might need to make a copy of locals_dict; at least that's how CPython does it
@@ -990,7 +997,9 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
mp_obj_t *items;
mp_obj_tuple_get(bases_tuple, &len, &items);
for (size_t i = 0; i < len; i++) {
- assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
+ if(!MP_OBJ_IS_TYPE(items[i], &mp_type_type)) {
+ mp_raise_TypeError("type is not an acceptable base type");
+ }
mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]);
// TODO: Verify with CPy, tested on function type
if (t->make_new == NULL) {
@@ -1076,6 +1085,9 @@ STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size
// 0 arguments are turned into 2 in the compiler
// 1 argument is not yet implemented
mp_arg_check_num(n_args, n_kw, 2, 2, false);
+ if(!MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
+ mp_raise_TypeError("first argument to super() must be type");
+ }
mp_obj_super_t *o = m_new_obj(mp_obj_super_t);
*o = (mp_obj_super_t){{type_in}, args[0], args[1]};
return MP_OBJ_FROM_PTR(o);
@@ -1112,14 +1124,37 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]));
if (dest[0] != MP_OBJ_NULL) {
- return;
+ break;
}
}
} else {
mp_obj_class_lookup(&lookup, type->parent);
- if (dest[0] != MP_OBJ_NULL) {
- return;
+ }
+
+ if (dest[0] != MP_OBJ_NULL) {
+ mp_obj_t member = dest[0];
+ // changes to mp_obj_instance_load_attr may require changes
+ // here...
+ #if MICROPY_PY_BUILTINS_PROPERTY
+ if (MP_OBJ_IS_TYPE(member, &mp_type_property)) {
+ const mp_obj_t *proxy = mp_obj_property_get(member);
+ if (proxy[0] == mp_const_none) {
+ mp_raise_AttributeError("unreadable attribute");
+ } else {
+ dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in);
+ }
+ }
+ #endif
+ #if MICROPY_PY_DESCRIPTORS
+ mp_obj_t attr_get_method[4];
+ mp_load_method_maybe(member, MP_QSTR___get__, attr_get_method);
+ if (attr_get_method[0] != MP_OBJ_NULL) {
+ attr_get_method[2] = self_in;
+ attr_get_method[3] = MP_OBJ_FROM_PTR(mp_obj_get_type(self_in));
+ dest[0] = mp_call_method_n_kw(2, 0, attr_get_method);
}
+ #endif
+ return;
}
mp_obj_class_lookup(&lookup, &mp_type_object);