Skip to content

Commit cce4f83

Browse files
authored
Unable to process LTTng trace on .NET 6.0 (#103)
* Fix for breaking change in .NET 6.0 that broke LTTng parser - Partial and zero-byte reads in DeflateStream - https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/partial-byte-reads-in-streams * Upgrade to Antlr runtime 4.11.1 in hopes it fixed this issue (it didn't). Also fixes build failure during upgrade per kaby76/Antlr4BuildTasks#31 * Upgrade all other Nugets as well
1 parent c80244b commit cce4f83

File tree

21 files changed

+1734
-1733
lines changed

21 files changed

+1734
-1733
lines changed

CtfPlayback/CtfPlayback.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>netstandard2.1</TargetFramework>
5-
<Version>1.2.2</Version>
5+
<Version>1.2.3</Version>
66
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
77
<Authors>Microsoft</Authors>
88
<Company>Microsoft Corp.</Company>
@@ -40,7 +40,7 @@
4040
</ItemGroup>
4141

4242
<ItemGroup>
43-
<PackageReference Include="Antlr4.Runtime.Standard" Version="4.9.3" GeneratePathProperty="true" />
43+
<PackageReference Include="Antlr4.Runtime.Standard" Version="4.11.1" GeneratePathProperty="true" />
4444
</ItemGroup>
4545

4646
<ItemGroup>

CtfPlayback/Helpers/StreamExts.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.IO;
6+
7+
namespace CtfPlayback.Helpers
8+
{
9+
internal static class StreamExts
10+
{
11+
/// <summary>
12+
/// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
13+
/// Keeps behavior of pre .NET 6.0 code which reads until count is reached or EOF
14+
/// .NET 6.0 breaking change - https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/partial-byte-reads-in-streams - bytes read can be less than what was requested
15+
/// </summary>
16+
/// <param name="stream">The stream to read from</param>
17+
/// <param name="buffer">
18+
/// An array of bytes. When this method returns, the buffer contains the specified
19+
/// byte array with the values between offset and (offset + count - 1) replaced by
20+
/// the bytes read from the current source.
21+
/// </param>
22+
/// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
23+
/// <param name="count">The number of bytes to be read from the current stream.</param>
24+
/// <returns>The total number of bytes read into the buffer. This can be zero (0) if the end of the stream has been reached.</returns>
25+
public static int ReadUntilBytesRequested(this Stream stream, byte[] buffer, int offset, int count)
26+
{
27+
int read = stream.Read(buffer, offset, count);
28+
if (read == 0)
29+
{
30+
return 0;
31+
}
32+
33+
if (read != count) // .NET 6.0 breaking change - https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/partial-byte-reads-in-streams - bytes read can be less than what was requested
34+
{
35+
while (read < buffer.Length) // Keep reading until we fill up our buffer to the count
36+
{
37+
int tmpBytesRead = stream.Read(buffer.AsSpan().Slice(read));
38+
if (tmpBytesRead == 0) break;
39+
read += tmpBytesRead;
40+
}
41+
}
42+
43+
return read;
44+
}
45+
}
46+
}

CtfPlayback/Metadata/AntlrParser/CtfAntlrMetadataParser.cs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
using System.Text;
88
using Antlr4.Runtime;
99
using Antlr4.Runtime.Tree;
10+
using CtfPlayback.Helpers;
1011
using CtfPlayback.Metadata.Interfaces;
11-
using CtfReader.Metadata.AntlrParser;
1212

1313
namespace CtfPlayback.Metadata.AntlrParser
1414
{
@@ -68,7 +68,9 @@ public ICtfMetadata Parse(Stream metadataStream)
6868
/// <param name="metadataStream">Metadata stream</param>
6969
/// <returns>String representation of the metadata</returns>
7070
private unsafe string GetMetadata(Stream metadataStream)
71-
{
71+
{
72+
// See https://diamon.org/ctf/#spec7.1
73+
7274
byte[] headerBuffer = new byte[Marshal.SizeOf(typeof(MetadataPacketHeader))];
7375
byte[] buffer = null;
7476

@@ -81,8 +83,9 @@ private unsafe string GetMetadata(Stream metadataStream)
8183
var sb = new StringBuilder();
8284

8385
while (true)
84-
{
85-
if (metadataStream.Read(headerBuffer, 0, headerBuffer.Length) != headerBuffer.Length)
86+
{
87+
int bytesRead = metadataStream.ReadUntilBytesRequested(headerBuffer, 0, headerBuffer.Length);
88+
if (bytesRead == 0)
8689
{
8790
break;
8891
}
@@ -95,7 +98,7 @@ private unsafe string GetMetadata(Stream metadataStream)
9598

9699
// todo:check the endianness based on the magic number
97100

98-
if (header.Magic == 0x75d11d57) // CTF: Magic Header for binary metadata streams
101+
if (header.Magic == 0x75d11d57) // CTF: Magic Header for binary metadata streams // 1976638807
99102
{
100103
int packetSize = (int) header.PacketSize / 8 - headerBuffer.Length;
101104

@@ -104,19 +107,19 @@ private unsafe string GetMetadata(Stream metadataStream)
104107
buffer = new byte[packetSize];
105108
}
106109

107-
int read = metadataStream.Read(buffer, 0, packetSize);
110+
int read = metadataStream.ReadUntilBytesRequested(buffer, 0, packetSize);
108111
if (read == 0)
109112
{
110-
break;
113+
throw new InvalidDataException($"Metadata stream seems to be corrupt. We read 0 bytes when we expected packetSize:{packetSize} bytes.");
111114
}
112115

113116
int contentSize = (int) header.ContentSize / 8 - headerBuffer.Length;
114-
if (contentSize < read)
115-
{
116-
read = contentSize;
117-
}
118-
119-
string result = Encoding.ASCII.GetString(buffer, 0, read);
117+
if (read < contentSize)
118+
{
119+
throw new InvalidDataException($"Metadata stream seems to be corrupt. We read {read} packetSize bytes but the header says there should be {contentSize} bytes.");
120+
}
121+
122+
string result = Encoding.ASCII.GetString(buffer, 0, contentSize);
120123

121124
sb.Append(result);
122125
}
@@ -141,7 +144,7 @@ private unsafe string GetMetadata(Stream metadataStream)
141144
}
142145
}
143146
}
144-
147+
145148
return sb.ToString();
146149
}
147150

CtfPlayback/Metadata/AntlrParser/Generated/CtfBaseListener.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
// Copyright (c) Microsoft Corporation.
2-
// Licensed under the MIT License.
31
//------------------------------------------------------------------------------
42
// <auto-generated>
53
// This code was generated by a tool.
6-
// ANTLR Version: 4.7.2
4+
// ANTLR Version: 4.11.1
75
//
86
// Changes to this file may cause incorrect behavior and will be lost if
97
// the code is regenerated.
108
// </auto-generated>
119
//------------------------------------------------------------------------------
1210

13-
// Generated from Ctf.g4 by ANTLR 4.7.2
11+
// Generated from Ctf.g4 by ANTLR 4.11.1
1412

1513
// Unreachable code detected
1614
#pragma warning disable 0162
@@ -33,7 +31,8 @@
3331
/// which can be extended to create a listener which only needs to handle a subset
3432
/// of the available methods.
3533
/// </summary>
36-
[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.7.2")]
34+
[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.11.1")]
35+
[System.Diagnostics.DebuggerNonUserCode]
3736
[System.CLSCompliant(false)]
3837
public partial class CtfBaseListener : ICtfListener {
3938
/// <summary>

0 commit comments

Comments
 (0)