Skip to content

BlobBuilder.ReserveBytes needs to zero the memory #99244

@jaredpar

Description

@jaredpar

Description

The BlobBuilder.ReserveBytes method allows for callers to observe the backing byte[] before any data is written to it. Normally that is fine because BlobBuilder instances newly allocate the byte[] on construction so the data is zero'd out. In the case the BlobBuilder is created via pooling (the type supports pooling) then the data is whatever was written by the last consumer of the instance.

Reproduction Steps

Can observe using the following steps:

// Using PooledBlobBuilder from the SMR code base. Put used content 
// into the pool
var builder = PooledBlobBuilder.GetInstance();
builder.WriteBytes(42, 4);
builder.Free();

// Now grab a builder from the pool
builder = PooledBlobBuilder.GetInstance();
var blob = builder.ReserveBytes(4);
Console.WriteLine(blob.GetBytes()[0]); // prints 42

Expected behavior

The consumer should not be able to meaningfully observe the content from the previous writer.

Actual behavior

The consumer can observe the content from the previous writer

Regression?

This makes it more difficult for roslyn to widely use pooled BlobBuilder instances in our code base. Consider for example the code in PEBuilder.WriteCoffHeader:

stampFixup = builder.ReserveBytes(sizeof(uint));

This means that the BlobBuilder used for writing out the COFF header has four bytes that are uninitialized / non-zero. That means the underlying Blob for the COFF header is non-deterministic in the face of a pooled BlobBuilder. That non-determinism is then passed to PEBuilder.IdProvider resulting in non-deterministic MVID + timestamps being generated for the PE.

Known Workarounds

Roslyn can work around this by force zero-ing BlobBuilder that are used in COFF generation but it's better to fix the underlying bug.

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions