From dff6ea58212b902bcf867ab3a4dc23716b7cd185 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 8 Jan 2024 16:02:17 -0500 Subject: [PATCH] import fuchsia: check bounds to handle truncated traces the last record might be partially written so it's important to check bounds and dump the last record if that happens. --- import-fuchsia/src/import-fuchsia.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/import-fuchsia/src/import-fuchsia.cpp b/import-fuchsia/src/import-fuchsia.cpp index 9b4ef02a..b375273d 100644 --- a/import-fuchsia/src/import-fuchsia.cpp +++ b/import-fuchsia/src/import-fuchsia.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #ifdef _WIN32 #include @@ -70,7 +71,6 @@ struct PidTidEncoder { // A span into the main buffer struct Record { const uint64_t *p; - ; uint16_t len_word; uint64_t header; }; @@ -171,13 +171,26 @@ std::vector read_input(const char *input) { return buf; } -// read next record starting at `offset` -Record read_next_record(std::vector const &input, size_t &offset) { +// read next record starting at `offset`. Returns +// either `(ok, r)` for an in-bound record, or `(false, …)` otherwise. +std::pair read_next_record(std::vector const &input, size_t &offset) { + + // bound check +#define CHECK_BOUND(n) if ((n) > input.size()) { \ + fprintf(stderr, "warning: invalid record at offset %" PRIu64 "\n", offset); \ + return std::make_pair(false,Record{}); \ +} + + CHECK_BOUND(offset+8); + uint64_t header = *((uint64_t *)&input[offset]); uint16_t len_word = (header >> 4) & 0xfff; - Record sp{(uint64_t *)&input[offset], len_word, header}; + + CHECK_BOUND(offset + 8*len_word); + + Record r{(uint64_t *)&input[offset], len_word, header}; offset += 8 * len_word; - return sp; + return std::make_pair(true, r); } // there might be multiple processes so we allocate a pseudo-tid @@ -398,7 +411,8 @@ int main(int argc, char **argv) { #define CHECK_INIT() if (!initialized) throw TraceNotInitialized{} while (offset < buf.size()) { - Record r = read_next_record(buf, offset); + auto [ok, r] = read_next_record(buf, offset); + if (!ok) break; n_records++; uint8_t ty = r.header & 0xf;