diff options
author | stijn <stinos@zoho.com> | 2015-01-16 13:36:18 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2015-01-20 23:50:43 +0000 |
commit | bf19541f466fe40176c80ccfe324ef13c96bf957 (patch) | |
tree | 88aa42e85788c44d5412a5aac3d4384a7cd1a41a | |
parent | 0ab3fc3805282cc733bdf7a5970ec37e3160beee (diff) | |
download | micropython-bf19541f466fe40176c80ccfe324ef13c96bf957.tar.gz micropython-bf19541f466fe40176c80ccfe324ef13c96bf957.zip |
py: Prevent segfault for operations on closed StringIO.
Addresses issue #1067.
-rw-r--r-- | py/objstringio.c | 22 | ||||
-rw-r--r-- | tests/io/stringio1.py | 11 |
2 files changed, 32 insertions, 1 deletions
diff --git a/py/objstringio.c b/py/objstringio.c index f7b8074f35..c7e8395b49 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -42,15 +42,26 @@ typedef struct _mp_obj_stringio_t { mp_uint_t pos; } mp_obj_stringio_t; +#if MICROPY_CPYTHON_COMPAT +STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) { + if (o->vstr == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "I/O operation on closed file")); + } +} +#else +#define check_stringio_is_open(o) +#endif + STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_stringio_t *self = self_in; - print(env, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self->vstr); + print(env, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self); } STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { (void)errcode; mp_obj_stringio_t *o = o_in; + check_stringio_is_open(o); mp_uint_t remaining = o->vstr->len - o->pos; if (size > remaining) { size = remaining; @@ -63,6 +74,7 @@ STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { (void)errcode; mp_obj_stringio_t *o = o_in; + check_stringio_is_open(o); mp_uint_t remaining = o->vstr->alloc - o->pos; if (size > remaining) { // Take all what's already allocated... @@ -82,14 +94,22 @@ STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) { mp_obj_stringio_t *self = self_in; + check_stringio_is_open(self); return mp_obj_new_str_of_type(STREAM_TO_CONTENT_TYPE(self), (byte*)self->vstr->buf, self->vstr->len); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue); STATIC mp_obj_t stringio_close(mp_obj_t self_in) { mp_obj_stringio_t *self = self_in; +#if MICROPY_CPYTHON_COMPAT vstr_free(self->vstr); self->vstr = NULL; +#else + vstr_clear(self->vstr); + self->vstr->alloc = 0; + self->vstr->len = 0; + self->pos = 0; +#endif return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_close_obj, stringio_close); diff --git a/tests/io/stringio1.py b/tests/io/stringio1.py index 6979fe7c9d..dae0187f88 100644 --- a/tests/io/stringio1.py +++ b/tests/io/stringio1.py @@ -28,3 +28,14 @@ print(a.getvalue()) a = io.StringIO() a.write("foo") print(a.read()) + +a = io.StringIO() +a.close() +for f in [a.read, a.getvalue, lambda:a.write("")]: + # CPython throws for operations on closed I/O, micropython makes + # the underlying string empty unless MICROPY_CPYTHON_COMPAT defined + try: + f() + print("ValueError") + except ValueError: + print("ValueError") |