Skip to content

Commit

Permalink
src: safely remove the last line from dotenv
Browse files Browse the repository at this point in the history
Refs: nodejs#55925
PR-URL: nodejs#55982
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Richard Lau <[email protected]>
Reviewed-By: Juan José Arboleda <[email protected]>
  • Loading branch information
islandryu authored and nodejs-github-bot committed Dec 4, 2024
1 parent 7133c04 commit bc9dfc3
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/node_dotenv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,10 @@ void Dotenv::ParseContent(const std::string_view input) {
}

store_.insert_or_assign(std::string(key), multi_line_value);
content.remove_prefix(content.find('\n', closing_quote + 1));
auto newline = content.find('\n', closing_quote + 1);
if (newline != std::string_view::npos) {
content.remove_prefix(newline);
}
continue;
}
}
Expand Down Expand Up @@ -210,7 +213,10 @@ void Dotenv::ParseContent(const std::string_view input) {
store_.insert_or_assign(std::string(key), value);
// Select the first newline after the closing quotation mark
// since there could be newline characters inside the value.
content.remove_prefix(content.find('\n', closing_quote + 1));
auto newline = content.find('\n', closing_quote + 1);
if (newline != std::string_view::npos) {
content.remove_prefix(newline);
}
}
} else {
// Regular key value pair.
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/dotenv/no-final-newline-single-quotes.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BASIC='basic'
1 change: 1 addition & 0 deletions test/fixtures/dotenv/no-final-newline.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BASIC="basic"
22 changes: 22 additions & 0 deletions test/parallel/test-dotenv-edge-cases.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const fixtures = require('../common/fixtures');

const validEnvFilePath = '../fixtures/dotenv/valid.env';
const nodeOptionsEnvFilePath = '../fixtures/dotenv/node-options.env';
const noFinalNewlineEnvFilePath = '../fixtures/dotenv/no-final-newline.env';
const noFinalNewlineSingleQuotesEnvFilePath = '../fixtures/dotenv/no-final-newline-single-quotes.env';

describe('.env supports edge cases', () => {
it('supports multiple declarations, including optional ones', async () => {
Expand Down Expand Up @@ -148,4 +150,24 @@ describe('.env supports edge cases', () => {
assert.strictEqual(child.stderr, '');
assert.strictEqual(child.code, 0);
});

it('should handle file without a final newline', async () => {
const code = `
require('assert').strictEqual(process.env.BASIC, 'basic');
`.trim();
const child = await common.spawnPromisified(
process.execPath,
[ `--env-file=${path.resolve(__dirname, noFinalNewlineEnvFilePath)}`, '--eval', code ],
);

const SingleQuotesChild = await common.spawnPromisified(
process.execPath,
[ `--env-file=${path.resolve(__dirname, noFinalNewlineSingleQuotesEnvFilePath)}`, '--eval', code ],
);

assert.strictEqual(child.stderr, '');
assert.strictEqual(child.code, 0);
assert.strictEqual(SingleQuotesChild.stderr, '');
assert.strictEqual(SingleQuotesChild.code, 0);
});
});

0 comments on commit bc9dfc3

Please sign in to comment.