Skip to content

Commit c5510a5

Browse files
committed
Fix integer overflows
1 parent 8d75f7c commit c5510a5

3 files changed

Lines changed: 33 additions & 3 deletions

File tree

mypyc/lib-rt/vecs/vec_nested.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,11 @@ VecNested VecNested_Extend(VecNested vec, PyObject *iterable) {
329329
VecNested VecNested_ExtendVec(VecNested dst, VecNested src) {
330330
if (src.len == 0)
331331
return dst;
332+
if (src.len > PY_SSIZE_T_MAX - dst.len) {
333+
PyErr_NoMemory();
334+
VEC_DECREF(dst);
335+
return vec_error();
336+
}
332337
Py_ssize_t new_len = dst.len + src.len;
333338
// VecNested buf is never NULL (even for empty vecs), so no NULL guard needed
334339
Py_ssize_t cap = VEC_CAP(dst);
@@ -346,8 +351,13 @@ VecNested VecNested_ExtendVec(VecNested dst, VecNested src) {
346351
}
347352
// Need to reallocate (or dst and src share a buffer)
348353
Py_ssize_t new_cap = cap;
349-
while (new_cap < new_len)
354+
while (new_cap < new_len) {
355+
if (new_cap > (PY_SSIZE_T_MAX - 1) / 2) {
356+
new_cap = new_len;
357+
break;
358+
}
350359
new_cap = 2 * new_cap + 1;
360+
}
351361
int aliased = dst.buf == src.buf;
352362
VecNested new = vec_alloc(new_cap, dst.buf->item_type, dst.buf->depth);
353363
if (VEC_IS_ERROR(new)) {

mypyc/lib-rt/vecs/vec_t.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,11 @@ VecT VecT_Extend(VecT vec, PyObject *iterable, size_t item_type) {
342342
VecT VecT_ExtendVec(VecT dst, VecT src, size_t item_type) {
343343
if (src.len == 0)
344344
return dst;
345+
if (src.len > PY_SSIZE_T_MAX - dst.len) {
346+
PyErr_NoMemory();
347+
VEC_DECREF(dst);
348+
return vec_error();
349+
}
345350
Py_ssize_t new_len = dst.len + src.len;
346351
if (dst.buf == NULL) {
347352
// dst is empty, allocate new buf
@@ -369,8 +374,13 @@ VecT VecT_ExtendVec(VecT dst, VecT src, size_t item_type) {
369374
}
370375
// Need to reallocate (or dst and src share a buffer)
371376
Py_ssize_t new_cap = cap;
372-
while (new_cap < new_len)
377+
while (new_cap < new_len) {
378+
if (new_cap > (PY_SSIZE_T_MAX - 1) / 2) {
379+
new_cap = new_len;
380+
break;
381+
}
373382
new_cap = 2 * new_cap + 1;
383+
}
374384
int aliased = dst.buf == src.buf;
375385
VecT new = vec_alloc(new_cap, dst.buf->item_type);
376386
if (VEC_IS_ERROR(new)) {

mypyc/lib-rt/vecs/vec_template.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ VEC FUNC(Extend)(VEC vec, PyObject *iterable) {
372372
VEC FUNC(ExtendVec)(VEC dst, VEC src) {
373373
if (src.len == 0)
374374
return dst;
375+
if (unlikely(src.len > PY_SSIZE_T_MAX - dst.len)) {
376+
PyErr_NoMemory();
377+
VEC_DECREF(dst);
378+
return vec_error();
379+
}
375380
Py_ssize_t new_len = dst.len + src.len;
376381
Py_ssize_t cap = dst.buf ? VEC_CAP(dst) : 0;
377382
if (new_len <= cap && dst.buf != src.buf) {
@@ -382,8 +387,13 @@ VEC FUNC(ExtendVec)(VEC dst, VEC src) {
382387
}
383388
// Need to reallocate (or dst and src share a buffer)
384389
Py_ssize_t new_cap = cap;
385-
while (new_cap < new_len)
390+
while (new_cap < new_len) {
391+
if (unlikely(new_cap > (PY_SSIZE_T_MAX - 1) / 2)) {
392+
new_cap = new_len;
393+
break;
394+
}
386395
new_cap = 2 * new_cap + 1;
396+
}
387397
VEC new = vec_alloc(new_cap);
388398
if (VEC_IS_ERROR(new)) {
389399
VEC_DECREF(dst);

0 commit comments

Comments
 (0)