Automattic / node-canvas

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

Segmentation Fault in PutImageData #1972

Open jasperchua99 opened 2 years ago

jasperchua99 commented 2 years ago

Issue or Feature

PID 14986 received SIGSEGV for address: 0x9bf00803 /home/pi/Discord-Bot/node_modules/segfault-handler/build/Release/segfault-handler.node(+0x25f4)[0xf72df5f4] /lib/arm-linux-gnueabihf/libc.so.6(__default_rt_sa_restorer+0x0)[0xf7b28db0] /home/pi/Discord-Bot/node_modules/canvas/build/Release/canvas.node(_ZN9Context2d12PutImageDataERKN3Nan20FunctionCallbackInfoIN2v85ValueEEE+0x684)[0xf4c331b4] /home/pi/Discord-Bot/node_modules/canvas/build/Release/canvas.node(+0x23db4)[0xf4c29db4]

Steps to Reproduce

const canvas = new Canvas.createCanvas();

    const ctx = canvas.getContext('2d');

    ctx.canvas.width = 1024;
    ctx.canvas.height = 576;

    const base = await Canvas.loadImage(avatarURL);

    var hRatio = canvas.width / base.width;
    var vRatio = canvas.height / base.height;
    var ratio = Math.min(hRatio, vRatio);
    var centerShift_x = (canvas.width - base.width * ratio) / 2;
    var centerShift_y = (canvas.height - base.height * ratio) / 2;

    ctx.drawImage(base, 0, 0, base.width, base.height, // source rectangle
      centerShift_x, centerShift_y, base.width * ratio - 10, base.height * ratio - 10); // destination rectangle

    var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    var pix = imgData.data;
    //convert the image into a silhouette
    for (var i = 0, n = pix.length; i < n; i += 4) {
      //set red to 0
      pix[i] = 0;
      //set green to 0
      pix[i + 1] = 0;
      //set blue to 0
      pix[i + 2] = 0;
      //retain the alpha value
      pix[i + 3] = pix[i + 3];
    }
    await ctx.putImageData(imgData, 0, 0);

canvas.toBuffer()

Your Environment

jasperchua99 commented 2 years ago

if it helps as well, im using Node v17.4.0.

goffincedric commented 2 years ago

Also experiencing this issue. Running on: Raspbian 11 (bullseye) raspberrypi3 armv7l using Node v16.13.1.

goffincedric commented 2 years ago

Small update, I have been tinkering with the source code of the PutImageData function in CanvasRenderingContext2d.cc to pinpoint the exact place where the segmentation fault. Turns out the code in the provided above only fails when const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); is called.

This can be proven by first executing the code without the offending line:

import Canvas from 'canvas';
const canvas = new Canvas.createCanvas(2000, 200);
const ctx = canvas.getContext('2d');
for (let i = 0; i < 100; i++) {
const base = await Canvas.loadImage('assets/b_d.png');
const hRatio = canvas.width / base.width;
const vRatio = canvas.height / base.height;
const ratio = Math.min(hRatio, vRatio);
const centerShift_x = (canvas.width - base.width * ratio) / 2;
const centerShift_y = (canvas.height - base.height * ratio) / 2;

ctx.drawImage(base, 0, 0, base.width, base.height, // source rectangle
        centerShift_x, centerShift_y, base.width * ratio - 10, base.height * ratio - 10); // destination rectangle

//const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
await new Promise(resolve => setTimeout(() => resolve(), 10));
}

Run the code again but uncomment //const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);. The code will fail with either a message:

This is all speculation as I am not a c++ dev. Just some small clues to start from maybe.

goffincedric commented 2 years ago

Upgraded my raspberry pi to a 64bit version of debian. This segfault doesn't occur anymore with both my personal project and with the provided code above. The problem doesn't seem to be an ARM issue, more like a 32bit architecture issue.

TheRedXD commented 1 year ago

I get the same issue, here is part of the backtrace:

#0  0x00007f768c2017c8 in Context2d::PutImageData(Nan::FunctionCallbackInfo<v8::Value> const&) ()
   from /home/thered/Desktop/ai-assistant/node_modules/.pnpm/canvas@2.11.2/node_modules/canvas/build/Release/canvas.node
No symbol table info available.
#1  0x00007f768c1fa3d3 in Nan::imp::FunctionCallbackWrapper(v8::FunctionCallbackInfo<v8::Value> const&) ()
   from /home/thered/Desktop/ai-assistant/node_modules/.pnpm/canvas@2.11.2/node_modules/canvas/build/Release/canvas.node
No symbol table info available.
#2  0x0000000000dbaa30 in 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::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) ()
No symbol table info available.
#3  0x0000000000dbbf6f in v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) ()
No symbol table info available.
#4  0x00000000016fb7b9 in Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit ()
Version of NodeJS: v18.16.0
System Kernel: Linux
OS: Pop!_OS 22.04 LTS
OS Type: 64-bit
Output of uname -a: Linux pop-os 5.17.5-76051705-generic #202204271406~1655476786~22.04~62dd706 SMP PREEMPT Fri Jun 17 16 x86_64 x86_64 x86_64 GNU/Linux

System Hardware:

CPU: AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx (8) @ 2.300GHz
GPU: AMD ATI Radeon Vega Series / Radeon Vega Mobile Series
GPU: NVIDIA GeForce RTX 2060 Mobile
Memory: 13978MiB (16GB)
Host: TUF Gaming FX505DV_FX505DV 1.0

This issue seems to happen randomly? At times it works, and at other times it SEGFAULTS. I use ctx.putImageData in my code, will probably replace it with something else because it isn't working