Pairs PairsUtil::toPairs()

in plugins/experimental/wasm/lib/src/pairs_util.cc [104:188]


Pairs PairsUtil::toPairs(std::string_view buffer) {
  if (buffer.data() == nullptr || buffer.size() > PROXY_WASM_HOST_PAIRS_MAX_BYTES) {
    return {};
  }

  const char *pos = buffer.data();
  const char *end = buffer.data() + buffer.size();

  // Read number of pairs.
  if (pos + sizeof(uint32_t) > end) {
    return {};
  }
  uint32_t num_pairs = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
                               contextOrEffectiveContext() != nullptr
                                   ? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
                                   : false);
  pos += sizeof(uint32_t);

  // Check if we're not going to exceed the limit.
  if (num_pairs > PROXY_WASM_HOST_PAIRS_MAX_COUNT) {
    return {};
  }
  if (pos + num_pairs * 2 * sizeof(uint32_t) > end) {
    return {};
  }

  Sizes sizes;
  sizes.resize(num_pairs);

  for (auto &s : sizes) {
    // Read name length.
    if (pos + sizeof(uint32_t) > end) {
      return {};
    }
    s.first = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
                      contextOrEffectiveContext() != nullptr
                          ? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
                          : false);
    pos += sizeof(uint32_t);

    // Read value length.
    if (pos + sizeof(uint32_t) > end) {
      return {};
    }
    s.second = wasmtoh(*reinterpret_cast<const uint32_t *>(pos),
                       contextOrEffectiveContext() != nullptr
                           ? contextOrEffectiveContext()->wasmVm()->usesWasmByteOrder()
                           : false);
    pos += sizeof(uint32_t);
  }

  Pairs pairs;
  pairs.resize(num_pairs);

  for (uint32_t i = 0; i < num_pairs; i++) {
    auto &s = sizes[i];
    auto &p = pairs[i];

    // Don't overread.
    if (pos + s.first + 1 > end) {
      return {};
    }
    p.first = std::string_view(pos, s.first);
    pos += s.first;
    if (*pos++ != '\0') { // NULL-terminated string.
      return {};
    }

    // Don't overread.
    if (pos + s.second + 1 > end) {
      return {};
    }
    p.second = std::string_view(pos, s.second);
    pos += s.second;
    if (*pos++ != '\0') { // NULL-terminated string.
      return {};
    }
  }

  if (pos != end) {
    return {};
  }

  return pairs;
}