From f02bbca0c790f7751bbf7501e781ac5bee518c45 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 15 Jan 2022 18:31:35 -0700 Subject: [PATCH] parser: fix reading past end of buffer --- common/entdata.cc | 2 +- common/parser.cc | 4 ++-- include/common/parser.hh | 5 ++++- qbsp/map.cc | 6 ++++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/common/entdata.cc b/common/entdata.cc index 914f88aa..61eab9e3 100644 --- a/common/entdata.cc +++ b/common/entdata.cc @@ -117,7 +117,7 @@ keyvalues_t::iterator entdict_t::end() std::vector EntData_Parse(const std::string &entdata) { std::vector result; - parser_t parser(entdata.data()); + parser_t parser(entdata.data(), entdata.data() + entdata.size()); /* go through all the entities */ while (1) { diff --git a/common/parser.cc b/common/parser.cc index 0a3b43f1..f9745d17 100644 --- a/common/parser.cc +++ b/common/parser.cc @@ -37,8 +37,8 @@ bool parser_t::parse_token(parseflags flags) skipspace: /* skip space */ - while (*pos <= 32) { - if (!*pos) { + while (at_end() || *pos <= 32) { + if (at_end() || !*pos) { if (flags & PARSE_OPTIONAL) return false; if (flags & PARSE_SAMELINE) diff --git a/include/common/parser.hh b/include/common/parser.hh index 0b5fc5c7..ca5232bc 100644 --- a/include/common/parser.hh +++ b/include/common/parser.hh @@ -43,12 +43,15 @@ inline auto untie(const std::tuple &tuple) struct parser_t { const char *pos; + const char *end; uint32_t linenum = 1; std::string token; - parser_t(const char *data) : pos(data) { } + parser_t(const char *data, const char *in_end) : pos(data), end(in_end) { } bool parse_token(parseflags flags = PARSE_NORMAL); auto state() { return std::tie(pos, linenum); } + + bool at_end() const { return pos >= end; }; }; diff --git a/qbsp/map.cc b/qbsp/map.cc index d66ef9fa..75b70a52 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -1847,7 +1847,8 @@ mapentity_t LoadExternalMap(const char *filename) FError("Couldn't load external map file \"{}.\"\n", filename); } - parser_t parser(reinterpret_cast(file->data())); + const char *begin = reinterpret_cast(file->data()); + parser_t parser(begin, begin + file->size()); // parse the worldspawn if (!ParseEntity(parser, &dest)) { @@ -1895,7 +1896,8 @@ void LoadMapFile(void) return; } - parser_t parser(reinterpret_cast(file->data())); + const char *begin = reinterpret_cast(file->data()); + parser_t parser(begin, begin + file->size()); for (int i = 0;; i++) { mapentity_t &entity = map.entities.emplace_back();