patch 9.2.1187: tuple type with many items reads past the end of an array
Problem: A tuple type with more than 127 items gets a wrong item count
and reads past the end of an array. Allocation failure for a
tuple type is not handled.
Solution: Use an int for the item count. Use the "any" type when
allocation fails (Hirohito Higashi).
closes: #21517
Assisted-by: Claude
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
1 parent
26d8c85188
commit
21e109b324
6 files changed
+46
-8
No files matched your search
@@ -47,5 +47,6 @@ typedef enum {
|
||||
aid_get_func,
|
||||
aid_defer,
|
||||
aid_tuple_append,
|
||||
aid_tuple_type_args,
|
||||
aid_last
|
||||
} alloc_id_T;
|
||||
+2
-2
@@ -1640,8 +1640,8 @@ typedef enum
|
||||
// A type specification.
|
||||
struct type_S {
|
||||
vartype_T tt_type;
|
||||
int8_T tt_argcount; // for func, incl. vararg, -1 for unknown
|
||||
int8_T tt_min_argcount; // number of non-optional arguments
|
||||
int tt_argcount; // for func, incl. vararg, -1 for unknown
|
||||
int tt_min_argcount; // number of non-optional arguments
|
||||
short_u tt_flags; // TTFLAG_ values
|
||||
type_T *tt_member; // for list, dict, func return type
|
||||
class_T *tt_class; // for class and object
|
||||
|
||||
@@ -2542,4 +2542,36 @@ func Test_tuple_unpack_memory_fail()
|
||||
unlet t
|
||||
endfunc
|
||||
|
||||
" Memory allocation failure while creating a tuple type
|
||||
func Test_tuple_type_memory_fail()
|
||||
let lines =<< trim END
|
||||
var t = (1, 'a')
|
||||
END
|
||||
call test_alloc_fail(GetAllocId('tuple_type_args'), 0, 0)
|
||||
call v9.CheckSourceDefFailure(lines, 'E342:')
|
||||
|
||||
let lines =<< trim END
|
||||
var t = (1,) + ('a',)
|
||||
END
|
||||
call test_alloc_fail(GetAllocId('tuple_type_args'), 2, 0)
|
||||
call v9.CheckSourceDefFailure(lines, 'E342:')
|
||||
endfunc
|
||||
|
||||
" Test for a tuple type with more than 127 items
|
||||
func Test_tuple_type_many_items()
|
||||
let types = repeat(['number'], 300)->join(', ')
|
||||
let lines =<< trim eval END
|
||||
var t: tuple<{types}> = ({range(300)->join(', ')})
|
||||
assert_equal(299, t[299])
|
||||
assert_equal('tuple<{types}>', typename(t))
|
||||
END
|
||||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||||
|
||||
let types = repeat(['number'], 200)->join(', ')
|
||||
let lines =<< trim eval END
|
||||
var t: tuple<{types}> = ({repeat(["'x'"], 200)->join(', ')})
|
||||
END
|
||||
call v9.CheckSourceDefAndScriptFailure(lines, 'E1012:', 1)
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
@@ -743,6 +743,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1187,
|
||||
/**/
|
||||
1186,
|
||||
/**/
|
||||
|
||||
+2
-1
@@ -317,7 +317,8 @@ set_tuple_union_type_on_stack(type_T *type1, type_T *type2, cctx_T *cctx)
|
||||
type_T *new_tuple_type = get_tuple_type(&tuple_types_ga,
|
||||
cctx->ctx_type_list);
|
||||
// result inherits the variadic flag from the operands
|
||||
new_tuple_type->tt_flags |= (type1->tt_flags & TTFLAG_VARARGS)
|
||||
if ((new_tuple_type->tt_flags & TTFLAG_STATIC) == 0)
|
||||
new_tuple_type->tt_flags |= (type1->tt_flags & TTFLAG_VARARGS)
|
||||
| (type2->tt_flags & TTFLAG_VARARGS);
|
||||
|
||||
// set the type on the stack for the resulting tuple
|
||||
|
||||
+7
-5
@@ -321,7 +321,8 @@ tuple_type_add_types(
|
||||
// pointer to type_gap.
|
||||
if (ga_grow(type_gap, 1) == FAIL)
|
||||
return FAIL;
|
||||
tupletype->tt_args = ALLOC_CLEAR_MULT(type_T *, typecount);
|
||||
tupletype->tt_args = alloc_clear_id(sizeof(type_T *) * typecount,
|
||||
aid_tuple_type_args);
|
||||
if (tupletype->tt_args == NULL)
|
||||
return FAIL;
|
||||
((type_T **)type_gap->ga_data)[type_gap->ga_len] =
|
||||
@@ -389,7 +390,7 @@ get_tuple_type(garray_T *tuple_types_gap, garray_T *type_gap)
|
||||
if (typecount > 0)
|
||||
{
|
||||
if (tuple_type_add_types(type, typecount, type_gap) == FAIL)
|
||||
return NULL;
|
||||
return &t_any;
|
||||
mch_memmove(type->tt_args, tuple_types, sizeof(type_T *) * typecount);
|
||||
}
|
||||
type->tt_argcount = typecount;
|
||||
@@ -1919,13 +1920,14 @@ parse_type_tuple(
|
||||
*arg = p + 1;
|
||||
|
||||
ret_type = alloc_tuple_type(typecount, type_gap);
|
||||
ret_type->tt_flags = flags;
|
||||
ret_type->tt_argcount = typecount;
|
||||
if (tuple_type_add_types(ret_type, typecount, type_gap) == FAIL)
|
||||
if (ret_type == &t_any
|
||||
|| tuple_type_add_types(ret_type, typecount, type_gap) == FAIL)
|
||||
{
|
||||
ret_type = NULL;
|
||||
goto on_err;
|
||||
}
|
||||
ret_type->tt_flags = flags;
|
||||
ret_type->tt_argcount = typecount;
|
||||
mch_memmove(ret_type->tt_args, tuple_types_ga.ga_data,
|
||||
sizeof(type_T *) * typecount);
|
||||
|
||||
|
||||
Reference in new issue
Block a user