Skip to content

Commit 3b224a2

Browse files
deepview-autofixclaudeChALkeR
authored
fix: validate low surrogate in encodeString
When a high surrogate (0xD800–0xDBFF) was not followed by a valid low surrogate, the encoder still combined the next code unit into a supplementary code point, producing invalid UTF-8 percent-encoded output and swallowing the following character. Validate that the second code unit is a low surrogate (0xDC00–0xDFFF) and throw "URI malformed" otherwise, matching the behaviour for an unpaired trailing high surrogate. Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: DeepView Autofix <276251120+deepview-autofix@users.noreply.github.com> Co-Authored-By: Nikita Skovoroda <chalkerx@gmail.com> Signed-off-by: Nikita Skovoroda <chalkerx@gmail.com>
1 parent 9dcbaf2 commit 3b224a2

File tree

2 files changed

+12
-2
lines changed

2 files changed

+12
-2
lines changed

lib/internals/querystring.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,16 @@ function encodeString(str) {
7878
throw new Error("URI malformed");
7979
}
8080

81-
const c2 = str.charCodeAt(i) & 0x3ff;
81+
const c2 = str.charCodeAt(i);
82+
83+
// The second code unit must be a low surrogate (0xDC00–0xDFFF),
84+
// otherwise the input is not a well-formed UTF-16 string.
85+
if ((c2 & 0xfc00) !== 0xdc00) {
86+
throw new Error("URI malformed");
87+
}
8288

8389
lastPos = i + 1;
84-
c = 0x10000 + (((c & 0x3ff) << 10) | c2);
90+
c = 0x10000 + (((c & 0x3ff) << 10) | (c2 & 0x3ff));
8591
out +=
8692
hexTable[0xf0 | (c >> 18)] +
8793
hexTable[0x80 | ((c >> 12) & 0x3f)] +

test/stringify.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ test("invalid surrogate pair should throw", () => {
7676
assert.throws(() => qs.stringify({ foo: "\udc00" }), "URI malformed");
7777
});
7878

79+
test("high surrogate followed by non-surrogate should throw", () => {
80+
assert.throws(() => qs.stringify({ foo: "a\ud800b" }), "URI malformed");
81+
});
82+
7983
test("should omit nested values", () => {
8084
const f = qs.stringify({
8185
a: "b",

0 commit comments

Comments
 (0)