To get a trial key
fill out the form below
Team License (a basic version)
Enterprise License (extended version)
* By clicking this button you agree to our Privacy Policy statement

Request our prices
New License
License Renewal
--Select currency--
USD
EUR
GBP
RUB
* By clicking this button you agree to our Privacy Policy statement

Free PVS-Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

Message submitted.

Your message has been sent. We will email you at


If you haven't received our response, please do the following:
check your Spam/Junk folder and click the "Not Spam" button for our message.
This way, you won't miss messages from our team in the future.

>
>
>
How Visual Studio 2022 ate up 100 GB of…

How Visual Studio 2022 ate up 100 GB of memory and what XML bombs had to do with it

Sep 07 2021

In April 2021 Microsoft announced a new version of its IDE – Visual Studio 2022 – while also announcing that the IDE would be 64-bit. We've been waiting for this for so long – no more 4 GB memory limitations! However, as it turned out, it's not all that simple...

0865_VS2022_XMLBomb/image1.png

By the way, if you missed it, here's a link to the announcement post.

But let's get to the matter in question. I reproduced this problem on the latest (available at the time of writing) Visual Studio 2022 version - 17.0.0 Preview 3.1.

To reproduce this, the following is sufficient:

  • use the Blank Solution template to create a new project;
  • add an XML file to the solution.

After this, try to copy the following text to the XML file:

<?xml version="1.0"?>
<!DOCTYPE lolz [
 <!ENTITY lol "lol">
 <!ELEMENT lolz (#PCDATA)>
 <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
 <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
 <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
 <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
 <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
 <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
 <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
 <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
 <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
 <!ENTITY lol10 "&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;&lol9;">
 <!ENTITY lol11 
   "&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;&lol10;">
 <!ENTITY lol12 
   "&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;&lol11;">
 <!ENTITY lol13 
   "&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;&lol12;">
 <!ENTITY lol14 
   "&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;&lol13;">
 <!ENTITY lol15 
   "&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;&lol14;">
]>
<lolz>&lol15;</lolz>

Now go make yourself a cup of coffee, get back to your computer - and watch Visual Studio eat up more and more RAM.

0865_VS2022_XMLBomb/image2.png

You may have two questions:

  • Why create some weird XML and add it to projects?
  • What is happening here?

Let's figure this out. To do this, we'll need to understand why processing XML files carelessly can be dangerous and what the PVS-Studio analyzer has to do with all this.

SAST in PVS-Studio

We continue to actively develop PVS-Studio as a SAST solution. If we talk about the C# analyzer, the main focus here is OWASP Top 10 2017 (that's the latest version available - we are looking forward to an update!) support. By the way, if you missed it, not too long ago we added the taint analysis feature. You can read about it here.

So, I created (or, to be exact, attempted to create) a sample project to test the analyzer. The fact is, one of the OWASP Top 10 categories we are developing diagnostic rules for, is A4:2017-XML External Entities (XXE). It has to do with incorrect XML file processing that makes applications vulnerable to attacks. What does incorrect processing mean? Often it's excessive trust to input data (a perpetual problem that causes many vulnerabilities) combined with XML parsers that lack sufficient limitations.

As a result, if the files are compromised, this may cause various unpleasant consequences. There are two main problems here: data disclosure and denial of service. Both have corresponding CWEs:

I'll leave CWE-611 for the other day. Today we need CWE-776.

XML bombs (billion laughs attack)

I'll briefly describe the essence of the problem. If you'll want to know more, many resources on the internet will provide you with the information you need.

The XML standard assumes the use of DTD (document type definition). DTD enables you to use so-called XML entities.

The entity syntax is simple:

<!ENTITY myEntity "Entity value">

Then you can get the entity value as follows:

&myEntity;

The catch here is, entities can expand not only into strings (as in our case - "Entity value"), but also into sequences of other entities. For example:

<!ENTITY lol "lol">
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">

As a result, when expanding the 'lol1' entity, we get a string that looks like this:

lollollollollollollollollollol

You can go further and define the 'lol2' entity by expanding it through 'lol1':

<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">

Then when expanding the 'lol2' entity, you get the following output:

lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollol

How about going a level deeper and defining the 'lol3' entity?

<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">

Here's the output you get when expanding it:

lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
lollollollollollollollollollollollollollollollollollollollollollollollol
....

The XML file we used at the beginning of the article was generated with the same principle. Now, I think you see where the "billion laughs" name comes from. So, it turns out, if the XML parser is configured incorrectly (DTD processing is enabled and maximum entity size is not limited) - nothing good happens when this 'bomb' is processed.

Talking about C#, vulnerable code is easiest to demonstrate with an XmlReader type example:

var pathToXmlBomb = @"D:\XMLBomb.xml";
XmlReaderSettings rs = new XmlReaderSettings()
{
  DtdProcessing = DtdProcessing.Parse,
  MaxCharactersFromEntities = 0
};

using var reader = XmlReader.Create(File.OpenRead(pathToXmlBomb), rs);
while (reader.Read())
{
  if (reader.NodeType == XmlNodeType.Text)
    Console.WriteLine(reader.Value);
}

If I configure my XmlReader this way, I am almost telling the intruder: "Come on, blow this up!".

There are two reasons for this:

  • DTD processing is enabled;
  • the restriction for a maximum number of characters from entities has been removed and the file can grow unhindered.

By default, processing of DTD entities is forbidden: the DtdProcessing property is set to Prohibit. The maximum number of characters from entities is also limited (starting with .NET Framework 4.5.2). So in the modern .NET you have fewer and fewer opportunities to shoot yourself in the foot. This is still possible though - if you configure parsers incorrectly.

Coming back to Visual Studio 2022

It seems that in Visual Studio 2022, when we copied our XML bomb, both conditions were true:

  • DTD processing started;
  • no limitations were set - which caused the ever-increasing memory consumption.

We examined the process to see what was happening. What we found confirmed our expectations.

0865_VS2022_XMLBomb/image3.png

The process list showed that the main thread was processing with the XML file. That caused GUI to freeze, and IDE did not respond to any attempts to revive it. with the XML file.

The VS Main thread's call stack showed that the thread was busy processing DTD (the ParseDtd method execution)

0865_VS2022_XMLBomb/image4.png

During the experiment I was wondering, why does Visual Studio run DTD processing at all? Why doesn't it display XML as-is? I got my answer when experimenting with a small XML bomb (same approach, lighter load).

It seems that the whole point is to display possible values of entities in the editor "on the fly".

0865_VS2022_XMLBomb/image5.png

Small values are processed successfully, but problems arise when XML entities start growing.

Of course, after my investigation, I had to write a bug report.

Conclusion

This is how we - unexpectedly - saw an XML bomb in action. It was very interesting to explore a real-life popular application and find something like this.

Just as I am writing this, we are developing a diagnostic to search for code that is vulnerable to XML file processing problems. We expect to release it with PVS-Studio 7.15. If you want to see what the analyzer can do right now, I encourage you to download it and try it on your project. ;)

As always, subscribe to my Twitter so as not to miss anything interesting.

Popular related articles
The Evil within the Comparison Functions

Date: May 19 2017

Author: Andrey Karpov

Perhaps, readers remember my article titled "Last line effect". It describes a pattern I've once noticed: in most cases programmers make an error in the last line of similar text blocks. Now I want t…
Static analysis as part of the development process in Unreal Engine

Date: Jun 27 2017

Author: Andrey Karpov

Unreal Engine continues to develop as new code is added and previously written code is changed. What is the inevitable consequence of ongoing development in a project? The emergence of new bugs in th…
The Ultimate Question of Programming, Refactoring, and Everything

Date: Apr 14 2016

Author: Andrey Karpov

Yes, you've guessed correctly - the answer is "42". In this article you will find 42 recommendations about coding in C++ that can help a programmer avoid a lot of errors, save time and effort. The au…
How PVS-Studio Proved to Be More Attentive Than Three and a Half Programmers

Date: Oct 22 2018

Author: Andrey Karpov

Just like other static analyzers, PVS-Studio often produces false positives. What you are about to read is a short story where I'll tell you how PVS-Studio proved, just one more time, to be more atte…
The Last Line Effect

Date: May 31 2014

Author: Andrey Karpov

I have studied many errors caused by the use of the Copy-Paste method, and can assure you that programmers most often tend to make mistakes in the last fragment of a homogeneous code block. I have ne…
PVS-Studio for Java

Date: Jan 17 2019

Author: Andrey Karpov

In the seventh version of the PVS-Studio static analyzer, we added support of the Java language. It's time for a brief story of how we've started making support of the Java language, how far we've co…
Appreciate Static Code Analysis!

Date: Oct 16 2017

Author: Andrey Karpov

I am really astonished by the capabilities of static code analysis even though I am one of the developers of PVS-Studio analyzer myself. The tool surprised me the other day as it turned out to be sma…
PVS-Studio ROI

Date: Jan 30 2019

Author: Andrey Karpov

Occasionally, we're asked a question, what monetary value the company will receive from using PVS-Studio. We decided to draw up a response in the form of an article and provide tables, which will sho…
Free PVS-Studio for those who develops open source projects

Date: Dec 22 2018

Author: Andrey Karpov

On the New 2019 year's eve, a PVS-Studio team decided to make a nice gift for all contributors of open-source projects hosted on GitHub, GitLab or Bitbucket. They are given free usage of PVS-Studio s…
Technologies used in the PVS-Studio code analyzer for finding bugs and potential vulnerabilities

Date: Nov 21 2018

Author: Andrey Karpov

A brief description of technologies used in the PVS-Studio tool, which let us effectively detect a large number of error patterns and potential vulnerabilities. The article describes the implementati…

Comments (0)

Next comments
This website uses cookies and other technology to provide you a more personalized experience. By continuing the view of our web-pages you accept the terms of using these files. If you don't want your personal data to be processed, please, leave this site.
Learn More →
Accept