From 590afc60daffeddfe79a2bcaf6b2fcaac924c90d Mon Sep 17 00:00:00 2001 From: peter klausler Date: Mon, 9 Apr 2018 15:08:38 -0700 Subject: [PATCH] [flang] Add length check so that memcmp() on source does not go past the end of input and make valgrind complain. Original-commit: flang-compiler/f18@475e9db03548bd45ae81201561579de3119d6587 Reviewed-on: https://github.com/flang-compiler/f18/pull/48 Tree-same-pre-rewrite: false --- flang/lib/parser/parse-state.h | 7 ++++++- flang/lib/parser/token-parsers.h | 18 +++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/flang/lib/parser/parse-state.h b/flang/lib/parser/parse-state.h index 63d98db..1a82a68 100644 --- a/flang/lib/parser/parse-state.h +++ b/flang/lib/parser/parse-state.h @@ -147,13 +147,18 @@ public: return {UncheckedAdvance()}; } - std::optional PeekAtNextChar() { + std::optional PeekAtNextChar() const { if (p_ >= limit_) { return {}; } return {p_}; } + std::size_t BytesRemaining() const { + std::size_t remain = limit_ - p_; + return remain; + } + private: // Text remaining to be parsed const char *p_{nullptr}, *limit_{nullptr}; diff --git a/flang/lib/parser/token-parsers.h b/flang/lib/parser/token-parsers.h index c88fd54..d420d98 100644 --- a/flang/lib/parser/token-parsers.h +++ b/flang/lib/parser/token-parsers.h @@ -615,13 +615,21 @@ constexpr struct FormDirectivesAndEmptyLines { using resultType = Success; static std::optional Parse(ParseState *state) { while (std::optional at{state->PeekAtNextChar()}) { - static const char fixed[] = "!dir$ fixed\n", free[] = "!dir$ free\n"; if (**at == '\n') { state->UncheckedAdvance(); - } else if (std::memcmp(*at, fixed, sizeof fixed - 1) == 0) { - state->set_inFixedForm(true).UncheckedAdvance(sizeof fixed - 1); - } else if (std::memcmp(*at, free, sizeof free - 1) == 0) { - state->set_inFixedForm(false).UncheckedAdvance(sizeof free - 1); + } else if (**at == '!') { + static const char fixed[] = "!dir$ fixed\n", free[] = "!dir$ free\n"; + static constexpr std::size_t fixedBytes{sizeof fixed - 1}; + static constexpr std::size_t freeBytes{sizeof free - 1}; + std::size_t remain{state->BytesRemaining()}; + if (remain >= fixedBytes && std::memcmp(*at, fixed, fixedBytes) == 0) { + state->set_inFixedForm(true).UncheckedAdvance(fixedBytes); + } else if (remain >= freeBytes && + std::memcmp(*at, free, freeBytes) == 0) { + state->set_inFixedForm(false).UncheckedAdvance(freeBytes); + } else { + break; + } } else { break; } -- 2.7.4