@@ -196,7 +196,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
196196 if size == 0 {
197197 throw_ub_format ! ( "creating allocation with size 0" ) ;
198198 }
199- if i128 :: from ( size) > this. tcx . data_layout . pointer_size . signed_int_max ( ) {
199+ if size > this. max_size_of_val ( ) . bytes ( ) {
200200 throw_ub_format ! ( "creating an allocation larger than half the address space" ) ;
201201 }
202202 if let Err ( e) = Align :: from_bytes ( align) {
@@ -441,19 +441,34 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
441441 "malloc" => {
442442 let [ size] = this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
443443 let size = this. read_target_usize ( size) ?;
444- let res = this. malloc ( size, /*zero_init:*/ false ) ?;
445- this. write_pointer ( res, dest) ?;
444+ if size <= this. max_size_of_val ( ) . bytes ( ) {
445+ let res = this. malloc ( size, /*zero_init:*/ false ) ?;
446+ this. write_pointer ( res, dest) ?;
447+ } else {
448+ // If this does not fit in an isize, return null and, on Unix, set errno.
449+ if this. target_os_is_unix ( ) {
450+ let einval = this. eval_libc ( "ENOMEM" ) ;
451+ this. set_last_error ( einval) ?;
452+ }
453+ this. write_null ( dest) ?;
454+ }
446455 }
447456 "calloc" => {
448- let [ items, len ] =
457+ let [ items, elem_size ] =
449458 this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
450459 let items = this. read_target_usize ( items) ?;
451- let len = this. read_target_usize ( len) ?;
452- let size = items
453- . checked_mul ( len)
454- . ok_or_else ( || err_ub_format ! ( "overflow during calloc size computation" ) ) ?;
455- let res = this. malloc ( size, /*zero_init:*/ true ) ?;
456- this. write_pointer ( res, dest) ?;
460+ let elem_size = this. read_target_usize ( elem_size) ?;
461+ if let Some ( size) = this. compute_size_in_bytes ( Size :: from_bytes ( elem_size) , items) {
462+ let res = this. malloc ( size. bytes ( ) , /*zero_init:*/ true ) ?;
463+ this. write_pointer ( res, dest) ?;
464+ } else {
465+ // On size overflow, return null and, on Unix, set errno.
466+ if this. target_os_is_unix ( ) {
467+ let einval = this. eval_libc ( "ENOMEM" ) ;
468+ this. set_last_error ( einval) ?;
469+ }
470+ this. write_null ( dest) ?;
471+ }
457472 }
458473 "free" => {
459474 let [ ptr] = this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
@@ -465,8 +480,17 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
465480 this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
466481 let old_ptr = this. read_pointer ( old_ptr) ?;
467482 let new_size = this. read_target_usize ( new_size) ?;
468- let res = this. realloc ( old_ptr, new_size) ?;
469- this. write_pointer ( res, dest) ?;
483+ if new_size <= this. max_size_of_val ( ) . bytes ( ) {
484+ let res = this. realloc ( old_ptr, new_size) ?;
485+ this. write_pointer ( res, dest) ?;
486+ } else {
487+ // If this does not fit in an isize, return null and, on Unix, set errno.
488+ if this. target_os_is_unix ( ) {
489+ let einval = this. eval_libc ( "ENOMEM" ) ;
490+ this. set_last_error ( einval) ?;
491+ }
492+ this. write_null ( dest) ?;
493+ }
470494 }
471495
472496 // Rust allocation
0 commit comments