From c5e74408f9786219f6b44400dcf2098ab9cc78fb Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 7 May 2011 02:46:20 -0400 Subject: [PATCH] Add out-of-bound checks Signed-off-by: Mathieu Desnoyers --- converter/babeltrace-lib.c | 34 ++++++++++---- formats/ctf-text/types/array.c | 6 ++- formats/ctf-text/types/enum.c | 9 ++-- formats/ctf-text/types/float.c | 5 +- formats/ctf-text/types/integer.c | 5 +- formats/ctf-text/types/sequence.c | 6 ++- formats/ctf-text/types/string.c | 7 +-- formats/ctf-text/types/struct.c | 6 ++- formats/ctf-text/types/variant.c | 4 +- formats/ctf/ctf.c | 10 ++-- formats/ctf/types/array.c | 4 +- formats/ctf/types/enum.c | 12 +++-- formats/ctf/types/float.c | 71 +++++++++++++++++++++-------- formats/ctf/types/integer.c | 34 ++++++++++---- formats/ctf/types/sequence.c | 4 +- formats/ctf/types/string.c | 22 +++++++-- formats/ctf/types/struct.c | 4 +- formats/ctf/types/variant.c | 4 +- include/babeltrace/ctf-text/types.h | 16 +++---- include/babeltrace/ctf/types.h | 39 ++++++++++------ include/babeltrace/types.h | 16 +++---- types/array.c | 8 +++- types/sequence.c | 12 +++-- types/struct.c | 8 +++- types/variant.c | 4 +- 25 files changed, 236 insertions(+), 114 deletions(-) diff --git a/converter/babeltrace-lib.c b/converter/babeltrace-lib.c index bd0e11e1..51011e1d 100644 --- a/converter/babeltrace-lib.c +++ b/converter/babeltrace-lib.c @@ -34,6 +34,7 @@ int convert_event(struct ctf_text_stream_pos *sout, struct ctf_event *event_class; uint64_t id = 0; int len_index; + int ret; if (sin->pos.offset == -EOF) return -EOF; @@ -43,8 +44,9 @@ int convert_event(struct ctf_text_stream_pos *sout, /* Read and print event header */ if (stream_class->event_header) { - generic_rw(&sin->pos.parent, &stream_class->event_header->p); - + ret = generic_rw(&sin->pos.parent, &stream_class->event_header->p); + if (ret) + return ret; /* lookup event id */ len_index = struct_declaration_lookup_field_index(stream_class->event_header_decl, g_quark_from_static_string("id")); @@ -59,13 +61,19 @@ int convert_event(struct ctf_text_stream_pos *sout, id = defint->value._unsigned; /* set id */ } - generic_rw(&sout->parent, &stream_class->event_header->p); + ret = generic_rw(&sout->parent, &stream_class->event_header->p); + if (ret) + return ret; } /* Read and print stream-declared event context */ if (stream_class->event_context) { - generic_rw(&sin->pos.parent, &stream_class->event_context->p); - generic_rw(&sout->parent, &stream_class->event_context->p); + ret = generic_rw(&sin->pos.parent, &stream_class->event_context->p); + if (ret) + return ret; + ret = generic_rw(&sout->parent, &stream_class->event_context->p); + if (ret) + return ret; } if (id >= stream_class->events_by_id->len) { @@ -80,14 +88,22 @@ int convert_event(struct ctf_text_stream_pos *sout, /* Read and print event-declared event context */ if (event_class->context) { - generic_rw(&sin->pos.parent, &event_class->context->p); - generic_rw(&sout->parent, &event_class->context->p); + ret = generic_rw(&sin->pos.parent, &event_class->context->p); + if (ret) + return ret; + ret = generic_rw(&sout->parent, &event_class->context->p); + if (ret) + return ret; } /* Read and print event payload */ if (event_class->fields) { - generic_rw(&sin->pos.parent, &event_class->fields->p); - generic_rw(&sout->parent, &event_class->fields->p); + ret = generic_rw(&sin->pos.parent, &event_class->fields->p); + if (ret) + return ret; + ret = generic_rw(&sout->parent, &event_class->fields->p); + if (ret) + return ret; } return 0; diff --git a/formats/ctf-text/types/array.c b/formats/ctf-text/types/array.c index 1b8d6bee..b7770174 100644 --- a/formats/ctf-text/types/array.c +++ b/formats/ctf-text/types/array.c @@ -19,19 +19,21 @@ #include #include -void ctf_text_array_write(struct stream_pos *ppos, struct definition *definition) +int ctf_text_array_write(struct stream_pos *ppos, struct definition *definition) { struct ctf_text_stream_pos *pos = ctf_text_pos(ppos); + int ret; if (!pos->dummy) { print_pos_tabs(pos); fprintf(pos->fp, "[\n"); pos->depth++; } - array_rw(ppos, definition); + ret = array_rw(ppos, definition); if (!pos->dummy) { pos->depth--; print_pos_tabs(pos); fprintf(pos->fp, "]\n"); } + return ret; } diff --git a/formats/ctf-text/types/enum.c b/formats/ctf-text/types/enum.c index 198f7829..33009da7 100644 --- a/formats/ctf-text/types/enum.c +++ b/formats/ctf-text/types/enum.c @@ -20,7 +20,7 @@ #include #include -void ctf_text_enum_write(struct stream_pos *ppos, struct definition *definition) +int ctf_text_enum_write(struct stream_pos *ppos, struct definition *definition) { struct definition_enum *enum_definition = container_of(definition, struct definition_enum, p); @@ -28,14 +28,14 @@ void ctf_text_enum_write(struct stream_pos *ppos, struct definition *definition) enum_definition->integer; struct ctf_text_stream_pos *pos = ctf_text_pos(ppos); GArray *qs; - int i; + int i, ret; if (pos->dummy) - return; + return 0; print_pos_tabs(pos); fprintf(pos->fp, "("); pos->depth++; - generic_rw(ppos, &integer_definition->p); + ret = generic_rw(ppos, &integer_definition->p); print_pos_tabs(pos); qs = enum_definition->value; @@ -49,4 +49,5 @@ void ctf_text_enum_write(struct stream_pos *ppos, struct definition *definition) pos->depth--; print_pos_tabs(pos); fprintf(pos->fp, ")"); + return ret; } diff --git a/formats/ctf-text/types/float.c b/formats/ctf-text/types/float.c index e96b4dd5..1f52cb07 100644 --- a/formats/ctf-text/types/float.c +++ b/formats/ctf-text/types/float.c @@ -21,14 +21,15 @@ #include #include -void ctf_text_float_write(struct stream_pos *ppos, struct definition *definition) +int ctf_text_float_write(struct stream_pos *ppos, struct definition *definition) { struct definition_float *float_definition = container_of(definition, struct definition_float, p); struct ctf_text_stream_pos *pos = ctf_text_pos(ppos); if (pos->dummy) - return; + return 0; print_pos_tabs(pos); fprintf(pos->fp, "%Lg\n", float_definition->value); + return 0; } diff --git a/formats/ctf-text/types/integer.c b/formats/ctf-text/types/integer.c index 7dcca27e..1b565a29 100644 --- a/formats/ctf-text/types/integer.c +++ b/formats/ctf-text/types/integer.c @@ -21,7 +21,7 @@ #include #include -void ctf_text_integer_write(struct stream_pos *ppos, struct definition *definition) +int ctf_text_integer_write(struct stream_pos *ppos, struct definition *definition) { struct definition_integer *integer_definition = container_of(definition, struct definition_integer, p); @@ -30,7 +30,7 @@ void ctf_text_integer_write(struct stream_pos *ppos, struct definition *definiti struct ctf_text_stream_pos *pos = ctf_text_pos(ppos); if (pos->dummy) - return; + return 0; print_pos_tabs(pos); if (!integer_declaration->signedness) { fprintf(pos->fp, "%" PRIu64" (0x%" PRIX64 ")\n", @@ -41,4 +41,5 @@ void ctf_text_integer_write(struct stream_pos *ppos, struct definition *definiti integer_definition->value._signed, integer_definition->value._signed); } + return 0; } diff --git a/formats/ctf-text/types/sequence.c b/formats/ctf-text/types/sequence.c index a0f8260c..1e19885c 100644 --- a/formats/ctf-text/types/sequence.c +++ b/formats/ctf-text/types/sequence.c @@ -19,19 +19,21 @@ #include #include -void ctf_text_sequence_write(struct stream_pos *ppos, struct definition *definition) +int ctf_text_sequence_write(struct stream_pos *ppos, struct definition *definition) { struct ctf_text_stream_pos *pos = ctf_text_pos(ppos); + int ret; if (!pos->dummy) { print_pos_tabs(pos); fprintf(pos->fp, "[\n"); pos->depth++; } - sequence_rw(ppos, definition); + ret = sequence_rw(ppos, definition); if (!pos->dummy) { pos->depth--; print_pos_tabs(pos); fprintf(pos->fp, "]\n"); } + return ret; } diff --git a/formats/ctf-text/types/string.c b/formats/ctf-text/types/string.c index 22103ce8..d07501e5 100644 --- a/formats/ctf-text/types/string.c +++ b/formats/ctf-text/types/string.c @@ -21,8 +21,8 @@ #include /* C99 limits */ #include -void ctf_text_string_write(struct stream_pos *ppos, - struct definition *definition) +int ctf_text_string_write(struct stream_pos *ppos, + struct definition *definition) { struct definition_string *string_definition = container_of(definition, struct definition_string, p); @@ -30,7 +30,8 @@ void ctf_text_string_write(struct stream_pos *ppos, assert(string_definition->value != NULL); if (pos->dummy) - return; + return 0; print_pos_tabs(pos); fprintf(pos->fp, "%s\n", string_definition->value); + return 0; } diff --git a/formats/ctf-text/types/struct.c b/formats/ctf-text/types/struct.c index 4270a21a..760f1727 100644 --- a/formats/ctf-text/types/struct.c +++ b/formats/ctf-text/types/struct.c @@ -19,9 +19,10 @@ #include #include -void ctf_text_struct_write(struct stream_pos *ppos, struct definition *definition) +int ctf_text_struct_write(struct stream_pos *ppos, struct definition *definition) { struct ctf_text_stream_pos *pos = ctf_text_pos(ppos); + int ret; if (!pos->dummy) { if (pos->depth >= 0) { @@ -30,7 +31,7 @@ void ctf_text_struct_write(struct stream_pos *ppos, struct definition *definitio } pos->depth++; } - struct_rw(ppos, definition); + ret = struct_rw(ppos, definition); if (!pos->dummy) { pos->depth--; if (pos->depth >= 0) { @@ -38,4 +39,5 @@ void ctf_text_struct_write(struct stream_pos *ppos, struct definition *definitio fprintf(pos->fp, "}\n"); } } + return ret; } diff --git a/formats/ctf-text/types/variant.c b/formats/ctf-text/types/variant.c index 5a9df0aa..b4b72e16 100644 --- a/formats/ctf-text/types/variant.c +++ b/formats/ctf-text/types/variant.c @@ -19,7 +19,7 @@ #include #include -void ctf_text_variant_write(struct stream_pos *pos, struct definition *definition) +int ctf_text_variant_write(struct stream_pos *pos, struct definition *definition) { - variant_rw(pos, definition); + return variant_rw(pos, definition); } diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index 75d1b5eb..f57d086e 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -324,8 +324,9 @@ int create_stream_packet_index(struct ctf_trace *td, /* read and check header, set stream id (and check) */ if (td->packet_header) { /* Read packet header */ - generic_rw(&pos->parent, &td->packet_header->p); - + ret = generic_rw(&pos->parent, &td->packet_header->p); + if (ret) + return ret; len_index = struct_declaration_lookup_field_index(td->packet_header->declaration, g_quark_from_static_string("magic")); if (len_index >= 0) { struct definition_integer *defint; @@ -409,8 +410,9 @@ int create_stream_packet_index(struct ctf_trace *td, if (stream->packet_context) { /* Read packet context */ - generic_rw(&pos->parent, &stream->packet_context->p); - + ret = generic_rw(&pos->parent, &stream->packet_context->p); + if (ret) + return ret; /* read content size from header */ len_index = struct_declaration_lookup_field_index(stream->packet_context->declaration, g_quark_from_static_string("content_size")); if (len_index >= 0) { diff --git a/formats/ctf/types/array.c b/formats/ctf/types/array.c index aa3ffcf0..3fd0ad42 100644 --- a/formats/ctf/types/array.c +++ b/formats/ctf/types/array.c @@ -18,7 +18,7 @@ #include -void ctf_array_rw(struct stream_pos *pos, struct definition *definition) +int ctf_array_rw(struct stream_pos *pos, struct definition *definition) { - array_rw(pos, definition); + return array_rw(pos, definition); } diff --git a/formats/ctf/types/enum.c b/formats/ctf/types/enum.c index 153c82bd..f8fc9e57 100644 --- a/formats/ctf/types/enum.c +++ b/formats/ctf/types/enum.c @@ -20,7 +20,7 @@ #include #include -void ctf_enum_read(struct stream_pos *ppos, struct definition *definition) +int ctf_enum_read(struct stream_pos *ppos, struct definition *definition) { struct definition_enum *enum_definition = container_of(definition, struct definition_enum, p); @@ -31,8 +31,11 @@ void ctf_enum_read(struct stream_pos *ppos, struct definition *definition) const struct declaration_integer *integer_declaration = integer_definition->declaration; GArray *qs; + int ret; - ctf_integer_read(ppos, &integer_definition->p); + ret = ctf_integer_read(ppos, &integer_definition->p); + if (ret) + return ret; if (!integer_declaration->signedness) qs = enum_uint_to_quark_set(enum_declaration, integer_definition->value._unsigned); @@ -44,14 +47,15 @@ void ctf_enum_read(struct stream_pos *ppos, struct definition *definition) if (enum_definition->value) g_array_unref(enum_definition->value); enum_definition->value = qs; + return 0; } -void ctf_enum_write(struct stream_pos *pos, struct definition *definition) +int ctf_enum_write(struct stream_pos *pos, struct definition *definition) { struct definition_enum *enum_definition = container_of(definition, struct definition_enum, p); struct definition_integer *integer_definition = enum_definition->integer; - ctf_integer_write(pos, &integer_definition->p); + return ctf_integer_write(pos, &integer_definition->p); } diff --git a/formats/ctf/types/float.c b/formats/ctf/types/float.c index 8bb3f743..c494ee82 100644 --- a/formats/ctf/types/float.c +++ b/formats/ctf/types/float.c @@ -70,20 +70,34 @@ struct pos_len { size_t sign_start, exp_start, mantissa_start, len; }; -void _ctf_float_copy(struct stream_pos *destp, - struct definition_float *dest_definition, - struct stream_pos *srcp, - const struct definition_float *src_definition) +int _ctf_float_copy(struct stream_pos *destp, + struct definition_float *dest_definition, + struct stream_pos *srcp, + const struct definition_float *src_definition) { + int ret; + /* Read */ if (src_definition->declaration->byte_order == LITTLE_ENDIAN) { - ctf_integer_read(srcp, &src_definition->mantissa->p); - ctf_integer_read(srcp, &src_definition->exp->p); - ctf_integer_read(srcp, &src_definition->sign->p); + ret = ctf_integer_read(srcp, &src_definition->mantissa->p); + if (ret) + return ret; + ret = ctf_integer_read(srcp, &src_definition->exp->p); + if (ret) + return ret; + ret = ctf_integer_read(srcp, &src_definition->sign->p); + if (ret) + return ret; } else { - ctf_integer_read(srcp, &src_definition->sign->p); - ctf_integer_read(srcp, &src_definition->exp->p); - ctf_integer_read(srcp, &src_definition->mantissa->p); + ret = ctf_integer_read(srcp, &src_definition->sign->p); + if (ret) + return ret; + ret = ctf_integer_read(srcp, &src_definition->exp->p); + if (ret) + return ret; + ret = ctf_integer_read(srcp, &src_definition->mantissa->p); + if (ret) + return ret; } dest_definition->mantissa->value._unsigned = @@ -95,17 +109,30 @@ void _ctf_float_copy(struct stream_pos *destp, /* Write */ if (dest_definition->declaration->byte_order == LITTLE_ENDIAN) { - ctf_integer_write(destp, &dest_definition->mantissa->p); - ctf_integer_write(destp, &dest_definition->exp->p); - ctf_integer_write(destp, &dest_definition->sign->p); + ret = ctf_integer_write(destp, &dest_definition->mantissa->p); + if (ret) + return ret; + ret = ctf_integer_write(destp, &dest_definition->exp->p); + if (ret) + return ret; + ret = ctf_integer_write(destp, &dest_definition->sign->p); + if (ret) + return ret; } else { - ctf_integer_write(destp, &dest_definition->sign->p); - ctf_integer_write(destp, &dest_definition->exp->p); - ctf_integer_write(destp, &dest_definition->mantissa->p); + ret = ctf_integer_write(destp, &dest_definition->sign->p); + if (ret) + return ret; + ret = ctf_integer_write(destp, &dest_definition->exp->p); + if (ret) + return ret; + ret = ctf_integer_write(destp, &dest_definition->mantissa->p); + if (ret) + return ret; } + return 0; } -void ctf_float_read(struct stream_pos *ppos, struct definition *definition) +int ctf_float_read(struct stream_pos *ppos, struct definition *definition) { struct definition_float *float_definition = container_of(definition, struct definition_float, p); @@ -119,17 +146,19 @@ void ctf_float_read(struct stream_pos *ppos, struct definition *definition) struct definition_float *tmpfloat = container_of(tmpdef, struct definition_float, p); struct ctf_stream_pos destp; + int ret; ctf_init_pos(&destp, -1, O_WRONLY); destp.base = (char *) u.bits; ctf_align_pos(pos, float_declaration->p.alignment); - _ctf_float_copy(&destp.parent, tmpfloat, ppos, float_definition); + ret = _ctf_float_copy(&destp.parent, tmpfloat, ppos, float_definition); float_definition->value = u.v; definition_unref(tmpdef); + return ret; } -void ctf_float_write(struct stream_pos *ppos, struct definition *definition) +int ctf_float_write(struct stream_pos *ppos, struct definition *definition) { struct definition_float *float_definition = container_of(definition, struct definition_float, p); @@ -143,14 +172,16 @@ void ctf_float_write(struct stream_pos *ppos, struct definition *definition) struct definition_float *tmpfloat = container_of(tmpdef, struct definition_float, p); struct ctf_stream_pos srcp; + int ret; ctf_init_pos(&srcp, -1, O_RDONLY); srcp.base = (char *) u.bits; u.v = float_definition->value; ctf_align_pos(pos, float_declaration->p.alignment); - _ctf_float_copy(ppos, float_definition, &srcp.parent, tmpfloat); + ret = _ctf_float_copy(ppos, float_definition, &srcp.parent, tmpfloat); definition_unref(tmpdef); + return ret; } void __attribute__((constructor)) ctf_float_init(void) diff --git a/formats/ctf/types/integer.c b/formats/ctf/types/integer.c index 3381b585..9b918954 100644 --- a/formats/ctf/types/integer.c +++ b/formats/ctf/types/integer.c @@ -29,8 +29,8 @@ */ static -void _aligned_integer_read(struct stream_pos *ppos, - struct definition *definition) +int _aligned_integer_read(struct stream_pos *ppos, + struct definition *definition) { struct definition_integer *integer_definition = container_of(definition, struct definition_integer, p); @@ -42,6 +42,9 @@ void _aligned_integer_read(struct stream_pos *ppos, ctf_align_pos(pos, integer_declaration->p.alignment); assert(!(pos->offset % CHAR_BIT)); + if (!ctf_pos_access_ok(pos, integer_declaration->len)) + return -EFAULT; + if (!integer_declaration->signedness) { switch (integer_declaration->len) { case 8: @@ -124,10 +127,11 @@ void _aligned_integer_read(struct stream_pos *ppos, } } ctf_move_pos(pos, integer_declaration->len); + return 0; } static -void _aligned_integer_write(struct stream_pos *ppos, +int _aligned_integer_write(struct stream_pos *ppos, struct definition *definition) { struct definition_integer *integer_definition = @@ -140,6 +144,9 @@ void _aligned_integer_write(struct stream_pos *ppos, ctf_align_pos(pos, integer_declaration->p.alignment); assert(!(pos->offset % CHAR_BIT)); + if (!ctf_pos_access_ok(pos, integer_declaration->len)) + return -EFAULT; + if (pos->dummy) goto end; if (!integer_declaration->signedness) { @@ -191,9 +198,10 @@ void _aligned_integer_write(struct stream_pos *ppos, } end: ctf_move_pos(pos, integer_declaration->len); + return 0; } -void ctf_integer_read(struct stream_pos *ppos, struct definition *definition) +int ctf_integer_read(struct stream_pos *ppos, struct definition *definition) { struct definition_integer *integer_definition = container_of(definition, struct definition_integer, p); @@ -203,11 +211,14 @@ void ctf_integer_read(struct stream_pos *ppos, struct definition *definition) if (!(integer_declaration->p.alignment % CHAR_BIT) && !(integer_declaration->len % CHAR_BIT)) { - _aligned_integer_read(ppos, definition); - return; + return _aligned_integer_read(ppos, definition); } ctf_align_pos(pos, integer_declaration->p.alignment); + + if (!ctf_pos_access_ok(pos, integer_declaration->len)) + return -EFAULT; + if (!integer_declaration->signedness) { if (integer_declaration->byte_order == LITTLE_ENDIAN) bt_bitfield_read_le(pos->base, unsigned long, @@ -228,9 +239,10 @@ void ctf_integer_read(struct stream_pos *ppos, struct definition *definition) &integer_definition->value._signed); } ctf_move_pos(pos, integer_declaration->len); + return 0; } -void ctf_integer_write(struct stream_pos *ppos, struct definition *definition) +int ctf_integer_write(struct stream_pos *ppos, struct definition *definition) { struct definition_integer *integer_definition = container_of(definition, struct definition_integer, p); @@ -240,11 +252,14 @@ void ctf_integer_write(struct stream_pos *ppos, struct definition *definition) if (!(integer_declaration->p.alignment % CHAR_BIT) && !(integer_declaration->len % CHAR_BIT)) { - _aligned_integer_write(ppos, definition); - return; + return _aligned_integer_write(ppos, definition); } ctf_align_pos(pos, integer_declaration->p.alignment); + + if (!ctf_pos_access_ok(pos, integer_declaration->len)) + return -EFAULT; + if (pos->dummy) goto end; if (!integer_declaration->signedness) { @@ -268,4 +283,5 @@ void ctf_integer_write(struct stream_pos *ppos, struct definition *definition) } end: ctf_move_pos(pos, integer_declaration->len); + return 0; } diff --git a/formats/ctf/types/sequence.c b/formats/ctf/types/sequence.c index 1f36a49f..acd4c7c0 100644 --- a/formats/ctf/types/sequence.c +++ b/formats/ctf/types/sequence.c @@ -18,11 +18,11 @@ #include -void ctf_sequence_rw(struct stream_pos *ppos, struct definition *definition) +int ctf_sequence_rw(struct stream_pos *ppos, struct definition *definition) { struct declaration *declaration = definition->declaration; struct ctf_stream_pos *pos = ctf_pos(ppos); ctf_align_pos(pos, declaration->alignment); - sequence_rw(ppos, definition); + return sequence_rw(ppos, definition); } diff --git a/formats/ctf/types/string.c b/formats/ctf/types/string.c index 6a478abf..4ab30524 100644 --- a/formats/ctf/types/string.c +++ b/formats/ctf/types/string.c @@ -21,7 +21,7 @@ #include /* C99 limits */ #include -void ctf_string_read(struct stream_pos *ppos, struct definition *definition) +int ctf_string_read(struct stream_pos *ppos, struct definition *definition) { struct definition_string *string_definition = container_of(definition, struct definition_string, p); @@ -29,11 +29,21 @@ void ctf_string_read(struct stream_pos *ppos, struct definition *definition) string_definition->declaration; struct ctf_stream_pos *pos = ctf_pos(ppos); size_t len; + ssize_t max_len; char *srcaddr; ctf_align_pos(pos, string_declaration->p.alignment); + srcaddr = ctf_get_pos_addr(pos); - len = strlen(srcaddr) + 1; + /* Not counting \0 */ + max_len = pos->packet_size - pos->offset - 1; + if (max_len < 0) + return -EFAULT; + len = strnlen(srcaddr, max_len) + 1; /* Add \0 */ + /* Truncated string, unexpected. Trace probably corrupted. */ + if (srcaddr[len - 1] != '\0') + return -EFAULT; + if (string_definition->alloc_len < len) { string_definition->value = g_realloc(string_definition->value, len); @@ -43,9 +53,10 @@ void ctf_string_read(struct stream_pos *ppos, struct definition *definition) memcpy(string_definition->value, srcaddr, len); string_definition->len = len; ctf_move_pos(pos, len * CHAR_BIT); + return 0; } -void ctf_string_write(struct stream_pos *ppos, +int ctf_string_write(struct stream_pos *ppos, struct definition *definition) { struct definition_string *string_definition = @@ -59,10 +70,15 @@ void ctf_string_write(struct stream_pos *ppos, ctf_align_pos(pos, string_declaration->p.alignment); assert(string_definition->value != NULL); len = string_definition->len; + + if (!ctf_pos_access_ok(pos, len)) + return -EFAULT; + if (pos->dummy) goto end; destaddr = ctf_get_pos_addr(pos); memcpy(destaddr, string_definition->value, len); end: ctf_move_pos(pos, len * CHAR_BIT); + return 0; } diff --git a/formats/ctf/types/struct.c b/formats/ctf/types/struct.c index 7c0a249b..2913f4d0 100644 --- a/formats/ctf/types/struct.c +++ b/formats/ctf/types/struct.c @@ -18,11 +18,11 @@ #include -void ctf_struct_rw(struct stream_pos *ppos, struct definition *definition) +int ctf_struct_rw(struct stream_pos *ppos, struct definition *definition) { struct declaration *declaration = definition->declaration; struct ctf_stream_pos *pos = ctf_pos(ppos); ctf_align_pos(pos, declaration->alignment); - struct_rw(ppos, definition); + return struct_rw(ppos, definition); } diff --git a/formats/ctf/types/variant.c b/formats/ctf/types/variant.c index 13b97cf7..25c189dd 100644 --- a/formats/ctf/types/variant.c +++ b/formats/ctf/types/variant.c @@ -18,11 +18,11 @@ #include -void ctf_variant_rw(struct stream_pos *ppos, struct definition *definition) +int ctf_variant_rw(struct stream_pos *ppos, struct definition *definition) { struct declaration *declaration = definition->declaration; struct ctf_stream_pos *pos = ctf_pos(ppos); ctf_align_pos(pos, declaration->alignment); - variant_rw(ppos, definition); + return variant_rw(ppos, definition); } diff --git a/include/babeltrace/ctf-text/types.h b/include/babeltrace/ctf-text/types.h index 6a363a47..9e65435e 100644 --- a/include/babeltrace/ctf-text/types.h +++ b/include/babeltrace/ctf-text/types.h @@ -48,14 +48,14 @@ struct ctf_text_stream_pos *ctf_text_pos(struct stream_pos *pos) /* * Write only is supported for now. */ -void ctf_text_integer_write(struct stream_pos *pos, struct definition *definition); -void ctf_text_float_write(struct stream_pos *pos, struct definition *definition); -void ctf_text_string_write(struct stream_pos *pos, struct definition *definition); -void ctf_text_enum_write(struct stream_pos *pos, struct definition *definition); -void ctf_text_struct_write(struct stream_pos *pos, struct definition *definition); -void ctf_text_variant_write(struct stream_pos *pos, struct definition *definition); -void ctf_text_array_write(struct stream_pos *pos, struct definition *definition); -void ctf_text_sequence_write(struct stream_pos *pos, struct definition *definition); +int ctf_text_integer_write(struct stream_pos *pos, struct definition *definition); +int ctf_text_float_write(struct stream_pos *pos, struct definition *definition); +int ctf_text_string_write(struct stream_pos *pos, struct definition *definition); +int ctf_text_enum_write(struct stream_pos *pos, struct definition *definition); +int ctf_text_struct_write(struct stream_pos *pos, struct definition *definition); +int ctf_text_variant_write(struct stream_pos *pos, struct definition *definition); +int ctf_text_array_write(struct stream_pos *pos, struct definition *definition); +int ctf_text_sequence_write(struct stream_pos *pos, struct definition *definition); static inline void print_pos_tabs(struct ctf_text_stream_pos *pos) diff --git a/include/babeltrace/ctf/types.h b/include/babeltrace/ctf/types.h index 8018b5b3..e8cc97b1 100644 --- a/include/babeltrace/ctf/types.h +++ b/include/babeltrace/ctf/types.h @@ -28,7 +28,7 @@ #include #include #include - +#include struct packet_index { off_t offset; /* offset of the packet in the file, in bytes */ @@ -65,18 +65,18 @@ struct ctf_stream_pos *ctf_pos(struct stream_pos *pos) return container_of(pos, struct ctf_stream_pos, parent); } -void ctf_integer_read(struct stream_pos *pos, struct definition *definition); -void ctf_integer_write(struct stream_pos *pos, struct definition *definition); -void ctf_float_read(struct stream_pos *pos, struct definition *definition); -void ctf_float_write(struct stream_pos *pos, struct definition *definition); -void ctf_string_read(struct stream_pos *pos, struct definition *definition); -void ctf_string_write(struct stream_pos *pos, struct definition *definition); -void ctf_enum_read(struct stream_pos *pos, struct definition *definition); -void ctf_enum_write(struct stream_pos *pos, struct definition *definition); -void ctf_struct_rw(struct stream_pos *pos, struct definition *definition); -void ctf_variant_rw(struct stream_pos *pos, struct definition *definition); -void ctf_array_rw(struct stream_pos *pos, struct definition *definition); -void ctf_sequence_rw(struct stream_pos *pos, struct definition *definition); +int ctf_integer_read(struct stream_pos *pos, struct definition *definition); +int ctf_integer_write(struct stream_pos *pos, struct definition *definition); +int ctf_float_read(struct stream_pos *pos, struct definition *definition); +int ctf_float_write(struct stream_pos *pos, struct definition *definition); +int ctf_string_read(struct stream_pos *pos, struct definition *definition); +int ctf_string_write(struct stream_pos *pos, struct definition *definition); +int ctf_enum_read(struct stream_pos *pos, struct definition *definition); +int ctf_enum_write(struct stream_pos *pos, struct definition *definition); +int ctf_struct_rw(struct stream_pos *pos, struct definition *definition); +int ctf_variant_rw(struct stream_pos *pos, struct definition *definition); +int ctf_array_rw(struct stream_pos *pos, struct definition *definition); +int ctf_sequence_rw(struct stream_pos *pos, struct definition *definition); void ctf_move_pos_slow(struct ctf_stream_pos *pos, size_t offset, int whence); @@ -91,6 +91,9 @@ void ctf_fini_pos(struct ctf_stream_pos *pos); static inline void ctf_move_pos(struct ctf_stream_pos *pos, size_t bit_offset) { + if (pos->offset == -EOF) + return; + if (pos->fd >= 0) { if (((pos->prot == PROT_READ) && (pos->offset + bit_offset >= pos->content_size)) @@ -148,4 +151,14 @@ void ctf_pos_pad_packet(struct ctf_stream_pos *pos) ctf_move_pos(pos, pos->packet_size - pos->offset); } +static inline +int ctf_pos_access_ok(struct ctf_stream_pos *pos, size_t bit_len) +{ + if (pos->offset == -EOF) + return 0; + if (pos->offset + bit_len > pos->packet_size) + return 0; + return 1; +} + #endif /* _BABELTRACE_CTF_TYPES_H */ diff --git a/include/babeltrace/types.h b/include/babeltrace/types.h index c44ea2dd..cb0044e0 100644 --- a/include/babeltrace/types.h +++ b/include/babeltrace/types.h @@ -103,8 +103,8 @@ struct definition { int ref; /* number of references to the definition */ }; -typedef void (*rw_dispatch)(struct stream_pos *pos, - struct definition *definition); +typedef int (*rw_dispatch)(struct stream_pos *pos, + struct definition *definition); /* Parent of per-plugin positions */ struct stream_pos { @@ -113,14 +113,14 @@ struct stream_pos { }; static inline -void generic_rw(struct stream_pos *pos, struct definition *definition) +int generic_rw(struct stream_pos *pos, struct definition *definition) { enum ctf_type_id dispatch_id = definition->declaration->id; rw_dispatch call; assert(pos->rw_table[dispatch_id] != NULL); call = pos->rw_table[dispatch_id]; - call(pos, definition); + return call(pos, definition); } /* @@ -437,7 +437,7 @@ struct_declaration_get_field_from_index(struct declaration_struct *struct_declar struct field * struct_definition_get_field_from_index(struct definition_struct *struct_definition, int index); -void struct_rw(struct stream_pos *pos, struct definition *definition); +int struct_rw(struct stream_pos *pos, struct definition *definition); /* * The tag enumeration is validated to ensure that it contains only mappings @@ -466,7 +466,7 @@ int variant_definition_set_tag(struct definition_variant *variant, * to. */ struct field *variant_get_current_field(struct definition_variant *variant); -void variant_rw(struct stream_pos *pos, struct definition *definition); +int variant_rw(struct stream_pos *pos, struct definition *definition); /* * elem_declaration passed as parameter now belongs to the array. No @@ -478,7 +478,7 @@ struct declaration_array * struct declaration_scope *parent_scope); uint64_t array_len(struct definition_array *array); struct definition *array_index(struct definition_array *array, uint64_t i); -void array_rw(struct stream_pos *pos, struct definition *definition); +int array_rw(struct stream_pos *pos, struct definition *definition); /* * int_declaration and elem_declaration passed as parameter now belong @@ -490,7 +490,7 @@ struct declaration_sequence * struct declaration_scope *parent_scope); uint64_t sequence_len(struct definition_sequence *sequence); struct definition *sequence_index(struct definition_sequence *sequence, uint64_t i); -void sequence_rw(struct stream_pos *pos, struct definition *definition); +int sequence_rw(struct stream_pos *pos, struct definition *definition); /* * in: path (dot separated), out: q (GArray of GQuark) diff --git a/types/array.c b/types/array.c index cd7b31bf..f592dba1 100644 --- a/types/array.c +++ b/types/array.c @@ -27,20 +27,24 @@ struct definition *_array_definition_new(struct declaration *declaration, static void _array_definition_free(struct definition *definition); -void array_rw(struct stream_pos *pos, struct definition *definition) +int array_rw(struct stream_pos *pos, struct definition *definition) { struct definition_array *array_definition = container_of(definition, struct definition_array, p); const struct declaration_array *array_declaration = array_definition->declaration; uint64_t i; + int ret; /* No need to align, because the first field will align itself. */ for (i = 0; i < array_declaration->len; i++) { struct definition *elem = g_array_index(array_definition->elems, struct field, i).definition; - generic_rw(pos, elem); + ret = generic_rw(pos, elem); + if (ret) + return ret; } + return 0; } static diff --git a/types/sequence.c b/types/sequence.c index 61a5b80d..965fd30a 100644 --- a/types/sequence.c +++ b/types/sequence.c @@ -31,15 +31,18 @@ struct definition *_sequence_definition_new(struct declaration *declaration, static void _sequence_definition_free(struct definition *definition); -void sequence_rw(struct stream_pos *pos, struct definition *definition) +int sequence_rw(struct stream_pos *pos, struct definition *definition) { struct definition_sequence *sequence_definition = container_of(definition, struct definition_sequence, p); const struct declaration_sequence *sequence_declaration = sequence_definition->declaration; uint64_t len, oldlen, i; + int ret; - generic_rw(pos, &sequence_definition->len->p); + ret = generic_rw(pos, &sequence_definition->len->p); + if (ret) + return ret; len = sequence_definition->len->value._unsigned; /* * Yes, large sequences could be _painfully slow_ to parse due @@ -68,8 +71,11 @@ void sequence_rw(struct stream_pos *pos, struct definition *definition) field->definition = sequence_declaration->elem->definition_new(sequence_declaration->elem, sequence_definition->scope, name, i); - generic_rw(pos, field->definition); + ret = generic_rw(pos, field->definition); + if (ret) + return ret; } + return 0; } static diff --git a/types/struct.c b/types/struct.c index 211d1b02..6e82b57f 100644 --- a/types/struct.c +++ b/types/struct.c @@ -30,17 +30,21 @@ struct definition *_struct_definition_new(struct declaration *declaration, static void _struct_definition_free(struct definition *definition); -void struct_rw(struct stream_pos *ppos, struct definition *definition) +int struct_rw(struct stream_pos *ppos, struct definition *definition) { struct definition_struct *struct_definition = container_of(definition, struct definition_struct, p); unsigned long i; + int ret; for (i = 0; i < struct_definition->fields->len; i++) { struct field *field = &g_array_index(struct_definition->fields, struct field, i); - generic_rw(ppos, field->definition); + ret = generic_rw(ppos, field->definition); + if (ret) + return ret; } + return 0; } static diff --git a/types/variant.c b/types/variant.c index 460b2fb2..2a408725 100644 --- a/types/variant.c +++ b/types/variant.c @@ -27,14 +27,14 @@ struct definition *_variant_definition_new(struct declaration *declaration, static void _variant_definition_free(struct definition *definition); -void variant_rw(struct stream_pos *ppos, struct definition *definition) +int variant_rw(struct stream_pos *ppos, struct definition *definition) { struct definition_variant *variant_definition = container_of(definition, struct definition_variant, p); struct field *field; field = variant_get_current_field(variant_definition); - generic_rw(ppos, field->definition); + return generic_rw(ppos, field->definition); } static -- 2.34.1