cgen: add fixed array bounds checking for non-literal index (#8832)
							parent
							
								
									41a3b115a1
								
							
						
					
					
						commit
						15daeaeafa
					
				
							
								
								
									
										8
									
								
								TESTS.md
								
								
								
								
							
							
						
						
									
										8
									
								
								TESTS.md
								
								
								
								
							|  | @ -18,6 +18,11 @@ Tip: use `v -cc tcc` when compiling tests for speed. | |||
| 
 | ||||
| General runnable tests for different features of the V compiler. | ||||
| 
 | ||||
| * `vlib/v/tests/inout/compiler_test.v` | ||||
| 
 | ||||
| Test output of running a V program matches an expected .out file. | ||||
| Check the source for how to test panics. | ||||
| 
 | ||||
| ## Test building of actual V programs (examples, tools, V itself) | ||||
| 
 | ||||
| * `v build-tools` | ||||
|  | @ -41,11 +46,12 @@ This verifies that `_keep.v` files would be unchanged by `vfmt -w`. | |||
| This checks all source files are formatted and prints a summary. | ||||
| This is not required. | ||||
| 
 | ||||
| ## Other | ||||
| * `v test-fmt` | ||||
| 
 | ||||
| Test all files in the current directory are formatted. | ||||
| 
 | ||||
| ## Markdown | ||||
| 
 | ||||
| * `v check-md -hide-warnings .` | ||||
| 
 | ||||
| Ensure that all .md files in the project are formatted properly, | ||||
|  |  | |||
|  | @ -274,3 +274,14 @@ pub fn is_atty(fd int) int { | |||
| 		return C.isatty(fd) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| fn v_fixed_index(i int, len int) int { | ||||
| 	$if !no_bounds_checking ? { | ||||
| 		if i < 0 || i >= len { | ||||
| 			s := 'fixed array index out of range (index: $i, len: $len)' | ||||
| 			panic(s) | ||||
| 		} | ||||
| 	} | ||||
| 	return i | ||||
| } | ||||
|  |  | |||
|  | @ -4217,6 +4217,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { | |||
| 			g.write(')') | ||||
| 		} | ||||
| 		else { | ||||
| 			// indexing
 | ||||
| 			sym := g.table.get_final_type_symbol(node.left_type) | ||||
| 			left_is_ptr := node.left_type.is_ptr() | ||||
| 			if sym.kind == .array { | ||||
|  | @ -4397,7 +4398,15 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { | |||
| 					g.expr(node.left) | ||||
| 				} | ||||
| 				g.write('[') | ||||
| 				g.expr(node.index) | ||||
| 				direct := g.fn_decl != 0 && g.fn_decl.is_direct_arr | ||||
| 				if direct || node.index is ast.IntegerLiteral { | ||||
| 					g.expr(node.index) | ||||
| 				} else { | ||||
| 					// bounds check
 | ||||
| 					g.write('v_fixed_index(') | ||||
| 					g.expr(node.index) | ||||
| 					g.write(', $info.size)') | ||||
| 				} | ||||
| 				g.write(']') | ||||
| 				if is_fn_index_call { | ||||
| 					g.write(')') | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ pub fn mark_used(mut the_table table.Table, pref &pref.Preferences, ast_files [] | |||
| 		'__new_array_with_default', | ||||
| 		'__new_array_with_array_default', | ||||
| 		'new_array_from_c_array', | ||||
| 		'v_fixed_index', | ||||
| 		'memdup', | ||||
| 		'vstrlen', | ||||
| 		'__as_cast', | ||||
|  |  | |||
|  | @ -1,3 +1,7 @@ | |||
| // .out file:
 | ||||
| // To test a panic, remove everything after the long `===` line
 | ||||
| // You can also remove the line with 'line:' e.g. for a builtin fn
 | ||||
| 
 | ||||
| import os | ||||
| import term | ||||
| import v.util | ||||
|  | @ -52,7 +56,7 @@ fn test_all() { | |||
| 			n_found := normalize_panic_message(found, vroot) | ||||
| 			n_expected := normalize_panic_message(expected, vroot) | ||||
| 			if found.contains('================ V panic ================') { | ||||
| 				if n_found.contains(n_expected) { | ||||
| 				if n_found.starts_with(n_expected) { | ||||
| 					println(term.green('OK (panic)')) | ||||
| 					continue | ||||
| 				} else { | ||||
|  | @ -86,7 +90,10 @@ fn test_all() { | |||
| 
 | ||||
| fn normalize_panic_message(message string, vroot string) string { | ||||
| 	mut msg := message.all_before('=========================================') | ||||
| 	msg = msg.replace(vroot + os.path_separator, '') | ||||
| 	// change windows to nix path
 | ||||
| 	s := vroot.replace(os.path_separator, '/') | ||||
| 	// remove vroot
 | ||||
| 	msg = msg.replace(s + '/', '') | ||||
| 	msg = msg.trim_space() | ||||
| 	return msg | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,6 @@ | |||
| 1 | ||||
| ================ V panic ================ | ||||
|    module: builtin | ||||
|  function: v_fixed_index() | ||||
|   message: fixed array index out of range (index: 2, len: 2) | ||||
|      file: vlib/builtin/builtin.c.v | ||||
|  | @ -0,0 +1,4 @@ | |||
| a := [1,2]! | ||||
| println(a[0]) | ||||
| i := 2 | ||||
| _ = a[i] | ||||
|  | @ -0,0 +1,5 @@ | |||
| ================ V panic ================ | ||||
|    module: builtin | ||||
|  function: slice() | ||||
|   message: array.slice: slice bounds out of range (3 >= 2) | ||||
|      file: vlib/builtin/array.v | ||||
|  | @ -0,0 +1,3 @@ | |||
| a := [1,2]! | ||||
| i := 3 | ||||
| _ = a[i..i] | ||||
		Loading…
	
		Reference in New Issue