diff options
Diffstat (limited to 'thirdparty/tourist/analysis/src')
| -rw-r--r-- | thirdparty/tourist/analysis/src/dispatcher.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/thirdparty/tourist/analysis/src/dispatcher.cpp b/thirdparty/tourist/analysis/src/dispatcher.cpp index e7ea4a37e..a667b0c37 100644 --- a/thirdparty/tourist/analysis/src/dispatcher.cpp +++ b/thirdparty/tourist/analysis/src/dispatcher.cpp @@ -2,6 +2,8 @@ #include <foundation/scheduler.h> #include <trace/trace.h> +#include <constants.h> + //------------------------------------------------------------------------------ void Dispatcher::add_analyzer(Analyzer& analyzer) { @@ -20,6 +22,12 @@ void Dispatcher::on_new_type(const Type* type) if (outline->hash != type_hash) continue; + // Sum of non-array field sizes — the byte length of event.data that + // scalar field reads index into. + uint32 event_size = 0; + for (uint32 i = 0, n = type->get_field_count(); i < n; ++i) + event_size += type->get_field(i).get_size(); + for (uint32 i = 0; i < type->get_field_count(); ++i) { auto [field_name, field] = type->get_field_info(i); @@ -30,8 +38,23 @@ void Dispatcher::on_new_type(const Type* type) if (f->hash != field_hash) continue; - f->type_info = uint8(field.get_type_info()); - f->offset = int16(field.get_offset()); + uint32 type_info = field.get_type_info(); + uint32 offset = field.get_offset(); + + // Scalar fields are read via event.data + offset. Validate the + // offset and element size against event_size so a malicious + // utrace can't make Outline::Field memcpy past the event + // payload. Array/string fields are read from aux and ignore + // offset. + if ((type_info & TYPE_INFO_CAT_ARRAY) == 0) + { + uint32 element_size = 1u << (type_info & TYPE_INFO_SIZE_MASK); + if (offset > event_size || element_size > event_size - offset) + break; + } + + f->type_info = uint8(type_info); + f->offset = int16(offset); f->set = 1; f->index = i; break; |