Skip to content

Commit 74578fc

Browse files
authored
builtin: guard array push len panics (#27335)
1 parent de365a1 commit 74578fc

3 files changed

Lines changed: 37 additions & 4 deletions

File tree

vlib/builtin/array.v

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,8 +1129,10 @@ fn (mut a array) set_ni(i int, val voidptr) {
11291129
}
11301130

11311131
fn (mut a array) push(val voidptr) {
1132-
if a.len < 0 {
1133-
panic('array.push: negative len')
1132+
$if !no_bounds_checking {
1133+
if a.len < 0 {
1134+
panic('array.push: negative len')
1135+
}
11341136
}
11351137
if a.len >= max_int {
11361138
panic('array.push: len bigger than max_int')

vlib/builtin/array_d_gcboehm_opt.v

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,10 @@ fn (a &array) clone_to_depth_noscan(depth int) array {
360360
}
361361

362362
fn (mut a array) push_noscan(val voidptr) {
363-
if a.len < 0 {
364-
panic('array.push_noscan: negative len')
363+
$if !no_bounds_checking {
364+
if a.len < 0 {
365+
panic('array.push_noscan: negative len')
366+
}
365367
}
366368
if a.len >= max_int {
367369
panic('array.push_noscan: len bigger than max_int')

vlib/v/gen/c/coutput_test.v

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,35 @@ fn test_comptime_for_empty_attrs_does_not_emit_new_array_calls() {
259259
assert !compilation.output.contains('.args = builtin____new_array_with_default(0, 0, sizeof(FunctionParam), 0)')
260260
}
261261

262+
fn test_array_push_no_bounds_checking_keeps_max_len_panics() {
263+
os.chdir(vroot) or {}
264+
test_source := os.join_path(os.vtmp_dir(), 'coutput_array_push_no_bounds_checking.vv')
265+
source_lines := [
266+
'module main',
267+
'',
268+
'fn main() {',
269+
'\tmut names := []string{}',
270+
"\tnames << 'alpha'",
271+
'\tmut scores := []int{}',
272+
'\tscores << 1',
273+
'\tprintln(names.len + scores.len)',
274+
'}',
275+
]
276+
os.write_file(test_source, source_lines.join('\n') + '\n')!
277+
defer {
278+
os.rm(test_source) or {}
279+
}
280+
cmd := '${os.quoted_path(vexe)} -prod -no-bounds-checking -o - ${os.quoted_path(test_source)}'
281+
compilation := os.execute(cmd)
282+
ensure_compilation_succeeded(compilation, cmd)
283+
assert compilation.output.contains('VV_LOC void builtin__array_push(array* a, voidptr val) {')
284+
assert compilation.output.contains('VV_LOC void builtin__array_push_noscan(array* a, voidptr val) {')
285+
assert !compilation.output.contains('array.push: negative len')
286+
assert compilation.output.contains('array.push: len bigger than max_int')
287+
assert !compilation.output.contains('array.push_noscan: negative len')
288+
assert compilation.output.contains('array.push_noscan: len bigger than max_int')
289+
}
290+
262291
fn test_windows_sharedlive_string_interpolation_in_ternary_does_not_emit_inline_tmp_decl() {
263292
os.chdir(vroot) or {}
264293
test_source := os.join_path(os.vtmp_dir(), 'coutput_live_windows_ternary_str_intp.vv')

0 commit comments

Comments
 (0)