Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/dotenv/env_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,9 @@ struct Parser<'a> {
value_buffer: &'a mut Vec<u8>,
}

const WHITESPACE_CHARS: &[u8] = b"\t\x0B\x0C \xA0\n\r";
// Input is UTF-8, so this set must be ASCII-only: 0xA0 is a continuation byte
// there (NBSP is C2 A0), and trimming it byte-wise corrupts multi-byte sequences.
const WHITESPACE_CHARS: &[u8] = b"\t\x0B\x0C \n\r";

impl<'a> Parser<'a> {
fn skip_line(&mut self) {
Expand Down
19 changes: 19 additions & 0 deletions test/cli/run/env.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
isWindows,
tempDirWithFiles,
} from "harness";
import { parseEnv } from "node:util";
import path from "path";

function bunRunWithoutTrim(file: string, env?: Record<string, string>) {
Expand Down Expand Up @@ -372,6 +373,24 @@ test(".env space edgecase (issue #411)", () => {
expect(stdout).toBe("[A B]");
});

test(".env does not byte-trim 0xA0 out of UTF-8 values", () => {
// U+0920 DEVANAGARI LETTER TTHA encodes as E0 A4 A0 (trailing 0xA0)
// U+00A0 NO-BREAK SPACE encodes as C2 A0; Node.js preserves it verbatim.
expect(parseEnv("A=x\u0920\nB=\u00A0x\u00A0\nC=\u00A0\nD= x \n")).toEqual({
A: "x\u0920",
B: "\u00A0x\u00A0",
C: "\u00A0",
D: "x",
});

const dir = tempDirWithFiles("dotenv-utf8-nbsp", {
".env": "A=x\u0920\nB=\u00A0x\u00A0\n",
"index.ts": "console.log(JSON.stringify({ A: process.env.A, B: process.env.B }));",
});
const { stdout } = bunRun(`${dir}/index.ts`);
expect(JSON.parse(stdout)).toEqual({ A: "x\u0920", B: "\u00A0x\u00A0" });
});

test(".env special characters 1 (issue #2823)", () => {
const dir = tempDirWithFiles("dotenv-issue-2823", {
".env": 'A="a$t"\nC=`c\\$v`',
Expand Down
Loading