diff options
Diffstat (limited to 'erts/emulator/beam/erl_bits.c')
-rw-r--r-- | erts/emulator/beam/erl_bits.c | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c index e4dcb729f8..2fb0d26059 100644 --- a/erts/emulator/beam/erl_bits.c +++ b/erts/emulator/beam/erl_bits.c @@ -1021,10 +1021,12 @@ erts_new_bs_put_binary(Process *c_p, Eterm arg, Uint num_bits) ERL_BITS_DEFINE_STATEP(c_p); if (!is_binary(arg)) { - return 0; + c_p->fvalue = am_type; + return 0; } ERTS_GET_BINARY_BYTES(arg, bptr, bitoffs, bitsize); if (num_bits > 8*binary_size(arg)+bitsize) { + c_p->fvalue = am_short; return 0; } copy_binary_to_buffer(erts_current_bin, erts_bin_offset, bptr, bitoffs, num_bits); @@ -1098,6 +1100,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) #endif } else if (is_big(arg)) { if (big_to_double(arg, &u.f64) < 0) { + c_p->fvalue = am_no_float; return 0; } #ifdef DOUBLE_MIDDLE_ENDIAN @@ -1108,6 +1111,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) b = u.i32[1]; #endif } else { + c_p->fvalue = am_type; return 0; } } else if (num_bits == 32) { @@ -1130,6 +1134,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) } else if (is_big(arg)) { double f64; if (big_to_double(arg, &f64) < 0) { + c_p->fvalue = am_no_float; return 0; } ERTS_FP_CHECK_INIT(c_p); @@ -1137,6 +1142,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) ERTS_FP_ERROR(c_p,u.f32,;); a = u.i32; } else { + c_p->fvalue = am_type; return 0; } } else if (num_bits == 16) { @@ -1159,6 +1165,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) } else if (is_big(arg)) { double f64; if (big_to_double(arg, &f64) < 0) { + c_p->fvalue = am_no_float; return 0; } ERTS_FP_CHECK_INIT(c_p); @@ -1166,9 +1173,11 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) u.f16 = FP16_FROM_FP64(f64); a = u.i16; } else { + c_p->fvalue = am_type; return 0; } } else { + c_p->fvalue = am_invalid; return 0; } @@ -1265,6 +1274,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) #endif } else if (is_big(arg)) { if (big_to_double(arg, &f64) < 0) { + c_p->fvalue = am_no_float; return 0; } #ifdef DOUBLE_MIDDLE_ENDIAN @@ -1273,6 +1283,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) bptr = (byte *) &f64; #endif } else { + c_p->fvalue = am_type; return 0; } #ifdef DOUBLE_MIDDLE_ENDIAN @@ -1293,6 +1304,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) bptr = (byte *) &f32; } else if (is_big(arg)) { if (big_to_double(arg, &f64) < 0) { + c_p->fvalue = am_no_float; return 0; } ERTS_FP_CHECK_INIT(c_p); @@ -1300,6 +1312,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) ERTS_FP_ERROR(c_p,f32,;); bptr = (byte *) &f32; } else { + c_p->fvalue = am_type; return 0; } } else if (num_bits == 16) { @@ -1315,6 +1328,7 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) bptr = (byte *) &f16; } else if (is_big(arg)) { if (big_to_double(arg, &f64) < 0) { + c_p->fvalue = am_no_float; return 0; } ERTS_FP_CHECK_INIT(c_p); @@ -1322,9 +1336,11 @@ erts_new_bs_put_float(Process *c_p, Eterm arg, Uint num_bits, int flags) f16 = FP16_FROM_FP64(f64); bptr = (byte *) &f16; } else { + c_p->fvalue = am_type; return 0; } } else { + c_p->fvalue = am_invalid; return 0; } if (BIT_IS_MACHINE_ENDIAN(flags)) { @@ -1369,19 +1385,10 @@ void increase_proc_bin_sz(Process* p, ProcBin* pb, Uint new_size) Eterm erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, - Uint extra_words, Uint unit) + Uint extra_words, Uint unit) { - Eterm bin; /* Given binary */ - Eterm* ptr; - Eterm hdr; - ErlSubBin* sb; - ProcBin* pb; - Binary* binp; - Uint heap_need; - Uint build_size_in_bits; - Uint used_size_in_bits; Uint unsigned_bits; - ERL_BITS_DEFINE_STATEP(c_p); + Uint build_size_in_bits; /* * Check and untag the requested build size. @@ -1389,7 +1396,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, if (is_small(build_size_term)) { Sint signed_bits = signed_val(build_size_term); if (signed_bits < 0) { - goto badarg; + c_p->freason = BADARG; + return THE_NON_VALUE; } build_size_in_bits = (Uint) signed_bits; } else if (term_to_Uint(build_size_term, &unsigned_bits)) { @@ -1398,12 +1406,33 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, c_p->freason = unsigned_bits; return THE_NON_VALUE; } + return erts_bs_append_checked(c_p, reg, live, build_size_in_bits, + extra_words, unit); +} + +Eterm +erts_bs_append_checked(Process* c_p, Eterm* reg, Uint live, + Uint build_size_in_bits, Uint extra_words, + Uint unit) +{ + Eterm bin; /* Given binary */ + Eterm* ptr; + Eterm hdr; + ErlSubBin* sb; + ProcBin* pb; + Binary* binp; + Uint heap_need; + Uint used_size_in_bits; + ERL_BITS_DEFINE_STATEP(c_p); /* * Check the binary argument. */ bin = reg[live]; if (!is_boxed(bin)) { + type_error: + c_p->fvalue = am_type; + badarg: c_p->freason = BADARG; return THE_NON_VALUE; @@ -1411,7 +1440,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, ptr = boxed_val(bin); hdr = *ptr; if (!is_binary_header(hdr)) { - goto badarg; + goto type_error; } if (hdr != HEADER_SUB_BIN) { goto not_writable; @@ -1434,6 +1463,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, if (unit > 1) { if ((unit == 8 && (erts_bin_offset & 7) != 0) || (erts_bin_offset % unit) != 0) { + c_p->fvalue = am_unit; goto badarg; } } @@ -1447,6 +1477,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, } if((ERTS_UINT_MAX - build_size_in_bits) < erts_bin_offset) { + c_p->fvalue = am_size; c_p->freason = SYSTEM_LIMIT; return THE_NON_VALUE; } @@ -1526,6 +1557,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, if (unit > 1) { if ((unit == 8 && (erts_bin_offset & 7) != 0) || (erts_bin_offset % unit) != 0) { + c_p->fvalue = am_unit; goto badarg; } } @@ -1535,6 +1567,7 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, } if((ERTS_UINT_MAX - build_size_in_bits) < erts_bin_offset) { + c_p->fvalue = am_size; c_p->freason = SYSTEM_LIMIT; return THE_NON_VALUE; } @@ -1599,14 +1632,8 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term, Eterm erts_bs_private_append(Process* p, Eterm bin, Eterm build_size_term, Uint unit) { - Eterm* ptr; - ErlSubBin* sb; - ProcBin* pb; - Binary* binp; - Uint build_size_in_bits; - Uint pos_in_bits_after_build; Uint unsigned_bits; - ERL_BITS_DEFINE_STATEP(p); + Uint build_size_in_bits; /* * Check and untag the requested build size. @@ -1624,6 +1651,18 @@ erts_bs_private_append(Process* p, Eterm bin, Eterm build_size_term, Uint unit) p->freason = unsigned_bits; return THE_NON_VALUE; } + return erts_bs_private_append_checked(p, bin, build_size_in_bits, unit); +} + +Eterm +erts_bs_private_append_checked(Process* p, Eterm bin, Uint build_size_in_bits, Uint unit) +{ + Eterm* ptr; + ErlSubBin* sb; + ProcBin* pb; + Binary* binp; + Uint pos_in_bits_after_build; + ERL_BITS_DEFINE_STATEP(p); ptr = boxed_val(bin); ASSERT(*ptr == HEADER_SUB_BIN); @@ -1640,6 +1679,7 @@ erts_bs_private_append(Process* p, Eterm bin, Eterm build_size_term, Uint unit) erts_bin_offset = 8*sb->size + sb->bitsize; if((ERTS_UINT_MAX - build_size_in_bits) < erts_bin_offset) { + p->fvalue = am_size; p->freason = SYSTEM_LIMIT; return THE_NON_VALUE; } |