This is a short story about how using PVS-Studio it was possible to find an error in the source code of the library used in PVS-Studio. Moreover, not theoretical, but actual - the error was manifested in practice when using the library in the analyzer.
In PVS-Studio_Cmd (as well as some other utilities) we use a special library for parsing command line arguments - CommandLine.
Today, I was engaged in supporting the new mode in PVS-Studio_Cmd, and it just so happened that I had to use this library for parsing arguments. In the process of writing code, I am also debugging it, since I have to work with unfamiliar APIs.
So, the code is written, compiled, run for execution, ii ...
Code execution goes inside the library, where an exception of type
NullReferenceException occurs . From the side itβs not very clear - I donβt pass any explicit null references to the method.
Just in case, I look at the comments on the called method. It is very unlikely that they describe the conditions for an exception of type
NullReferenceException (since usually, as it seems to me, exceptions of this type are unforeseen).
In the comments to the method, there is no information about any
NullReferenceException (which, however, is expected).
To see what exactly causes the exception (and where), I decided to download the source code of the project, collect and connect the debug version of the library to the analyzer. The source code for the project
is available on GitHub . Version 1.9.71 is required, since it is precisely this type that is now used in the analyzer.
I load the appropriate version of the source code, collect, connect the debug library to the analyzer, run the code for execution and see:
So, the place of the exception is clear -
helpInfo is
null , which causes an exception of type
NullReferenceException when accessing the
Left instance property.
And then I became thoughtful. Recently, PVS-Studio for C # has been not badly improved in various areas, including in the field of search for dereferencing of potentially null references. In particular, the interprocedural analysis was improved. Therefore, it immediately became interesting for me to check the source code to see if PVS-Studio could find the error under discussion.
I checked the source code, and among other warnings, I saw exactly what I was hoping for.
PVS-Studio Warning :
V3080 Possible null dereference inside method at 'helpInfo.Left'. Consider inspecting the 2nd argument: helpInfo. Parser.cs 405
Yes, there it is! Exactly what you need. Let's look at the source code in a bit more detail.
private bool DoParseArgumentsVerbs( string[] args, object options, ref object verbInstance) { var verbs = ReflectionHelper.RetrievePropertyList<VerbOptionAttribute>(options); var helpInfo = ReflectionHelper.RetrieveMethod<HelpVerbOptionAttribute>(options); if (args.Length == 0) { if (helpInfo != null || _settings.HelpWriter != null) { DisplayHelpVerbText(options, helpInfo, null);
The analyzer generates a warning message when calling the
DisplayHelpVerbText method and warns about the second argument -
helpInfo . Note that this method is in the
then branch of the
if statement . The conditional expression is composed in such a way that
then- branch can be executed with the following values ββof variables:
- helpInfo == null ;
- _settings.HelpWriter! = null ;
Let's see the body of the
DisplayHelpVerbText method:
private void DisplayHelpVerbText( object options, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, string verb) { string helpText; if (verb == null) { HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, null, out helpText); } else { HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, verb, out helpText); } if (_settings.HelpWriter != null) { _settings.HelpWriter.Write(helpText); } }
Since
verb == null (see the method call) we are interested in the
then- branch of the
if statement . Although the situation with the
else branch will be similar, we will consider the
then- branch, since in our particular case execution was through it. Remember that
helpInfo can be
null .
Now let's look at the body of the
HelpVerbOptionAttribute.InvokeMethod method. Actually, you already saw it in the screenshot above:
internal static void InvokeMethod( object target, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, string verb, out string text) { text = null; var method = helpInfo.Left; if (!CheckMethodSignature(method)) { throw new MemberAccessException( SR.MemberAccessException_BadSignatureForHelpVerbOptionAttribute .FormatInvariant(method.Name)); } text = (string)method.Invoke(target, new object[] { verb }); }
helpInfo.Left is called unconditionally, although
helpInfo can be
null . The analyzer warned about this, and this happened.
Conclusion
It turned out funny that with the help of PVS-Studio it was possible to find an error in the code of the library that is used in PVS-Studio. I think this is a kind of continuation of the answer to the question βDoes PVS-Studio find errors in PVS-Studio code?β. :) It can find errors not only in the PVS-Studio code, but also in the code of the libraries used.
Finally, I propose to
download the analyzer and try to check your project - what if you can find something interesting there too?
If you want to share this article with an English-speaking audience, then please use the link to the translation: Sergey Vasiliev.
The story of how PVS-Studio found an error in the library used in ... PVS-Studio