Skip to content

Commit

Permalink
Resolve paths before comparing input/output destination (#2878)
Browse files Browse the repository at this point in the history
This fixes an issue where if you try to write to the same destination as the
input file but you are not using absolute (or the same relative path) for both
the input and output, sharp/vips might produce errors such as:

someFile.jpg: unable to open for write
unix error: No such file or directory
  • Loading branch information
rexxars authored Sep 6, 2021
1 parent afb2113 commit 52307fa
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lib/output.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

const path = require('path');
const is = require('./is');
const sharp = require('./sharp');

Expand Down Expand Up @@ -59,7 +60,7 @@ function toFile (fileOut, callback) {
let err;
if (!is.string(fileOut)) {
err = new Error('Missing output file path');
} else if (this.options.input.file === fileOut) {
} else if (is.string(this.options.input.file) && path.resolve(this.options.input.file) === path.resolve(fileOut)) {
err = new Error('Cannot use same file for input and output');
} else if (this.options.formatOut === 'input' && fileOut.toLowerCase().endsWith('.gif') && !this.constructor.format.magick.output.file) {
err = errMagickSave;
Expand Down
43 changes: 43 additions & 0 deletions test/unit/io.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const fs = require('fs');
const path = require('path');
const assert = require('assert');
const rimraf = require('rimraf');

Expand Down Expand Up @@ -316,6 +317,48 @@ describe('Input/output', function () {
});
});

it('Fail when output File is input File (relative output, absolute input)', function (done) {
const relativePath = path.relative(process.cwd(), fixtures.inputJpg);
sharp(fixtures.inputJpg).toFile(relativePath, function (err) {
assert(err instanceof Error);
assert.strictEqual('Cannot use same file for input and output', err.message);
done();
});
});

it('Fail when output File is input File via Promise (relative output, absolute input)', function (done) {
const relativePath = path.relative(process.cwd(), fixtures.inputJpg);
sharp(fixtures.inputJpg).toFile(relativePath).then(function (data) {
assert(false);
done();
}).catch(function (err) {
assert(err instanceof Error);
assert.strictEqual('Cannot use same file for input and output', err.message);
done();
});
});

it('Fail when output File is input File (relative input, absolute output)', function (done) {
const relativePath = path.relative(process.cwd(), fixtures.inputJpg);
sharp(relativePath).toFile(fixtures.inputJpg, function (err) {
assert(err instanceof Error);
assert.strictEqual('Cannot use same file for input and output', err.message);
done();
});
});

it('Fail when output File is input File via Promise (relative input, absolute output)', function (done) {
const relativePath = path.relative(process.cwd(), fixtures.inputJpg);
sharp(relativePath).toFile(fixtures.inputJpg).then(function (data) {
assert(false);
done();
}).catch(function (err) {
assert(err instanceof Error);
assert.strictEqual('Cannot use same file for input and output', err.message);
done();
});
});

it('Fail when output File is empty', function (done) {
sharp(fixtures.inputJpg).toFile('', function (err) {
assert(err instanceof Error);
Expand Down

0 comments on commit 52307fa

Please sign in to comment.