Skip to content

[Security] readFileSync allocates unbounded memory - OOM and int32 overflow #2

Description

@JkarVN

Summary

readFileSync in src/module/node/fs/fs.cpp (L376-440) reads the entire file into memory without any size limit. Additionally, there is an integer overflow when casting size (int64_t) to int32_t at line 429.

Impact

  1. OOM crash: Reading a multi-GB file causes unchecked heap allocation, crashing the process.
  2. Undefined behavior / truncation: If size > INT32_MAX, the cast on L429 (static_cast<int32_t>(size)) produces a negative value passed to v8::String::NewFromUtf8, which is undefined behavior.

Vulnerable Code

// L421-438
int64_t size = file.tellg();  // No upper bound check
file.seekg(0, std::ios::beg);

if (encoding == "utf8") {
    std::string content(size, '\0');   // Allocates 'size' bytes unchecked
    if (file.read(&content[0], size)) {
        args.GetReturnValue().Set(
            v8::String::NewFromUtf8(
                p_isolate, content.c_str(), v8::NewStringType::kNormal,
                static_cast<int32_t>(size))  // int64 -> int32 overflow if size > 2GB
                .ToLocalChecked());
    }
} else {
    v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(p_isolate, size);  // Allocates 'size' bytes unchecked
}

Suggested Fix

static constexpr int64_t kMaxReadFileSize = 512LL * 1024 * 1024; // 512 MB

int64_t size = file.tellg();
if (size < 0 || size > kMaxReadFileSize) {
    p_isolate->ThrowException(
        v8::String::NewFromUtf8Literal(p_isolate, "Error: File too large"));
    return;
}
// Now safe to cast to int32_t (size <= 512MB < INT32_MAX)

Affected Files

  • src/module/node/fs/fs.cpp L421-438

Severity

Major - Any file path passing isPathSafe pointing to a large file (e.g., disk image, log file) can exhaust process memory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity vulnerability

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions