-
Notifications
You must be signed in to change notification settings - Fork 7.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix null reference when markdown content is empty #7463
Fix null reference when markdown content is empty #7463
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder that we have to check so many null references. Seems we need review all the code (not in the PR).
@@ -16,25 +16,28 @@ internal class FencedCodeBlockRenderer : VT100ObjectRenderer<FencedCodeBlock> | |||
{ | |||
protected override void Write(VT100Renderer renderer, FencedCodeBlock obj) | |||
{ | |||
foreach (var codeLine in obj.Lines.Lines) | |||
if (obj?.Lines != null && obj.Lines.Lines != null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use "?" we could do
if (obj?.Lines?.Lines != null)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to obj?.Lines.Lines != null
obj.Lines
is of type StringLineGroup which cannot be null.
{ | ||
if (!string.IsNullOrWhiteSpace(codeLine.ToString())) | ||
foreach (var codeLine in obj?.Lines.Lines) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have checked obj != null
in previous line and could remove "?"
foreach (var codeLine in obj.Lines.Lines)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
@@ -16,38 +16,43 @@ internal class HeaderBlockRenderer : VT100ObjectRenderer<HeadingBlock> | |||
{ | |||
protected override void Write(VT100Renderer renderer, HeadingBlock obj) | |||
{ | |||
// Format header and then add blank line to improve readability. | |||
switch (obj.Level) | |||
string headerText = obj.Inline?.FirstChild?.ToString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we check obj != null
too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
} | ||
else | ||
{ | ||
renderer.Write(renderer.EscapeSequences.FormatLink(obj.FirstChild.ToString(), obj.Url)); | ||
renderer.Write(renderer.EscapeSequences.FormatLink(obj.FirstChild?.ToString(), obj.Url)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We check obj.FirstChild != null
in both code path in the "if-else" - seems we should move the check to new "if":
if (obj.FirstChild != null)
{
if (obj.IsImage)
{
renderer.Write(renderer.EscapeSequences.FormatImage(obj.FirstChild.ToString()));
}
else
{
renderer.Write(renderer.EscapeSequences.FormatLink(obj.FirstChild.ToString(), obj.Url));
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question marks here would have different semantics of course, but I imagine FormatLink
will thrown an NRE if its first argument is null
.
So I would do similar to @iSazonov (just a style change):
if (obj.FirstChild == null)
{
return;
}
if (obj.IsImage)
{
renderer.Write(renderer.EscapeSequences.FormatImage(obj.FirstChild.ToString()));
}
else
{
renderer.Write(renderer.EscapeSequences.FormatLink(obj.FirstChild.ToString(), obj.Url));
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We support having empty alt-text for images and empty link text. So updated accordingly.
{ | ||
if (!string.IsNullOrWhiteSpace(codeLine.ToString())) | ||
foreach (var codeLine in obj.Lines.Lines) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
string
instead of var
would be more obvious here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
@@ -16,14 +16,16 @@ internal class LinkInlineRenderer : VT100ObjectRenderer<LinkInline> | |||
{ | |||
protected override void Write(VT100Renderer renderer, LinkInline obj) | |||
{ | |||
string text = obj?.FirstChild?.ToString(); | |||
|
|||
// Format link as image or link. | |||
if (obj.IsImage) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If obj
is null
, this will cause an NRE. Would the logic be preserved like this:
string text = obj?.FirstChild?.ToString();
if (text == null)
{
return;
}
// Golden path code...
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
obj
can never be null, hence removed ?
after obj
.
We allow text to be null hence the above logic holds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (obj.IsImage)
- can cause an NRE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iSazonov obj
is guaranteed to be not null. If it is null the renderer is not called.
@rjmholt Updated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
// This specifically helps for parameters help content. | ||
if (string.Equals(obj.Info, "yaml", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
renderer.Write("\t").WriteLine(codeLine.ToString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We call codeLine.ToString())
twice above - should we use a variable?
And in line 34 too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One is in if and other is in else, so only one of them is called. And this change is out of scope for this PR.
@daxian-dbw @SteveL-MSFT The PR is ready to merge if you haven't comments. |
Fix #7453
PR Summary
Fix cases where markdown content can be empty and we get a null reference exception.
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
to the beginning of the title and remove the prefix when the PR is ready.[feature]
if the change is significant or affects feature tests