github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/executor/_include/flatbuffers/registry.h (about)

     1  /*
     2   * Copyright 2017 Google Inc. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #ifndef FLATBUFFERS_REGISTRY_H_
    18  #define FLATBUFFERS_REGISTRY_H_
    19  
    20  #include "flatbuffers/base.h"
    21  #include "flatbuffers/idl.h"
    22  
    23  namespace flatbuffers {
    24  
    25  // Convenience class to easily parse or generate text for arbitrary FlatBuffers.
    26  // Simply pre-populate it with all schema filenames that may be in use, and
    27  // This class will look them up using the file_identifier declared in the
    28  // schema.
    29  class Registry {
    30   public:
    31    // Call this for all schemas that may be in use. The identifier has
    32    // a function in the generated code, e.g. MonsterIdentifier().
    33    void Register(const char *file_identifier, const char *schema_path) {
    34      Schema schema;
    35      schema.path_ = schema_path;
    36      schemas_[file_identifier] = schema;
    37    }
    38  
    39    // Generate text from an arbitrary FlatBuffer by looking up its
    40    // file_identifier in the registry.
    41    bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest) {
    42      // Get the identifier out of the buffer.
    43      // If the buffer is truncated, exit.
    44      if (len < sizeof(uoffset_t) + kFileIdentifierLength) {
    45        lasterror_ = "buffer truncated";
    46        return false;
    47      }
    48      std::string ident(
    49          reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
    50          kFileIdentifierLength);
    51      // Load and parse the schema.
    52      Parser parser;
    53      if (!LoadSchema(ident, &parser)) return false;
    54      // Now we're ready to generate text.
    55      auto err = GenText(parser, flatbuf, dest);
    56      if (err) {
    57        lasterror_ =
    58            "unable to generate text for FlatBuffer binary: " + std::string(err);
    59        return false;
    60      }
    61      return true;
    62    }
    63  
    64    // Converts a binary buffer to text using one of the schemas in the registry,
    65    // use the file_identifier to indicate which.
    66    // If DetachedBuffer::data() is null then parsing failed.
    67    DetachedBuffer TextToFlatBuffer(const char *text,
    68                                    const char *file_identifier) {
    69      // Load and parse the schema.
    70      Parser parser;
    71      if (!LoadSchema(file_identifier, &parser)) return DetachedBuffer();
    72      // Parse the text.
    73      if (!parser.Parse(text)) {
    74        lasterror_ = parser.error_;
    75        return DetachedBuffer();
    76      }
    77      // We have a valid FlatBuffer. Detach it from the builder and return.
    78      return parser.builder_.Release();
    79    }
    80  
    81    // Modify any parsing / output options used by the other functions.
    82    void SetOptions(const IDLOptions &opts) { opts_ = opts; }
    83  
    84    // If schemas used contain include statements, call this function for every
    85    // directory the parser should search them for.
    86    void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }
    87  
    88    // Returns a human readable error if any of the above functions fail.
    89    const std::string &GetLastError() { return lasterror_; }
    90  
    91   private:
    92    bool LoadSchema(const std::string &ident, Parser *parser) {
    93      // Find the schema, if not, exit.
    94      auto it = schemas_.find(ident);
    95      if (it == schemas_.end()) {
    96        // Don't attach the identifier, since it may not be human readable.
    97        lasterror_ = "identifier for this buffer not in the registry";
    98        return false;
    99      }
   100      auto &schema = it->second;
   101      // Load the schema from disk. If not, exit.
   102      std::string schematext;
   103      if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
   104        lasterror_ = "could not load schema: " + schema.path_;
   105        return false;
   106      }
   107      // Parse schema.
   108      parser->opts = opts_;
   109      if (!parser->Parse(schematext.c_str(), include_paths_.data(),
   110                         schema.path_.c_str())) {
   111        lasterror_ = parser->error_;
   112        return false;
   113      }
   114      return true;
   115    }
   116  
   117    struct Schema {
   118      std::string path_;
   119      // TODO(wvo) optionally cache schema file or parsed schema here.
   120    };
   121  
   122    std::string lasterror_;
   123    IDLOptions opts_;
   124    std::vector<const char *> include_paths_;
   125    std::map<std::string, Schema> schemas_;
   126  };
   127  
   128  }  // namespace flatbuffers
   129  
   130  #endif  // FLATBUFFERS_REGISTRY_H_