Skip to content

Commit 4d6076c

Browse files
authored
Escape HTML characters when rendering MRVA results as markdown (#1462)
1 parent 43650fd commit 4d6076c

File tree

4 files changed

+71
-8
lines changed

4 files changed

+71
-8
lines changed

extensions/ql-vscode/src/remote-queries/remote-queries-markdown-generation.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ function generateMarkdownForCodeSnippet(
138138
const codeLines = codeSnippet.text
139139
.split('\n')
140140
.map((line, index) =>
141-
highlightCodeLines(line, index + snippetStartLine, highlightedRegion)
141+
highlightAndEscapeCodeLines(line, index + snippetStartLine, highlightedRegion)
142142
);
143143

144144
// Make sure there are no extra newlines before or after the <code> block:
@@ -153,20 +153,25 @@ function generateMarkdownForCodeSnippet(
153153
return lines;
154154
}
155155

156-
function highlightCodeLines(
156+
function highlightAndEscapeCodeLines(
157157
line: string,
158158
lineNumber: number,
159159
highlightedRegion?: HighlightedRegion
160160
): string {
161161
if (!highlightedRegion || !shouldHighlightLine(lineNumber, highlightedRegion)) {
162-
return line;
162+
return escapeHtmlCharacters(line);
163163
}
164164
const partiallyHighlightedLine = parseHighlightedLine(
165165
line,
166166
lineNumber,
167167
highlightedRegion
168168
);
169-
return `${partiallyHighlightedLine.plainSection1}<strong>${partiallyHighlightedLine.highlightedSection}</strong>${partiallyHighlightedLine.plainSection2}`;
169+
170+
const plainSection1 = escapeHtmlCharacters(partiallyHighlightedLine.plainSection1);
171+
const highlightedSection = escapeHtmlCharacters(partiallyHighlightedLine.highlightedSection);
172+
const plainSection2 = escapeHtmlCharacters(partiallyHighlightedLine.plainSection2);
173+
174+
return `${plainSection1}<strong>${highlightedSection}</strong>${plainSection2}`;
170175
}
171176

172177
function generateMarkdownForAlertMessage(
@@ -330,3 +335,10 @@ function createFileName(nwo: string) {
330335
const [owner, repo] = nwo.split('/');
331336
return `${owner}-${repo}`;
332337
}
338+
339+
/**
340+
* Escape characters that could be interpreted as HTML instead of raw code.
341+
*/
342+
function escapeHtmlCharacters(text: string): string {
343+
return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
344+
}

extensions/ql-vscode/test/pure-tests/remote-queries/markdown-generation/data/interpreted-results/problem/analyses-results.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,34 @@
148148
"endColumn": 57
149149
},
150150
"codeFlows": []
151+
},
152+
{
153+
"message": {
154+
"tokens": [
155+
{
156+
"t": "text",
157+
"text": "This component is implicitly exported."
158+
}
159+
]
160+
},
161+
"shortDescription": "This component is implicitly exported.",
162+
"fileLink": {
163+
"fileLinkPrefix": "https://github.com/AlexRogalskiy/android-nrf-toolbox/blob/034cf3aa7d2a3a4145177de32546ca518a462a66",
164+
"filePath": "app/src/main/AndroidManifest.xml"
165+
},
166+
"severity": "Warning",
167+
"codeSnippet": {
168+
"startLine": 237,
169+
"endLine": 251,
170+
"text": "\t\t</service>\n\n\t\t<activity\n\t\t\tandroid:name=\"no.nordicsemi.android.nrftoolbox.dfu.DfuInitiatorActivity\"\n\t\t\tandroid:label=\"@string/dfu_service_title\"\n\t\t\tandroid:noHistory=\"true\"\n\t\t\tandroid:theme=\"@style/AppTheme.Translucent\" >\n\t\t\t<intent-filter>\n\t\t\t\t<action android:name=\"no.nordicsemi.android.action.DFU_UPLOAD\" />\n\n\t\t\t\t<category android:name=\"android.intent.category.DEFAULT\" />\n\t\t\t</intent-filter>\n\t\t</activity>\n\n\t\t<service\n"
171+
},
172+
"highlightedRegion": {
173+
"startLine": 239,
174+
"startColumn": 3,
175+
"endLine": 249,
176+
"endColumn": 15
177+
},
178+
"codeFlows": []
151179
}
152180
]
153181
}

extensions/ql-vscode/test/pure-tests/remote-queries/markdown-generation/data/interpreted-results/problem/expected/_summary.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ select t,
4141
| Repository | Results |
4242
| --- | --- |
4343
| github/codeql | [1 result(s)](#file-github-codeql-md) |
44-
| meteor/meteor | [4 result(s)](#file-meteor-meteor-md) |
44+
| meteor/meteor | [5 result(s)](#file-meteor-meteor-md) |

extensions/ql-vscode/test/pure-tests/remote-queries/markdown-generation/data/interpreted-results/problem/expected/meteor-meteor.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
<pre><code class="javascript"> /g,hashElement);
66
*/
7-
text = text.replace(/(\n\n[ ]{0,3}<!(--<strong>[^\r]*?</strong>--\s*)+>[ \t]*(?=\n{2,}))/g,hashElement);
7+
text = text.replace(/(\n\n[ ]{0,3}&lt;!(--<strong>[^\r]*?</strong>--\s*)+&gt;[ \t]*(?=\n{2,}))/g,hashElement);
88

9-
// PHP and ASP-style processor instructions (<?...?> and <%...%>)
9+
// PHP and ASP-style processor instructions (&lt;?...?&gt; and &lt;%...%&gt;)
1010
</code></pre>
1111

1212
*This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '----'.*
@@ -17,7 +17,7 @@
1717

1818
<pre><code class="javascript"> // Build a regex to find HTML tags and comments. See Friedl's
1919
// "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
20-
var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--<strong>.*?</strong>--\s*)+>)/gi;
20+
var regex = /(&lt;[a-z\/!$]("[^"]*"|'[^']*'|[^'"&gt;])*&gt;|&lt;!(--<strong>.*?</strong>--\s*)+&gt;)/gi;
2121

2222
text = text.replace(regex, function(wholeMatch) {
2323
</code></pre>
@@ -46,3 +46,26 @@ pp.strictDirective = function(start) {
4646
*This part of the regular expression may cause exponential backtracking on strings starting with '"' and containing many repetitions of '\!'.*
4747

4848
----------------------------------------
49+
50+
[app/src/main/AndroidManifest.xml](https://github.com/AlexRogalskiy/android-nrf-toolbox/blob/034cf3aa7d2a3a4145177de32546ca518a462a66/app/src/main/AndroidManifest.xml#L239-L249)
51+
52+
<pre><code class="javascript"> &lt;/service&gt;
53+
54+
<strong>&lt;activity</strong>
55+
<strong> android:name="no.nordicsemi.android.nrftoolbox.dfu.DfuInitiatorActivity"</strong>
56+
<strong> android:label="@string/dfu_service_title"</strong>
57+
<strong> android:noHistory="true"</strong>
58+
<strong> android:theme="@style/AppTheme.Translucent" &gt;</strong>
59+
<strong> &lt;intent-filter&gt;</strong>
60+
<strong> &lt;action android:name="no.nordicsemi.android.action.DFU_UPLOAD" /&gt;</strong>
61+
<strong></strong>
62+
<strong> &lt;category android:name="android.intent.category.DEFAULT" /&gt;</strong>
63+
<strong> &lt;/intent-filter&gt;</strong>
64+
<strong> &lt;/activity&gt;</strong>
65+
66+
&lt;service
67+
</code></pre>
68+
69+
*This component is implicitly exported.*
70+
71+
----------------------------------------

0 commit comments

Comments
 (0)