Skip to content

Commit 9ccd35f

Browse files
authored
fix: validate sampling factors (#106)
1 parent b58cc11 commit 9ccd35f

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

lib/decoder.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,9 @@ var JpegImage = (function jpegImage() {
576576
return array;
577577
}
578578
function prepareComponents(frame) {
579-
var maxH = 0, maxV = 0;
579+
// According to the JPEG standard, the sampling factor must be between 1 and 4
580+
// See https://github.com/libjpeg-turbo/libjpeg-turbo/blob/9abeff46d87bd201a952e276f3e4339556a403a3/libjpeg.txt#L1138-L1146
581+
var maxH = 1, maxV = 1;
580582
var component, componentId;
581583
for (componentId in frame.components) {
582584
if (frame.components.hasOwnProperty(componentId)) {
@@ -745,6 +747,11 @@ var JpegImage = (function jpegImage() {
745747
var h = data[offset + 1] >> 4;
746748
var v = data[offset + 1] & 15;
747749
var qId = data[offset + 2];
750+
751+
if ( h <= 0 || v <= 0 ) {
752+
throw new Error('Invalid sampling factor, expected values above 0');
753+
}
754+
748755
frame.componentsOrder.push(componentId);
749756
frame.components[componentId] = {
750757
h: h,

test/index.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ function fixture(name) {
77
return fs.readFileSync(path.join(__dirname, 'fixtures', name));
88
}
99

10-
const SUPER_LARGE_JPEG_BASE64 =
11-
'/9j/wJ39sP//DlKWvX+7xPlXkJa9f7v8DoDVAAD//zb6QAEAI2cBv3P/r4ADpX8Jf14AAAAAgCPE+VeQlr1/uwCAAAAVALNOjAGP2lIS';
10+
const SUPER_LARGE_JPEG_BASE64 = '/9j/wfFRBf//BdgC/9p/2P/E4d4=';
11+
12+
const SUPER_LARGE_RESOLUTION_JPEG_BASE64 = '/9j/wfFR2PDh3g==';
1213

1314
const SUPER_LARGE_JPEG_BUFFER = Buffer.from(SUPER_LARGE_JPEG_BASE64, 'base64');
15+
const SUPER_LARGE_RESOLUTION_JPEG_BUFFER = Buffer.from(SUPER_LARGE_RESOLUTION_JPEG_BASE64, 'base64');
1416

1517
it('should be able read image with a bad e1 marker not preceeded by ff', function () {
1618
var jpegData = fixture('table-with-bad-e1.jpg');
@@ -274,8 +276,8 @@ it('should be able to decode large images within memory limits', () => {
274276

275277
// See https://github.com/eugeneware/jpeg-js/issues/53
276278
it('should limit resolution exposure', function () {
277-
expect(() => jpeg.decode(SUPER_LARGE_JPEG_BUFFER)).toThrow(
278-
'maxResolutionInMP limit exceeded by 141MP',
279+
expect(() => jpeg.decode(SUPER_LARGE_RESOLUTION_JPEG_BUFFER)).toThrow(
280+
'maxResolutionInMP limit exceeded by 3405MP',
279281
);
280282
});
281283

@@ -288,3 +290,9 @@ it('should limit memory exposure', function () {
288290
var jpegData = fixture('grumpycat.jpg');
289291
expect(() => jpeg.decode(jpegData)).not.toThrow();
290292
}, 30000);
293+
294+
// See https://github.com/jpeg-js/jpeg-js/issues/105
295+
it('invalid sampling factor should error out', function () {
296+
expect(() => jpeg.decode(Buffer.from('/9j/wfFR2AD/UdgA/9r/3g==', 'base64')).toThrow(
297+
'Invalid sampling factor, expected values above 0'))
298+
});

0 commit comments

Comments
 (0)