Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add limits on sampling factors #106

Merged
merged 2 commits into from Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/decoder.js
Expand Up @@ -576,7 +576,9 @@ var JpegImage = (function jpegImage() {
return array;
}
function prepareComponents(frame) {
var maxH = 0, maxV = 0;
// According to the JPEG standard, the sampling factor must be between 1 and 4
// See https://github.com/libjpeg-turbo/libjpeg-turbo/blob/9abeff46d87bd201a952e276f3e4339556a403a3/libjpeg.txt#L1138-L1146
var maxH = 1, maxV = 1;
patrickhulce marked this conversation as resolved.
Show resolved Hide resolved
var component, componentId;
for (componentId in frame.components) {
if (frame.components.hasOwnProperty(componentId)) {
Expand Down Expand Up @@ -745,6 +747,11 @@ var JpegImage = (function jpegImage() {
var h = data[offset + 1] >> 4;
var v = data[offset + 1] & 15;
var qId = data[offset + 2];

if ( h <= 0 || v <= 0 ) {
throw new Error('Invalid sampling factor, expected values above 0');
patrickhulce marked this conversation as resolved.
Show resolved Hide resolved
}

frame.componentsOrder.push(componentId);
frame.components[componentId] = {
h: h,
Expand Down
16 changes: 12 additions & 4 deletions test/index.js
Expand Up @@ -7,10 +7,12 @@ function fixture(name) {
return fs.readFileSync(path.join(__dirname, 'fixtures', name));
}

const SUPER_LARGE_JPEG_BASE64 =
'/9j/wJ39sP//DlKWvX+7xPlXkJa9f7v8DoDVAAD//zb6QAEAI2cBv3P/r4ADpX8Jf14AAAAAgCPE+VeQlr1/uwCAAAAVALNOjAGP2lIS';
const SUPER_LARGE_JPEG_BASE64 = '/9j/wfFRBf//BdgC/9p/2P/E4d4=';
patrickhulce marked this conversation as resolved.
Show resolved Hide resolved

const SUPER_LARGE_RESOLUTION_JPEG_BASE64 = '/9j/wfFR2PDh3g==';

const SUPER_LARGE_JPEG_BUFFER = Buffer.from(SUPER_LARGE_JPEG_BASE64, 'base64');
const SUPER_LARGE_RESOLUTION_JPEG_BUFFER = Buffer.from(SUPER_LARGE_RESOLUTION_JPEG_BASE64, 'base64');

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

// See https://github.com/eugeneware/jpeg-js/issues/53
it('should limit resolution exposure', function () {
expect(() => jpeg.decode(SUPER_LARGE_JPEG_BUFFER)).toThrow(
'maxResolutionInMP limit exceeded by 141MP',
expect(() => jpeg.decode(SUPER_LARGE_RESOLUTION_JPEG_BUFFER)).toThrow(
patrickhulce marked this conversation as resolved.
Show resolved Hide resolved
'maxResolutionInMP limit exceeded by 3405MP',
);
});

Expand All @@ -288,3 +290,9 @@ it('should limit memory exposure', function () {
var jpegData = fixture('grumpycat.jpg');
expect(() => jpeg.decode(jpegData)).not.toThrow();
}, 30000);

// See https://github.com/jpeg-js/jpeg-js/issues/105
it('invalid sampling factor should error out', function () {
expect(() => jpeg.decode(Buffer.from('/9j/wfFR2AD/UdgA/9r/3g==', 'base64')).toThrow(
'Invalid sampling factor, expected values above 0'))
});