Skip to content
Open
Show file tree
Hide file tree
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
142 changes: 102 additions & 40 deletions src/njs_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -675,43 +675,43 @@ njs_value_buffer_get(njs_vm_t *vm, njs_value_t *value, njs_str_t *dst)


static njs_int_t
njs_buffer_array_range(njs_vm_t *vm, njs_typed_array_t *array,
const njs_value_t *start, const njs_value_t *end, const char *name,
uint8_t **out_start, uint8_t **out_end)
njs_buffer_range_index(njs_vm_t *vm, const njs_value_t *value, uint64_t *out)
{
uint64_t num_start, num_end;
njs_int_t ret;
njs_array_buffer_t *buffer;
if (njs_is_defined(value)) {
return njs_value_to_index(vm, njs_value_arg(value), out);
}

num_start = 0;
return NJS_OK;
}

if (njs_slow_path(njs_is_detached_buffer(array->buffer))) {
njs_type_error(vm, "detached buffer");
return NJS_ERROR;
}

if (njs_is_defined(start)) {
ret = njs_value_to_index(vm, njs_value_arg(start), &num_start);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
}
/*
* Applies an already-resolved [num_start, num_end) range to array. The
* array's buffer is fetched, and revalidated as non-detached, here, after
* any njs_value_to_index() coercion of the range bounds performed by the
* caller, so that a user callback triggered by that coercion cannot leave
* the resulting out_start and out_end pointing into a buffer that has
* since been detached. has_end == 0 means "use array->byte_length" for
* num_end.
*/

static njs_int_t
njs_buffer_apply_range(njs_vm_t *vm, njs_typed_array_t *array,
uint64_t num_start, uint64_t num_end, njs_bool_t has_end,
njs_bool_t writable, const char *name, uint8_t **out_start,
uint8_t **out_end)
{
njs_array_buffer_t *buffer;

if (num_start > array->byte_length) {
njs_range_error(vm, "\"%sStart\" is out of range: %L", name, num_start);
return NJS_ERROR;
}

num_end = array->byte_length;
if (!has_end) {
num_end = array->byte_length;

if (njs_is_defined(end)) {
ret = njs_value_to_index(vm, njs_value_arg(end), &num_end);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
}

if (num_end > array->byte_length) {
} else if (num_end > array->byte_length) {
njs_range_error(vm, "\"%sEnd\" is out of range: %L", name, num_end);
return NJS_ERROR;
}
Expand All @@ -720,7 +720,21 @@ njs_buffer_array_range(njs_vm_t *vm, njs_typed_array_t *array,
num_end = num_start;
}

buffer = njs_typed_array_buffer(array);
if (writable) {
buffer = njs_typed_array_writable(vm, array);
if (njs_slow_path(buffer == NULL)) {
return NJS_ERROR;
}

} else {
buffer = array->buffer;

if (njs_slow_path(njs_is_detached_buffer(buffer))) {
njs_type_error(vm, "detached buffer");
return NJS_ERROR;
}
}

*out_start = &buffer->u.u8[array->offset + num_start];
*out_end = &buffer->u.u8[array->offset + num_end];

Expand All @@ -736,6 +750,8 @@ njs_buffer_compare_array(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2,
{
size_t size, src_size, trg_size;
uint8_t *src, *src_end, *trg, *trg_end;
uint64_t num_target_start, num_target_end, num_source_start,
num_source_end;
njs_int_t ret;
njs_typed_array_t *source, *target;

Expand All @@ -749,13 +765,41 @@ njs_buffer_compare_array(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2,
return NJS_ERROR;
}

ret = njs_buffer_array_range(vm, target, target_start, target_end, "target",
num_target_start = 0;
num_target_end = 0;

ret = njs_buffer_range_index(vm, target_start, &num_target_start);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

ret = njs_buffer_range_index(vm, target_end, &num_target_end);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

num_source_start = 0;
num_source_end = 0;

ret = njs_buffer_range_index(vm, source_start, &num_source_start);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

ret = njs_buffer_range_index(vm, source_end, &num_source_end);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

ret = njs_buffer_apply_range(vm, target, num_target_start, num_target_end,
njs_is_defined(target_end), 0, "target",
&trg, &trg_end);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

ret = njs_buffer_array_range(vm, source, source_start, source_end, "source",
ret = njs_buffer_apply_range(vm, source, num_source_start, num_source_end,
njs_is_defined(source_end), 0, "source",
&src, &src_end);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
Expand Down Expand Up @@ -2022,10 +2066,10 @@ njs_buffer_prototype_copy(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
{
size_t size;
uint8_t *src, *src_end, *trg, *trg_end;
uint64_t num_target_start, num_source_start, num_source_end;
njs_int_t ret;
njs_value_t *val1, *val2;
njs_value_t *val1, *val2, *source_end_arg;
njs_typed_array_t *source, *target;
njs_array_buffer_t *buffer;

val1 = njs_argument(args, 0);
val2 = njs_arg(args, nargs, 1);
Expand All @@ -2040,23 +2084,41 @@ njs_buffer_prototype_copy(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
return NJS_ERROR;
}

ret = njs_buffer_array_range(vm, target, njs_arg(args, nargs, 2),
&njs_value_undefined, "target", &trg,
&trg_end);
num_target_start = 0;

ret = njs_buffer_range_index(vm, njs_arg(args, nargs, 2),
&num_target_start);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

ret = njs_buffer_array_range(vm, source, njs_arg(args, nargs, 3),
njs_arg(args, nargs, 4), "source", &src,
&src_end);
num_source_start = 0;
num_source_end = 0;

ret = njs_buffer_range_index(vm, njs_arg(args, nargs, 3),
&num_source_start);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

buffer = njs_typed_array_writable(vm, target);
if (njs_slow_path(buffer == NULL)) {
return NJS_ERROR;
source_end_arg = njs_arg(args, nargs, 4);

ret = njs_buffer_range_index(vm, source_end_arg, &num_source_end);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

ret = njs_buffer_apply_range(vm, target, num_target_start, 0, 0, 1,
"target", &trg, &trg_end);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

ret = njs_buffer_apply_range(vm, source, num_source_start, num_source_end,
njs_is_defined(source_end_arg), 0, "source",
&src, &src_end);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}

size = njs_min(trg_end - trg, src_end - src);
Expand Down
Loading
Loading