Skip to content

Commit

Permalink
svf_runtime: security review, part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
tempname11 committed Oct 17, 2023
1 parent 5f10c1d commit 17f511e
Show file tree
Hide file tree
Showing 12 changed files with 294 additions and 269 deletions.
55 changes: 28 additions & 27 deletions svf_runtime/src/svf_compatibility.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,8 @@ bool SVFRT_check_struct(
}
ctx->s1_struct_matches.pointer[s1_index] = s0_index;

SVFRT_RangeStructDefinition structs0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r0, ctx->s0->structs, SVF_META_StructDefinition);
SVFRT_RangeStructDefinition structs1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r1, ctx->s1->structs, SVF_META_StructDefinition);
SVFRT_RangeStructDefinition structs0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r0, ctx->s0->structs, SVF_META_StructDefinition);
SVFRT_RangeStructDefinition structs1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r1, ctx->s1->structs, SVF_META_StructDefinition);
if (!structs0.pointer || !structs1.pointer) {
// Internal error.
return false;
Expand All @@ -185,8 +185,8 @@ bool SVFRT_check_struct(
SVF_META_StructDefinition *s0 = structs0.pointer + s0_index;
SVF_META_StructDefinition *s1 = structs1.pointer + s1_index;

SVFRT_RangeFieldDefinition fields0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r0, s0->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r1, s1->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r0, s0->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r1, s1->fields, SVF_META_FieldDefinition);

if (!fields0.pointer || !fields0.pointer) {
// Internal error.
Expand All @@ -210,11 +210,11 @@ bool SVFRT_check_struct(
}

// TODO @performance: N^2
for (size_t i = 0; i < fields1.count; i++) {
for (uint32_t i = 0; i < fields1.count; i++) {
SVF_META_FieldDefinition *field1 = fields1.pointer + i;

bool found = false;
for (size_t j = 0; j < fields0.count; j++) {
for (uint32_t j = 0; j < fields0.count; j++) {
SVF_META_FieldDefinition *field0 = fields0.pointer + j;

if (field0->name_hash == field1->name_hash) {
Expand Down Expand Up @@ -278,8 +278,8 @@ bool SVFRT_check_choice(
}
ctx->s1_choice_matches.pointer[s1_index] = s0_index;

SVFRT_RangeChoiceDefinition choices0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r0, ctx->s0->choices, SVF_META_ChoiceDefinition);
SVFRT_RangeChoiceDefinition choices1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r1, ctx->s1->choices, SVF_META_ChoiceDefinition);
SVFRT_RangeChoiceDefinition choices0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r0, ctx->s0->choices, SVF_META_ChoiceDefinition);
SVFRT_RangeChoiceDefinition choices1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r1, ctx->s1->choices, SVF_META_ChoiceDefinition);
if (!choices0.pointer || !choices1.pointer) {
// Internal error.
return false;
Expand All @@ -288,8 +288,8 @@ bool SVFRT_check_choice(
SVF_META_ChoiceDefinition *c0 = choices0.pointer + s0_index;
SVF_META_ChoiceDefinition *c1 = choices1.pointer + s1_index;

SVFRT_RangeOptionDefinition options0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r0, c0->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r1, c1->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r0, c0->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r1, c1->options, SVF_META_OptionDefinition);

if (!options0.pointer || !options0.pointer) {
// Internal error.
Expand All @@ -311,11 +311,12 @@ bool SVFRT_check_choice(
return false;
}

for (size_t i = 0; i < options0.count; i++) {
// TODO @performance: N^2
for (uint32_t i = 0; i < options0.count; i++) {
SVF_META_OptionDefinition *option0 = options0.pointer + i;

bool found = false;
for (size_t j = 0; j < options1.count; j++) {
for (uint32_t j = 0; j < options1.count; j++) {
SVF_META_OptionDefinition *option1 = options1.pointer + j;

if (option0->name_hash == option1->name_hash) {
Expand Down Expand Up @@ -353,7 +354,7 @@ bool SVFRT_check_choice(
}

void SVFRT_check_compatibility(
SVFRT_CompatibilityResult *result,
SVFRT_CompatibilityResult *out_result,
SVFRT_Bytes scratch_memory,
SVFRT_Bytes schema_write,
SVFRT_Bytes schema_read,
Expand Down Expand Up @@ -403,11 +404,11 @@ void SVFRT_check_compatibility(
/*.count =*/ s1->structs.count
};

for (size_t i = 0; i < s1->structs.count; i++) {
for (uint32_t i = 0; i < s1->structs.count; i++) {
s1_struct_matches.pointer[i] = (uint32_t) (-1);
s1_struct_strides.pointer[i] = 0;
}
for (size_t i = 0; i < s1->choices.count; i++) {
for (uint32_t i = 0; i < s1->choices.count; i++) {
s1_choice_matches.pointer[i] = (uint32_t) (-1);
}

Expand All @@ -424,32 +425,32 @@ void SVFRT_check_compatibility(
};
SVFRT_CheckContext *ctx = &ctx_val;

size_t struct_index0 = (size_t) (-1);
size_t struct_index1 = (size_t) (-1);
uint32_t struct_index0 = (uint32_t) (-1);
uint32_t struct_index1 = (uint32_t) (-1);

SVFRT_RangeStructDefinition structs0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r0, ctx->s0->structs, SVF_META_StructDefinition);
SVFRT_RangeStructDefinition structs1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->r1, ctx->s1->structs, SVF_META_StructDefinition);
SVFRT_RangeStructDefinition structs0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r0, ctx->s0->structs, SVF_META_StructDefinition);
SVFRT_RangeStructDefinition structs1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->r1, ctx->s1->structs, SVF_META_StructDefinition);

if (!structs0.pointer || !structs1.pointer) {
// Internal error.
return;
}

for (size_t i = 0; i < structs0.count; i++) {
for (uint32_t i = 0; i < structs0.count; i++) {
if (structs0.pointer[i].name_hash == entry_name_hash) {
struct_index0 = i;
break;
}
}

for (size_t i = 0; i < structs1.count; i++) {
for (uint32_t i = 0; i < structs1.count; i++) {
if (structs1.pointer[i].name_hash == entry_name_hash) {
struct_index1 = i;
break;
}
}

if (struct_index0 == (size_t) (-1) || struct_index1 == (size_t) (-1)) {
if (struct_index0 == (uint32_t) (-1) || struct_index1 == (uint32_t) (-1)) {
// Internal error.
return;
}
Expand All @@ -470,9 +471,9 @@ void SVFRT_check_compatibility(
}
}

result->level = ctx->current_level;
result->struct_strides = ctx->s1_struct_strides;
result->entry_size0 = structs0.pointer[struct_index0].size;
result->entry_struct_index0 = struct_index0;
result->entry_struct_index1 = struct_index1;
out_result->level = ctx->current_level;
out_result->struct_strides = ctx->s1_struct_strides;
out_result->entry_size0 = structs0.pointer[struct_index0].size;
out_result->entry_struct_index0 = struct_index0;
out_result->entry_struct_index1 = struct_index1;
}
48 changes: 24 additions & 24 deletions svf_runtime/src/svf_conversion.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ void SVFRT_bump_type(
SVF_META_ChoiceDefinition *c0 = ctx->choices0.pointer + inner_c0_index;
SVF_META_ChoiceDefinition *c1 = ctx->choices1.pointer + inner_c1_index;

SVFRT_RangeOptionDefinition options0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->info->r0, c0->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->info->r1, c1->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->info->r0, c0->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->info->r1, c1->options, SVF_META_OptionDefinition);

if (!options0.pointer || !options1.pointer) {
ctx->internal_error = true;
Expand All @@ -209,7 +209,7 @@ void SVFRT_bump_type(
SVF_META_OptionDefinition *option0 = options0.pointer + input_tag;
SVF_META_OptionDefinition *option1 = NULL;

for (size_t i = 0; i < options1.count; i++) {
for (uint32_t i = 0; i < options1.count; i++) {
SVF_META_OptionDefinition *option = options1.pointer + i;

if (option->name_hash == option0->name_hash) {
Expand Down Expand Up @@ -265,9 +265,9 @@ void SVFRT_bump_type(
uint32_t inner_s0_index = u0->reference.type_union.defined_struct.index;
uint32_t inner_s1_index = u1->reference.type_union.defined_struct.index;

size_t inner_input_size = ctx->structs0.pointer[inner_s0_index].size;
uint32_t inner_input_size = ctx->structs0.pointer[inner_s0_index].size;

void *inner_input_data = SVFRT_from_reference(ctx->data_bytes, in_reference, inner_input_size);
void *inner_input_data = SVFRT_internal_from_reference(ctx->data_bytes, in_reference, inner_input_size);
if (!inner_input_data) {
ctx->data_error = true;
return;
Expand Down Expand Up @@ -355,13 +355,13 @@ void SVFRT_bump_type(
uint32_t inner_s1_index = u1->sequence.element_type_union.defined_struct.index;
size_t inner_size = ctx->structs0.pointer[inner_s0_index].size;

void *inner_data = SVFRT_from_sequence(ctx->data_bytes, in_sequence, inner_size);
void *inner_data = SVFRT_internal_from_sequence(ctx->data_bytes, in_sequence, inner_size);
if (!inner_data) {
ctx->data_error = true;
return;
}

for (size_t i = 0; i < in_sequence.count; i++) {
for (uint32_t i = 0; i < in_sequence.count; i++) {
SVFRT_Bytes inner_range = {
/*.pointer =*/ ((uint8_t *) inner_data) + inner_size * i,
/*.count =*/ inner_size,
Expand Down Expand Up @@ -432,8 +432,8 @@ void SVFRT_bump_struct_contents(
SVF_META_StructDefinition *s0 = ctx->structs0.pointer + s0_index;
SVF_META_StructDefinition *s1 = ctx->structs1.pointer + s1_index;

SVFRT_RangeFieldDefinition fields0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->info->r0, s0->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->info->r1, s1->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->info->r0, s0->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->info->r1, s1->fields, SVF_META_FieldDefinition);
if (!fields0.pointer || !fields1.pointer) {
ctx->internal_error = true;
return;
Expand All @@ -443,10 +443,10 @@ void SVFRT_bump_struct_contents(
// Sub-structs and choices may also contain these, so recurse over them.

// @TODO @performance: N^2.
for (size_t i = 0; i < fields0.count; i++) {
for (uint32_t i = 0; i < fields0.count; i++) {
SVF_META_FieldDefinition *field0 = fields0.pointer + i;

for (size_t j = 0; j < fields1.count; j++) {
for (uint32_t j = 0; j < fields1.count; j++) {
SVF_META_FieldDefinition *field1 = fields1.pointer + j;
if (field0->name_hash != field1->name_hash) {
continue;
Expand Down Expand Up @@ -593,15 +593,15 @@ void SVFRT_copy_concrete(

uint8_t input_tag = *input_tag_bytes.pointer;

SVFRT_RangeOptionDefinition options0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->info->r0, c0->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->info->r1, c1->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->info->r0, c0->options, SVF_META_OptionDefinition);
SVFRT_RangeOptionDefinition options1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->info->r1, c1->options, SVF_META_OptionDefinition);
if (!options0.pointer || !options1.pointer) {
ctx->internal_error = true;
return;
}

SVF_META_OptionDefinition *option0 = NULL;
for (size_t i = 0; i < options0.count; i++) {
for (uint32_t i = 0; i < options0.count; i++) {
SVF_META_OptionDefinition *option = options0.pointer + i;

if (option->index == input_tag) {
Expand All @@ -616,7 +616,7 @@ void SVFRT_copy_concrete(
}

SVF_META_OptionDefinition *option1 = NULL;
for (size_t i = 0; i < options1.count; i++) {
for (uint32_t i = 0; i < options1.count; i++) {
SVF_META_OptionDefinition *option = options1.pointer + i;

if (option->name_hash == option0->name_hash) {
Expand Down Expand Up @@ -1139,7 +1139,7 @@ void SVFRT_copy_type(
out_sequence->data_offset_complement = ~(suballocation.pointer - ctx->allocation.pointer);
out_sequence->count = in_sequence.count;

for (size_t i = 0; i < in_sequence.count; i++) {
for (uint32_t i = 0; i < in_sequence.count; i++) {
SVFRT_copy_concrete(
ctx,
recursion_depth + 1,
Expand Down Expand Up @@ -1180,8 +1180,8 @@ void SVFRT_copy_struct(
SVF_META_StructDefinition *s0 = ctx->structs0.pointer + s0_index;
SVF_META_StructDefinition *s1 = ctx->structs1.pointer + s1_index;

SVFRT_RangeFieldDefinition fields0 = SVFRT_RANGE_FROM_SEQUENCE(ctx->info->r0, s0->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields1 = SVFRT_RANGE_FROM_SEQUENCE(ctx->info->r1, s1->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->info->r0, s0->fields, SVF_META_FieldDefinition);
SVFRT_RangeFieldDefinition fields1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(ctx->info->r1, s1->fields, SVF_META_FieldDefinition);
if (!fields0.pointer || !fields0.pointer) {
ctx->internal_error = true;
return;
Expand All @@ -1190,10 +1190,10 @@ void SVFRT_copy_struct(
// Go over the intersection between s0 and s1.

// TODO @performance: N^2.
for (size_t i = 0; i < fields0.count; i++) {
for (uint32_t i = 0; i < fields0.count; i++) {
SVF_META_FieldDefinition *field0 = fields0.pointer + i;

for (size_t j = 0; j < fields1.count; j++) {
for (uint32_t j = 0; j < fields1.count; j++) {
SVF_META_FieldDefinition *field1 = fields1.pointer + j;
if (field0->name_hash != field1->name_hash) {
continue;
Expand Down Expand Up @@ -1226,10 +1226,10 @@ void SVFRT_convert_message(
SVFRT_AllocatorFn *allocator_fn,
void *allocator_ptr
) {
SVFRT_RangeStructDefinition structs0 = SVFRT_RANGE_FROM_SEQUENCE(info->r0, info->s0->structs, SVF_META_StructDefinition);
SVFRT_RangeStructDefinition structs1 = SVFRT_RANGE_FROM_SEQUENCE(info->r1, info->s1->structs, SVF_META_StructDefinition);
SVFRT_RangeChoiceDefinition choices0 = SVFRT_RANGE_FROM_SEQUENCE(info->r0, info->s0->choices, SVF_META_ChoiceDefinition);
SVFRT_RangeChoiceDefinition choices1 = SVFRT_RANGE_FROM_SEQUENCE(info->r1, info->s1->choices, SVF_META_ChoiceDefinition);
SVFRT_RangeStructDefinition structs0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(info->r0, info->s0->structs, SVF_META_StructDefinition);
SVFRT_RangeStructDefinition structs1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(info->r1, info->s1->structs, SVF_META_StructDefinition);
SVFRT_RangeChoiceDefinition choices0 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(info->r0, info->s0->choices, SVF_META_ChoiceDefinition);
SVFRT_RangeChoiceDefinition choices1 = SVFRT_INTERNAL_RANGE_FROM_SEQUENCE(info->r1, info->s1->choices, SVF_META_ChoiceDefinition);

if (0
|| !structs0.pointer
Expand Down
29 changes: 17 additions & 12 deletions svf_runtime/src/svf_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,36 @@
extern "C" {
#endif

void *SVFRT_from_reference(
void *SVFRT_internal_from_reference(
SVFRT_Bytes bytes,
SVFRT_Reference reference,
size_t type_size
uint32_t type_size
) {
uint32_t data_offset = ~reference.data_offset_complement;
if (data_offset > bytes.count) {
return NULL;
}
if (data_offset + type_size > bytes.count) {

// Prevent addition overflow by casting operands to `uint64_t` first.
if ((uint64_t) data_offset + (uint64_t) type_size > (uint64_t) bytes.count) {
return NULL;
}

return (void *) (bytes.pointer + data_offset);
}

void *SVFRT_from_sequence(
void *SVFRT_internal_from_sequence(
SVFRT_Bytes bytes,
SVFRT_Sequence sequence,
size_t type_size
uint32_t type_stride
) {
uint32_t data_offset = ~sequence.data_offset_complement;
if (data_offset > bytes.count) {
return NULL;
}
if (data_offset + sequence.count * type_size > bytes.count) {

// Prevent multiply-add overflow by casting operands to `uint64_t` first. It
// works, because `UINT64_MAX == UINT32_MAX * UINT32_MAX + UINT32_MAX + UINT32_MAX`.
uint64_t end_offset = (uint64_t) data_offset + (
(uint64_t) sequence.count * (uint64_t) type_stride
);

// Check end of the range.
if (end_offset > (uint64_t) bytes.count) {
return NULL;
}
return (void *) (bytes.pointer + data_offset);
Expand Down
Loading

0 comments on commit 17f511e

Please sign in to comment.