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_uint_t pos;
|
||||||
} mp_obj_stringio_t;
|
} 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) {
|
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;
|
(void)kind;
|
||||||
mp_obj_stringio_t *self = self_in;
|
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) {
|
STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||||
(void)errcode;
|
(void)errcode;
|
||||||
mp_obj_stringio_t *o = o_in;
|
mp_obj_stringio_t *o = o_in;
|
||||||
|
check_stringio_is_open(o);
|
||||||
mp_uint_t remaining = o->vstr->len - o->pos;
|
mp_uint_t remaining = o->vstr->len - o->pos;
|
||||||
if (size > remaining) {
|
if (size > remaining) {
|
||||||
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) {
|
STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||||
(void)errcode;
|
(void)errcode;
|
||||||
mp_obj_stringio_t *o = o_in;
|
mp_obj_stringio_t *o = o_in;
|
||||||
|
check_stringio_is_open(o);
|
||||||
mp_uint_t remaining = o->vstr->alloc - o->pos;
|
mp_uint_t remaining = o->vstr->alloc - o->pos;
|
||||||
if (size > remaining) {
|
if (size > remaining) {
|
||||||
// Take all what's already allocated...
|
// 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) {
|
STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) {
|
||||||
mp_obj_stringio_t *self = 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);
|
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_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue);
|
||||||
|
|
||||||
STATIC mp_obj_t stringio_close(mp_obj_t self_in) {
|
STATIC mp_obj_t stringio_close(mp_obj_t self_in) {
|
||||||
mp_obj_stringio_t *self = self_in;
|
mp_obj_stringio_t *self = self_in;
|
||||||
|
#if MICROPY_CPYTHON_COMPAT
|
||||||
vstr_free(self->vstr);
|
vstr_free(self->vstr);
|
||||||
self->vstr = NULL;
|
self->vstr = NULL;
|
||||||
|
#else
|
||||||
|
vstr_clear(self->vstr);
|
||||||
|
self->vstr->alloc = 0;
|
||||||
|
self->vstr->len = 0;
|
||||||
|
self->pos = 0;
|
||||||
|
#endif
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_close_obj, stringio_close);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_close_obj, stringio_close);
|
||||||
|
|
|
@ -28,3 +28,14 @@ print(a.getvalue())
|
||||||
a = io.StringIO()
|
a = io.StringIO()
|
||||||
a.write("foo")
|
a.write("foo")
|
||||||
print(a.read())
|
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