Lifted null comparison decompiles to HasValue/GetValueOrDefault with a '? true : false'
Author: siegfriedpammerCreated Sep 13, 2026Updated Sep 16, 2026
LabelsDecompilerOutput
Input code
SixLabors.ImageSharp 4.1.1, SixLabors.ImageSharp.Formats.Png.PngEncoderCore.WriteXmpChunk (and
WriteExifChunk, same shape):
ilspycmd ~/.cache/nugetfuzz/sixlabors.imagesharp/4.1.1/lib/net8.0/SixLabors.ImageSharp.dll \
-t SixLabors.ImageSharp.Formats.Png.PngEncoderCoreErroneous output
Current master (dbf23c6e4):
byte[] data = meta.XmpProfile.Data;
int? num = data?.Length;
if ((num ?? 0) == 0)
{
return;
}With #4091 (6fcb387ff) the lifted comparison is expanded and wrapped in a no-op conditional:
byte[] data = meta.XmpProfile.Data;
int? num = data?.Length;
if ((!num.HasValue || num.GetValueOrDefault() == 0) ? true : false)
{
return;
}Two separate things happen here: the ?? form is lost, and the resulting bool expression gains a
? true : false.
Other instances from the same corpus run (top-200 nuget.org packages, #4091 against its merge base):
- Swashbuckle.AspNetCore.SwaggerGen 10.2.3,
XmlCommentsRequestBodyFilter:if ((num2 ?? 1) == 0 || num == 0)becomesif ((num2.HasValue && num2.GetValueOrDefault() == 0) || num == 0) OpenTelemetry.Exporter.OpenTelemetryProtocolserializer:((statusCode ?? StatusCode.Unset) != StatusCode.Unset)becomes(statusCode.HasValue && statusCode.GetValueOrDefault() != StatusCode.Unset)
Details
- Product in use: ICSharpCode.Decompiler, built from source
- Version in use: not reproducible on master (dbf23c6e4); measured at 6fcb387ff against merge base 712ad1aed. Three types in the corpus are affected; the output remains correct.
Filed by an AI agent (Claude) on Siegfried's behalf.
Source: icsharpcode/ILSpy