py/objstringio: Catch mp_uint_t overflow of stream position in write().

This commit is contained in:
Tom Collins 2017-05-25 13:41:59 -07:00 committed by Damien George
parent ed6d2547df
commit e26fb3ad73
1 changed files with 11 additions and 6 deletions

View File

@ -72,22 +72,27 @@ STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size,
(void)errcode; (void)errcode;
mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in); mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);
check_stringio_is_open(o); check_stringio_is_open(o);
mp_int_t remaining = o->vstr->alloc - o->pos; mp_uint_t new_pos = o->pos + size;
if (new_pos < size) {
// Writing <size> bytes will overflow o->pos beyond limit of mp_uint_t.
*errcode = MP_EFBIG;
return MP_STREAM_ERROR;
}
mp_uint_t org_len = o->vstr->len; mp_uint_t org_len = o->vstr->len;
if ((mp_int_t)size > remaining) { if (new_pos > o->vstr->alloc) {
// Take all what's already allocated... // Take all what's already allocated...
o->vstr->len = o->vstr->alloc; o->vstr->len = o->vstr->alloc;
// ... and add more // ... and add more
vstr_add_len(o->vstr, size - remaining); vstr_add_len(o->vstr, new_pos - o->vstr->alloc);
} }
// If there was a seek past EOF, clear the hole // If there was a seek past EOF, clear the hole
if (o->pos > org_len) { if (o->pos > org_len) {
memset(o->vstr->buf + org_len, 0, o->pos - org_len); memset(o->vstr->buf + org_len, 0, o->pos - org_len);
} }
memcpy(o->vstr->buf + o->pos, buf, size); memcpy(o->vstr->buf + o->pos, buf, size);
o->pos += size; o->pos = new_pos;
if (o->pos > o->vstr->len) { if (new_pos > o->vstr->len) {
o->vstr->len = o->pos; o->vstr->len = new_pos;
} }
return size; return size;
} }