py: Prevent segfault for operations on closed StringIO.
Addresses issue #1067.
This commit is contained in:
parent
0ab3fc3805
commit
bf19541f46
@ -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);
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user