Repository: nodejs/node
File: src/node_http_parser.cc (C++)

Code before:
class StringPtrAllocator {
 public:
  // Memory impact: ~8KB per parser (66 StringPtr × 128 bytes).
  static constexpr size_t kSlabSize = 8192;

  StringPtrAllocator() { buffer_.SetLength(0); }

  // Allocate memory from the slab. Returns nullptr if full.
  char* Allocate(size_t size) {
    const size_t current = buffer_.length();
    if (current + size > kSlabSize) {
      return nullptr;
    }
    buffer_.SetLength(current + size);
    return buffer_.out() + current;
  }

  // Check if pointer is within this allocator's buffer.
  bool Contains(const char* ptr) const {
    return ptr >= buffer_.out() && ptr < buffer_.out() + buffer_.capacity();
  }
  // Reset allocator for new message.
  void Reset() { buffer_.SetLength(0); }

 private:
  MaybeStackBuffer<char, kSlabSize> buffer_;
};

struct StringPtr {
  StringPtr() = default;
  ~StringPtr() { Reset(); }

  StringPtr(const StringPtr&) = delete;
  StringPtr& operator=(const StringPtr&) = delete;

  void SetAllocator(StringPtrAllocator* allocator) { allocator_ = allocator; }

  // If str_ does not point to owned storage yet, this function makes it do
  // so. This is called at the end of each http_parser_execute() so as not
  // to leak references. See issue #2438 and test-http-parser-bad-ref.js.
  void Save() {
    if (str_ == nullptr || on_heap_ ||
        (allocator_ != nullptr && allocator_->Contains(str_))) {
      return;
    }
    // Try allocator first, fall back to heap
    if (allocator_ != nullptr) {
      char* ptr = allocator_->Allocate(size_);
      if (ptr != nullptr) {
        memcpy(ptr, str_, size_);
        str_ = ptr;

Review comment (suggestion):
We're not actually using this as a `MaybeStackBuffer` here anymore, it's basically just a std::array + length.

Nothing that needs to change but just pointing it out since `MaybeStackBuffer` typically indicates a potential external heap allocation

Code after:
class StringPtrAllocator {
 public:
  // Memory impact: ~8KB per parser (66 StringPtr × 128 bytes).
  static constexpr size_t kSlabSize = 8192;

  StringPtrAllocator() = default;

  // Allocate memory from the slab. Returns nullptr if full.
  char* TryAllocate(size_t size) {
    if (length_ + size > kSlabSize) {
      return nullptr;
    }
    char* ptr = buffer_ + length_;
    length_ += size;
    return ptr;
  }

  // Check if pointer is within this allocator's buffer.
  bool Contains(const char* ptr) const {
    return ptr >= buffer_ && ptr < buffer_ + kSlabSize;
  }

  // Reset allocator for new message.
  void Reset() { length_ = 0; }

 private:
  char buffer_[kSlabSize];
  size_t length_ = 0;
};

struct StringPtr {
  StringPtr() = default;
  ~StringPtr() { Reset(); }

  StringPtr(const StringPtr&) = delete;
  StringPtr& operator=(const StringPtr&) = delete;

  // If str_ does not point to owned storage yet, this function makes it do
  // so. This is called at the end of each http_parser_execute() so as not
  // to leak references. See issue #2438 and test-http-parser-bad-ref.js.
  void Save(StringPtrAllocator* allocator) {
    if (str_ == nullptr || on_heap_ ||
        (allocator != nullptr && allocator->Contains(str_))) {
      return;
    }
    // Try allocator first, fall back to heap
    if (allocator != nullptr) {
      char* ptr = allocator->TryAllocate(size_);
      if (ptr != nullptr) {
        memcpy(ptr, str_, size_);
        str_ = ptr;