summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/erl_bits.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/erl_bits.c')
-rw-r--r--erts/emulator/beam/erl_bits.c82
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;
}