Skip to content

Commit 0f78dcc

Browse files
BridgeARaddaleax
authored andcommitted
util: escape C1 control characters and switch to hex format
C1 control characters will from now on also be escaped to prevent altering the terminal behavior. Fixes: #29450 PR-URL: #29826 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
1 parent 5e4d99a commit 0f78dcc

File tree

3 files changed

+31
-25
lines changed

3 files changed

+31
-25
lines changed

lib/internal/util/inspect.js

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ const kArrayType = 1;
115115
const kArrayExtrasType = 2;
116116

117117
/* eslint-disable no-control-regex */
118-
const strEscapeSequencesRegExp = /[\x00-\x1f\x27\x5c]/;
119-
const strEscapeSequencesReplacer = /[\x00-\x1f\x27\x5c]/g;
120-
const strEscapeSequencesRegExpSingle = /[\x00-\x1f\x5c]/;
121-
const strEscapeSequencesReplacerSingle = /[\x00-\x1f\x5c]/g;
118+
const strEscapeSequencesRegExp = /[\x00-\x1f\x27\x5c\x7f-\x9f]/;
119+
const strEscapeSequencesReplacer = /[\x00-\x1f\x27\x5c\x7f-\x9f]/g;
120+
const strEscapeSequencesRegExpSingle = /[\x00-\x1f\x5c\x7f-\x9f]/;
121+
const strEscapeSequencesReplacerSingle = /[\x00-\x1f\x5c\x7f-\x9f]/g;
122122
/* eslint-enable no-control-regex */
123123

124124
const keyStrRegExp = /^[a-zA-Z_][a-zA-Z_0-9]*$/;
@@ -134,21 +134,23 @@ const kWeak = 0;
134134
const kIterator = 1;
135135
const kMapEntries = 2;
136136

137-
// Escaped special characters. Use empty strings to fill up unused entries.
137+
// Escaped control characters (plus the single quote and the backslash). Use
138+
// empty strings to fill up unused entries.
138139
const meta = [
139-
'\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004',
140-
'\\u0005', '\\u0006', '\\u0007', '\\b', '\\t',
141-
'\\n', '\\u000b', '\\f', '\\r', '\\u000e',
142-
'\\u000f', '\\u0010', '\\u0011', '\\u0012', '\\u0013',
143-
'\\u0014', '\\u0015', '\\u0016', '\\u0017', '\\u0018',
144-
'\\u0019', '\\u001a', '\\u001b', '\\u001c', '\\u001d',
145-
'\\u001e', '\\u001f', '', '', '',
146-
'', '', '', '', "\\'", '', '', '', '', '',
147-
'', '', '', '', '', '', '', '', '', '',
148-
'', '', '', '', '', '', '', '', '', '',
149-
'', '', '', '', '', '', '', '', '', '',
150-
'', '', '', '', '', '', '', '', '', '',
151-
'', '', '', '', '', '', '', '\\\\'
140+
'\\x00', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\x07', // x07
141+
'\\b', '\\t', '\\n', '\\x0B', '\\f', '\\r', '\\x0E', '\\x0F', // x0F
142+
'\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17', // x17
143+
'\\x18', '\\x19', '\\x1A', '\\x1B', '\\x1C', '\\x1D', '\\x1E', '\\x1F', // x1F
144+
'', '', '', '', '', '', '', "\\'", '', '', '', '', '', '', '', '', // x2F
145+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', // x3F
146+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', // x4F
147+
'', '', '', '', '', '', '', '', '', '', '', '', '\\\\', '', '', '', // x5F
148+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', // x6F
149+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '\\x7F', // x7F
150+
'\\x80', '\\x81', '\\x82', '\\x83', '\\x84', '\\x85', '\\x86', '\\x87', // x87
151+
'\\x88', '\\x89', '\\x8A', '\\x8B', '\\x8C', '\\x8D', '\\x8E', '\\x8F', // x8F
152+
'\\x90', '\\x91', '\\x92', '\\x93', '\\x94', '\\x95', '\\x96', '\\x97', // x97
153+
'\\x98', '\\x99', '\\x9A', '\\x9B', '\\x9C', '\\x9D', '\\x9E', '\\x9F', // x9F
152154
];
153155

154156
function getUserOptions(ctx) {
@@ -317,7 +319,10 @@ function strEscape(str) {
317319
const lastIndex = str.length;
318320
for (let i = 0; i < lastIndex; i++) {
319321
const point = str.charCodeAt(i);
320-
if (point === singleQuote || point === 92 || point < 32) {
322+
if (point === singleQuote ||
323+
point === 92 ||
324+
point < 32 ||
325+
(point > 126 && point < 160)) {
321326
if (last === i) {
322327
result += meta[point];
323328
} else {

test/parallel/test-fs-whatwg-url.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ if (common.isWindows) {
6363
code: 'ERR_INVALID_ARG_VALUE',
6464
type: TypeError,
6565
message: 'The argument \'path\' must be a string or Uint8Array without ' +
66-
'null bytes. Received \'c:\\\\tmp\\\\\\u0000test\''
66+
"null bytes. Received 'c:\\\\tmp\\\\\\x00test'"
6767
}
6868
);
6969
} else {
@@ -96,8 +96,8 @@ if (common.isWindows) {
9696
{
9797
code: 'ERR_INVALID_ARG_VALUE',
9898
type: TypeError,
99-
message: 'The argument \'path\' must be a string or Uint8Array without ' +
100-
'null bytes. Received \'/tmp/\\u0000test\''
99+
message: "The argument 'path' must be a string or Uint8Array without " +
100+
"null bytes. Received '/tmp/\\x00test'"
101101
}
102102
);
103103
}

test/parallel/test-util-inspect.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,11 @@ assert.strictEqual(
9191
new Date('2010-02-14T12:48:40+01:00').toISOString()
9292
);
9393
assert.strictEqual(util.inspect(new Date('')), (new Date('')).toString());
94-
assert.strictEqual(util.inspect('\n\u0001'), "'\\n\\u0001'");
94+
assert.strictEqual(util.inspect('\n\x01'), "'\\n\\x01'");
9595
assert.strictEqual(
96-
util.inspect(`${Array(75).fill(1)}'\n\u001d\n\u0003`),
97-
`"${Array(75).fill(1)}'\\n" +\n '\\u001d\\n' +\n '\\u0003'`
96+
util.inspect(`${Array(75).fill(1)}'\n\x1d\n\x03\x85\x7f\x7e\x9f\xa0`),
97+
// eslint-disable-next-line no-irregular-whitespace
98+
`"${Array(75).fill(1)}'\\n" +\n '\\x1D\\n' +\n '\\x03\\x85\\x7F~\\x9F '`
9899
);
99100
assert.strictEqual(util.inspect([]), '[]');
100101
assert.strictEqual(util.inspect(Object.create([])), 'Array {}');

0 commit comments

Comments
 (0)