Skip to content

Commit 83ad26c

Browse files
authored
fix(mobile): prevent invalid HTML entities from crashing markdown (#6495)
Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>
1 parent fd51561 commit 83ad26c

2 files changed

Lines changed: 25 additions & 2 deletions

File tree

apps/mobile/modules/t3-markdown-text/src/nativeMarkdownText.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,22 @@ const EMPTY_CONTEXT: RunContext = {
7070

7171
const INLINE_HTML_TAG_PATTERN = /<\/?(?:kbd|mark|sub|sup|u)(?:\s[^>]*)?>/gi;
7272

73+
function decodeCodePoint(codePoint: number, entity: string): string {
74+
if (!Number.isInteger(codePoint) || codePoint < 0 || codePoint > 0x10ffff) {
75+
return entity;
76+
}
77+
return String.fromCodePoint(codePoint);
78+
}
79+
7380
function decodeHtmlEntitiesOnce(value: string): string {
7481
return value.replace(
7582
/&(?:#(\d+)|#x([0-9a-f]+)|amp|apos|gt|lt|nbsp|quot);/gi,
7683
(entity, decimal: string | undefined, hexadecimal: string | undefined) => {
7784
if (decimal) {
78-
return String.fromCodePoint(Number.parseInt(decimal, 10));
85+
return decodeCodePoint(Number.parseInt(decimal, 10), entity);
7986
}
8087
if (hexadecimal) {
81-
return String.fromCodePoint(Number.parseInt(hexadecimal, 16));
88+
return decodeCodePoint(Number.parseInt(hexadecimal, 16), entity);
8289
}
8390
switch (entity.toLowerCase()) {
8491
case "&amp;":

apps/mobile/src/lib/nativeMarkdownText.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,22 @@ describe("nativeMarkdownTextRuns", () => {
126126
]);
127127
});
128128

129+
it.each([
130+
["&#128512;", "😀"],
131+
["&#x1f680;", "🚀"],
132+
["&#9999999999;", "&#9999999999;"],
133+
["&#x110000;", "&#x110000;"],
134+
["&amp;#9999999999;", "&#9999999999;"],
135+
["&amp;#x110000;", "&#x110000;"],
136+
])("normalizes numeric entity %s without throwing", (content, expected) => {
137+
const node: MarkdownNode = {
138+
type: "paragraph",
139+
children: [{ type: "text", content }],
140+
};
141+
142+
expect(nativeMarkdownTextRuns(node)).toEqual([{ text: expected }]);
143+
});
144+
129145
it("reads inline content from nested text nodes", () => {
130146
const node: MarkdownNode = {
131147
type: "paragraph",

0 commit comments

Comments
 (0)