Skip to content

Commit

Permalink
chore(marshal): Reject strings containing characters that *should* be…
Browse files Browse the repository at this point in the history
… escaped
  • Loading branch information
gibson042 committed Jan 12, 2024
1 parent ad52be1 commit 7fcb8f5
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
4 changes: 2 additions & 2 deletions packages/marshal/src/encodePassable.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ const encodeCompactStringSuffix = str =>
* @type {(encoded: string) => string}
*/
const decodeCompactStringSuffix = encoded => {
return encoded.replace(/([!_])(.|\n)?/g, (esc, prefix, suffix) => {
return encoded.replace(/([\0-!_])(.|\n)?/g, (esc, prefix, suffix) => {
switch (esc) {
case '!_':
return ' ';
Expand All @@ -279,7 +279,7 @@ const decodeCompactStringSuffix = encoded => {
return '_';
default: {
const ch = /** @type {string} */ (suffix);
// The range of valid escapes is [(0x00+0x21)..(0x1F+0x21)], i.e.
// The range of valid `!`-escape suffixes is [(0x00+0x21)..(0x1F+0x21)], i.e.
// [0x21..0x40] (U+0021 EXCLAMATION MARK to U+0040 COMMERCIAL AT).
(prefix === '!' && suffix !== undefined && ch >= '!' && ch <= '@') ||
Fail`invalid string escape: ${q(esc)}`;
Expand Down
35 changes: 35 additions & 0 deletions packages/marshal/test/test-encodePassable.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,41 @@ test('capability encoding', t => {
t.is(encodePassableCompact(decodeAsciiPassable(dataCompact)), dataCompact);
});

test('compact string validity', t => {
t.notThrows(() => decodePassableInternal('~sa"z'));
t.notThrows(() => decodePassableInternal('~sa!!z'));
const specialEscapes = ['!_', '!|', '_@', '__'];
for (const prefix of ['!', '_']) {
for (let cp = 0; cp <= 0x7f; cp += 1) {
const esc = `${prefix}${String.fromCodePoint(cp)}`;
const tryDecode = () => decodePassableInternal(`~sa${esc}z`);
if (esc.match(/![!-@]/) || specialEscapes.includes(esc)) {
t.notThrows(tryDecode, `valid string escape: ${JSON.stringify(esc)}`);
} else {
t.throws(
tryDecode,
{ message: /invalid string escape/ },
`invalid string escape: ${JSON.stringify(esc)}`,
);
}
}
t.throws(
() => decodePassableInternal(`~sa${prefix}`),
{ message: /invalid string escape/ },
`unterminated ${JSON.stringify(prefix)} escape`,
);
}
for (let cp = 0; cp < 0x20; cp += 1) {
const ch = String.fromCodePoint(cp);
const uCode = cp.toString(16).padStart(4, '0');
t.throws(
() => decodePassableInternal(`~sa${ch}z`),
{ message: /invalid string escape/ },
`disallowed string control character: U+${uCode} ${JSON.stringify(ch)}`,
);
}
});

test('capability encoding validity constraints', t => {
const r = Remotable();
let encoding;
Expand Down

0 comments on commit 7fcb8f5

Please sign in to comment.