Corrupt PNG throws uncatchable error
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
- #1788 @afonsojanu による — マージされずにクローズ
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 55/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- javascript, node.js
- 領域
- backend
調査の方向性
doc.image エントリーポイントから開始し、PNG の透明度処理の経路を png-js decodePixels まで追跡します。そこでは非同期の zlib エラーが再スローされます。issue に記載された壊れた PNG のケースを再現し、プロセスをクラッシュさせることなく、失敗が呼び出し元で捕捉可能になるか、document のエラーパスを通じて発行されることを確認します。
索引モデルが issue の本文から書いたものです。
説明
Bug Report
Description
When embedding a PNG which IDAT data is corrupted or truncated, pdfkit crashes the process with an uncaught exception. The error cannot be caught by the caller: wrapping inside try/catch does not work, and no error event is emitted on the document.
The root cause is in the png-js dependency. In decodePixels, it calls zlib.inflate and re-throws the error from inside the asynchronous callback:
decodePixels(fn) {
return zlib.inflate(this.imgData, (err, data) => {
if (err) {
throw err;
}
...
This happens specifically when pdfkit needs to access the raw pixels, for example for PNGs with transparency.
How to reproduce
Create a script as follows:
const PDFDocument = require('pdfkit');
const fs = require('fs');
const zlib = require('zlib');
// Construct a PNG which IDAT payload is not a valid zlib stream
function chunk(type, data) {
const len = Buffer.alloc(4);
len.writeUInt32BE(data.length);
const body = Buffer.concat([Buffer.from(type, 'ascii'), data]);
const crc = Buffer.alloc(4);
crc.writeUInt32BE(zlib.crc32 ? zlib.crc32(body) : 0);
return Buffer.concat([len, body, crc]);
}
const ihdr = Buffer.alloc(13);
ihdr.writeUInt32BE(1, 0); // width
ihdr.writeUInt32BE(1, 4); // height
ihdr[8] = 8; // bit depth
ihdr[9] = 6; // color type: RGBA (forces pdfkit to decode pixels)
const corruptPng = Buffer.concat([
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
chunk('IHDR', ihdr),
chunk('IDAT', Buffer.from([0xde, 0xad, 0xbe, 0xef])), // garbage deflate data
chunk('IEND', Buffer.alloc(0)),
]);
const doc = new PDFDocument();
doc.pipe(fs.createWriteStream('/dev/null'));
try {
doc.image(corruptPng, 0, 0);
doc.end();
} catch (err) {
console.log('Caught:', err.message); // never reached
}
Result: despite the try-catch, the Node process crashes.
Environment: pdfkit 0.19.1, png-js 1.1.0, Node.js 22
Suggested fix
The cleanest option is probably to replace png-js with a maintained decoder such as fast-png, which decodes synchronously, throws normal catchable errors, and seems to be more actively maintained.
Alternatively, fixing png-js itself would be fine too, of course, and I think that the fix would be small. However, this exact problem has already been reported in that repo many years ago (foliojs/png.js#14) and the repository shows little activity, so a fix on the pdfkit side seems more realistic.
- 主要言語
- JavaScript
- スター
- 10.7k
- フォーク
- 1.2k
- 平均マージ
- 21時間 41分
- マージ済み PR(30日)
- 27
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
foliojs/pdfkit のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
foliojs/pdfkit#1804 · コメント 5 件 ·
メンテナーはふだん 1 日以内に返信
-
PDFKit crashes when providing fonts as Buffer in table対応中かも @ykw9263 が 133 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
foliojs/pdfkit#1743 · コメント 13 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
foliojs/pdfkit#1635 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
foliojs/pdfkit#1512 · コメント 1 件 · リアクション 2 件 ·
メンテナーはふだん 1 日以内に返信
-
Upgrade codemirrorオープン
難易度 3/5 1〜2日 初心者へのやさしさ 45/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 73/100
hugomrdias/playwright-test#753 ·
メンテナーはふだん 1 日以内に返信
-
bug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
KonstantinStarovoytov/kitden#21 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
guybedford/es-module-shims#556 ·
-
app ernst:4-klein
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
NewspeedyNL/PidLane#683 ·
メンテナーはふだん 1 日以内に返信