[flang] Add length check so that memcmp() on source does not go past the end of input...
authorpeter klausler <pklausler@nvidia.com>
Mon, 9 Apr 2018 22:08:38 +0000 (15:08 -0700)
committerpeter klausler <pklausler@nvidia.com>
Mon, 9 Apr 2018 22:08:38 +0000 (15:08 -0700)
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
flang/lib/parser/token-parsers.h

index 63d98db..1a82a68 100644 (file)
@@ -147,13 +147,18 @@ public:
     return {UncheckedAdvance()};
   }
 
-  std::optional<const char *> PeekAtNextChar() {
+  std::optional<const char *> 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};
index c88fd54..d420d98 100644 (file)
@@ -615,13 +615,21 @@ constexpr struct FormDirectivesAndEmptyLines {
   using resultType = Success;
   static std::optional<Success> Parse(ParseState *state) {
     while (std::optional<const char *> 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;
       }