Automattic / node-canvas

Node canvas is a Cairo backed Canvas implementation for NodeJS.
10.22k stars 1.17k forks source link

Nodejs crash when processing PDF file with pdfjs #2349

Open jhpage opened 9 months ago

jhpage commented 9 months ago

Issue

nodejs crashes when processing a PDF file containing an image. Enclosed the PDF file too.

The crash is as follows:

FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal.
 1: 0xb85bc0 node::Abort() [node]
 2: 0xa94749 node::OOMErrorHandler(char const*, bool) [node]
 3: 0xd66a2a v8::Utils::ReportApiFailure(char const*, char const*) [node]
 4: 0x7ffba0dd5d4d Context2d::CreateImageData(Nan::FunctionCallbackInfo<v8::Value> const&) [/home/sridhar/devl/node-canvas/node_modules/canvas/build/Release/canvas.node]
 5: 0x7ffba0dcc3d3  [/home/sridhar/devl/node-canvas/node_modules/canvas/build/Release/canvas.node]
 6: 0xdc4e00  [node]
 7: 0xdc633f v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [node]
 8: 0x1705c39  [node]

Steps to Reproduce

The following sample is taken from pdfjs example here: customized a bit to output an SVG file.

import Canvas from "canvas";
import fs from "fs";
import { getDocument } from "pdfjs-dist/legacy/build/pdf.mjs";

class NodeCanvasFactory {
    create(width, height) {
    const canvas = Canvas.createCanvas(width, height, 'svg');
    const context = canvas.getContext("2d");
    return {
        canvas,
        context,
    };
    }
    reset(canvasAndContext, width, height) {
    canvasAndContext.canvas.width = width;
    canvasAndContext.canvas.height = height;
    }
    destroy(canvasAndContext) {
    canvasAndContext.canvas.width = 0;
    canvasAndContext.canvas.height = 0;
    canvasAndContext.canvas = null;
    canvasAndContext.context = null;
    }
}

// Some PDFs need external cmaps.
const CMAP_URL = "./node_modules/pdfjs-dist/cmaps/";
const CMAP_PACKED = true;

// Where the standard fonts are located.
const STANDARD_FONT_DATA_URL = "./node_modules/pdfjs-dist/standard_fonts/";

const canvasFactory = new NodeCanvasFactory();

// Loading file from file system into typed array.
const pdfPath = "./sample.pdf"
const data = new Uint8Array(fs.readFileSync(pdfPath));

// Load the PDF file.
const loadingTask = getDocument({
    data,
    cMapUrl: CMAP_URL,
    cMapPacked: CMAP_PACKED,
    standardFontDataUrl: STANDARD_FONT_DATA_URL,
    canvasFactory,
});

try {
    const pdfDocument = await loadingTask.promise;
    const page = await pdfDocument.getPage(1);
    const viewport = page.getViewport({ scale: 1.0 });
    const canvasAndContext = canvasFactory.create(
    viewport.width,
    viewport.height
    );
    const renderContext = {
    canvasContext: canvasAndContext.context,
    viewport,
    };
    const renderTask = page.render(renderContext);
    await renderTask.promise;
    const image = canvasAndContext.canvas.toBuffer();
    fs.writeFile("output.svg", image, function (error) {
    if (error) {
        console.error("Error: " + error);
    } else {
        console.log("Finished converting first page of PDF to output.svg");
    }
    });
    page.cleanup();
} catch (reason) {
    console.log(reason);
}

Your Environment

zbjornson commented 9 months ago

That error appears to say that Node ran out of memory while creating a large ImageData object. If you can trim your example down to figure out which line it crashes at (or step through it line-by-line with a debugger until it crashes), that would be useful.

jhpage commented 9 months ago

I don't think it is related to out-of-memory errors.

jhpage commented 9 months ago

By using console.log() statements, I have been able to track down the error to these lines in the code:

const renderTask = page.render(renderContext);
await renderTask.promise;

Statements after the await are not executed, instead I get a crash.

jhpage commented 9 months ago

I tried logging an issue with pdfjs thinking it may be related, but they closed the issue saying it seems to be node-canvas related since the code works fine in firefox.

pathikrit commented 9 months ago

I am having the same issue on a 1 page PDF!

PDF

NewIndianExpress.pdf

Error

FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal
 1: 0x1001713ac node::Abort() [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
 2: 0x1001714a4 node::OOMErrorHandler(char const*, v8::OOMDetails const&) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
 3: 0x1002ce954 v8::api_internal::ToLocalEmpty() [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
 4: 0x10571417c Context2d::CreateImageData(Nan::FunctionCallbackInfo<v8::Value> const&) [/Users/pbhowmick/workspace/newswall/node_modules/canvas/build/Release/canvas.node]
 5: 0x1057020a0 Nan::imp::FunctionCallbackWrapper(v8::FunctionCallbackInfo<v8::Value> const&) [/Users/pbhowmick/workspace/newswall/node_modules/canvas/build/Release/canvas.node]
 6: 0x1003378f0 v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, unsigned long*, int) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
 7: 0x100337060 v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
 8: 0x100bb33ec Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
 9: 0x100b30064 Builtins_InterpreterEntryTrampoline [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
10: 0x100b30064 Builtins_InterpreterEntryTrampoline [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
11: 0x100b30064 Builtins_InterpreterEntryTrampoline [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
12: 0x105bc9aec 
13: 0x105c4ffe8 
14: 0x100c06e38 Builtins_PromiseFulfillReactionJob [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
15: 0x100b56834 Builtins_RunMicrotasks [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
16: 0x100b2e3c4 Builtins_JSRunMicrotasksEntry [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
17: 0x100404ca4 v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
18: 0x100405194 v8::internal::(anonymous namespace)::InvokeWithTryCatch(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
19: 0x100405370 v8::internal::Execution::TryRunMicrotasks(v8::internal::Isolate*, v8::internal::MicrotaskQueue*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
20: 0x10042d2e8 v8::internal::MicrotaskQueue::RunMicrotasks(v8::internal::Isolate*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
21: 0x10042db84 v8::internal::MicrotaskQueue::PerformCheckpoint(v8::Isolate*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
22: 0x1000b8c50 node::InternalCallbackScope::Close() [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
23: 0x1000b8fd8 node::InternalMakeCallback(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
24: 0x1000cf06c node::AsyncWrap::MakeCallback(v8::Local<v8::Function>, int, v8::Local<v8::Value>*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
25: 0x100176c8c node::fs::FSReqCallback::Resolve(v8::Local<v8::Value>) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
26: 0x1001773b8 node::fs::AfterNoArgs(uv_fs_s*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
27: 0x10016d5e0 node::MakeLibuvRequestCallback<uv_fs_s, void (*)(uv_fs_s*)>::Wrapper(uv_fs_s*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
28: 0x100b0b550 uv__work_done [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
29: 0x100b0ecf8 uv__async_io [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
30: 0x100b2149c uv__io_poll [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
31: 0x100b0f1c8 uv_run [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
32: 0x1000b96f4 node::SpinEventLoopInternal(node::Environment*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
33: 0x1001ae484 node::NodeMainInstance::Run() [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
34: 0x10013e5d8 node::LoadSnapshotDataAndRun(node::SnapshotData const**, node::InitializationResultImpl const*) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
35: 0x10013e840 node::Start(int, char**) [/Users/pbhowmick/.nvm/versions/node/v19.9.0/bin/node]
36: 0x18bac10e0 start [/usr/lib/dyld]