Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions src/libAtomVM/opcodesswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -5447,20 +5447,21 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
term bs_bin = term_get_match_state_binary(src);
avm_int_t bs_offset = term_get_match_state_offset(src);

if (unit != 8) {
TRACE("bs_get_binary2: Unsupported: unit must be 8.\n");
RAISE_ERROR(UNSUPPORTED_ATOM);
}
avm_int_t size_val = 0;
if (term_is_integer(size)) {
size_val = term_to_int(size);
size_val = term_to_int(size) * unit;
if (size_val % 8) {
TRACE("bs_get_binary2: Unsupported: size must be divisible by 8, got: %ld\n", size_val);
RAISE_ERROR(UNSUPPORTED_ATOM);
}
size_val = size_val / 8;
} else if (size == ALL_ATOM) {
size_val = term_binary_size(bs_bin) - bs_offset / 8;
} else {
TRACE("bs_get_binary2: size is neither an integer nor the atom `all`\n");
RAISE_ERROR(BADARG_ATOM);
}
if (bs_offset % unit != 0) {
if (bs_offset % 8 != 0) {
TRACE("bs_get_binary2: Unsupported. Offset on binary read must be aligned on byte boundaries.\n");
RAISE_ERROR(BADARG_ATOM);
}
Expand All @@ -5471,11 +5472,11 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)

TRACE("bs_get_binary2/7, fail=%u src=%p live=%u unit=%u\n", (unsigned) fail, (void *) bs_bin, (unsigned) live, (unsigned) unit);

if ((unsigned int) (bs_offset / unit + size_val) > term_binary_size(bs_bin)) {
if ((unsigned int) (bs_offset / 8 + size_val) > term_binary_size(bs_bin)) {
TRACE("bs_get_binary2: insufficient capacity -- bs_offset = %d, size_val = %d\n", (int) bs_offset, (int) size_val);
JUMP_TO_ADDRESS(mod->labels[fail]);
} else {
term_set_match_state_offset(src, bs_offset + size_val * unit);
term_set_match_state_offset(src, bs_offset + size_val * 8);

TRIM_LIVE_REGS(live);
// there is always room for a MAX_REG + 1 register, used as working register
Expand Down Expand Up @@ -6940,7 +6941,12 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
}
} else {
VERIFY_IS_INTEGER(size, "bs_create_bin/6", fail);
avm_int_t signed_size_value = term_to_int(size);
avm_int_t signed_size_value = term_to_int(size) * segment_unit;
if (UNLIKELY(signed_size_value % 8)) {
TRACE("bs_create_bin/6: Unsupported: size must be dvisible by 8, got: %ld\n", signed_size_value);
RAISE_ERROR(UNSUPPORTED_ATOM);
}
signed_size_value = signed_size_value / 8;
if (UNLIKELY(signed_size_value < 0)) {
if (fail == 0) {
RAISE_ERROR(BADARG_ATOM);
Expand All @@ -6957,6 +6963,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
}
}
segment_size = signed_size_value;
segment_unit = 8;
}
break;
}
Expand Down Expand Up @@ -7109,7 +7116,12 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
TRACE("bs_create_bin/6: size value less than 0: %i\n", (int) signed_size_value);
RAISE_ERROR(BADARG_ATOM);
}
size_value = (size_t) signed_size_value;
size_value = (size_t) signed_size_value * segment_unit;
if (UNLIKELY(size_value % 8)) {
TRACE("bs_create_bin/6: Unsupported: bitstring size (%d) is not evenly divisible by 8\n", (int) size_value);
RAISE_ERROR(UNSUPPORTED_ATOM);
}
size_value = size_value / 8;
if (size_value > src_size) {
if (fail == 0) {
RAISE_ERROR(BADARG_ATOM);
Expand Down
Loading