aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/tourist/analysis/src/dispatcher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/tourist/analysis/src/dispatcher.cpp')
-rw-r--r--thirdparty/tourist/analysis/src/dispatcher.cpp27
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;