halflife icon indicating copy to clipboard operation
halflife copied to clipboard

Memory leak in VGUI1 Image Label code

Open SamVanheer opened this issue 4 years ago • 2 comments

This code leaks FileInputStream objects: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/cl_dll/vgui_CustomObjects.cpp#L383-L393

The object is created but never freed, so repeated calls can use up all memory. It would take an obscene amount of calls to accomplish that though, this leaks about 8 bytes per object (4 bytes for the vtable, 4 bytes for the FILE pointer).

Allocating the stream on the stack will solve this problem:

FileInputStream fis( sz, false );
m_pTGA = new BitmapTGA(&fis,true);
fis.close();

This is a valid way to use VGUI1 streams. See this code for an example of another stream that is allocated this way: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/game_shared/vgui_loadtga.cpp#L65-L78

SamVanheer avatar Apr 27 '21 18:04 SamVanheer

Adding to this report, this memory leak can be exploited by servers to cause leaks on the client.

At the end of this method: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/player.cpp#L3949-L4181

Putting this:

//Image need not exist, and must not exist as a resolution-specific image for the code containing the leak to be reached.
const char* fakeBannerImageName = "foo";

//SVC_DIRECTOR messages start with a byte indicating the total size of the message after the size value.
//The next byte is the command id, followed by command-specific values.
const int messageSize = 1 + strlen(fakeBannerImageName) + 1;

//Leak this many stream objects every time we update the player.
for (int i = 0; i < 50; ++i)
{
	MESSAGE_BEGIN(MSG_ONE, SVC_DIRECTOR, NULL, pev);
	WRITE_BYTE(messageSize);
	WRITE_BYTE(DRC_CMD_BANNER);
	WRITE_STRING(fakeBannerImageName);
	MESSAGE_END();
}

This will send 50 director messages every time the server updates the client, each message leaks memory. I ran the game with a memory profiler. After just a few seconds (~5 seconds spent in the server) thousands of objects were leaked.

SamVanheer avatar Apr 25 '22 12:04 SamVanheer

@kisak-valve please, you should offer a job contract to @SamVanheer

RauliTop avatar May 10 '22 09:05 RauliTop