Skip to content

Commit 2fbaabc

Browse files
Handle blank lines in aux exception data better (#233)
1 parent d472b66 commit 2fbaabc

File tree

5 files changed

+197
-4
lines changed

5 files changed

+197
-4
lines changed

MAPIInspector/Source/BlockParser/BlockString.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ public abstract class BlockString : Block
1010
public string Data => data;
1111
public int Length => data.Length;
1212
public bool Empty => string.IsNullOrEmpty(data);
13+
public bool LineMode { get; set; } = false;
14+
public bool BlankLine { get; set; } = false;
1315
}
1416
}

MAPIInspector/Source/BlockParser/BlockStringA.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ namespace BlockParser
55
{
66
public class BlockStringA : BlockString
77
{
8-
public bool LineMode { get; set; } = false;
98
protected override void Parse()
109
{
1110
Parsed = false;
@@ -57,6 +56,11 @@ protected override void Parse()
5756
data = data.Substring(0, lfIndex);
5857
length = lfIndex + lineEndingLength;
5958
}
59+
60+
if (lfIndex == 0 && lineEndingLength > 0)
61+
{
62+
BlankLine = true;
63+
}
6064
}
6165

6266
data = Strings.RemoveInvalidCharacters(data);

MAPIInspector/Source/BlockParser/BlockStringW.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ namespace BlockParser
55
{
66
public class BlockStringW : BlockString
77
{
8-
public bool LineMode { get; set; } = false;
98
protected override void Parse()
109
{
1110
Parsed = false;
@@ -14,7 +13,7 @@ protected override void Parse()
1413
return;
1514

1615
// We don't want to skip a null because we stopped at the line ending
17-
var fixedLength = cchChar != -1|| LineMode;
16+
var fixedLength = cchChar != -1 || LineMode;
1817
var oldOffset = parser.Offset;
1918
var bytes = parser.ReadBytes(size);
2019
parser.Offset = oldOffset;
@@ -63,6 +62,12 @@ protected override void Parse()
6362
data = data.Substring(0, lfIndex);
6463
length = (lfIndex + lineEndingLength) * 2; // Multiply by 2 for UTF-16 bytes
6564
}
65+
66+
if (lfIndex == 0 && lineEndingLength > 0)
67+
{
68+
BlankLine = true;
69+
}
70+
6671
}
6772

6873
data = Strings.RemoveInvalidCharacters(data);

MAPIInspector/Source/BlockParserTests/BlockStringATests.cs

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,187 @@ public void MultipleLinesNullTerminated_ParsesCorrectly()
200200

201201
Assert.AreEqual(0x78563412, int1);
202202
}
203+
204+
[TestMethod]
205+
public void BlankLine_SingleLine_BlankLine_Line_EOS()
206+
{
207+
var bytes = new byte[]
208+
{
209+
// "line1\r\n"
210+
0x6C, 0x69, 0x6E, 0x65, 0x31, 0x0D, 0x0A, // 7 bytes
211+
// "\r\n" (blank line)
212+
0x0D, 0x0A, // 2 bytes
213+
// "line3"
214+
0x6C, 0x69, 0x6E, 0x65, 0x33 // 5 bytes (no terminator - EOS)
215+
};
216+
var parser = new BinaryParser(bytes);
217+
218+
var block1 = Block.ParseStringLineA(parser);
219+
Assert.AreEqual("line1", block1);
220+
Assert.IsFalse(block1.BlankLine);
221+
Assert.AreEqual(0, block1.Offset);
222+
Assert.AreEqual(5, block1.Length);
223+
Assert.AreEqual(7, block1.Size);
224+
225+
var block2 = Block.ParseStringLineA(parser);
226+
Assert.AreEqual("", block2);
227+
Assert.IsTrue(block2.BlankLine);
228+
Assert.AreEqual(7, block2.Offset);
229+
Assert.AreEqual(0, block2.Length);
230+
Assert.AreEqual(2, block2.Size);
231+
232+
var block3 = Block.ParseStringLineA(parser);
233+
Assert.AreEqual("line3", block3);
234+
Assert.IsFalse(block3.BlankLine);
235+
Assert.AreEqual(9, block3.Offset);
236+
Assert.AreEqual(5, block3.Length);
237+
Assert.AreEqual(5, block3.Size);
238+
239+
Assert.AreEqual(14, parser.Offset);
240+
Assert.AreEqual(0, parser.RemainingBytes);
241+
}
242+
243+
[TestMethod]
244+
public void BlankLine_TwoLines_BlankLine_Line_NullTerminator_OtherData()
245+
{
246+
var bytes = new byte[]
247+
{
248+
// "line1\r\n"
249+
0x6C, 0x69, 0x6E, 0x65, 0x31, 0x0D, 0x0A, // 7 bytes
250+
// "line2\n"
251+
0x6C, 0x69, 0x6E, 0x65, 0x32, 0x0A, // 6 bytes
252+
// "\r\n" (blank line)
253+
0x0D, 0x0A, // 2 bytes
254+
// "line4\0" (null terminated)
255+
0x6C, 0x69, 0x6E, 0x65, 0x34, 0x00, // 6 bytes
256+
// Other data
257+
0xAA, 0xBB, 0xCC, 0xDD // 4 bytes
258+
};
259+
var parser = new BinaryParser(bytes);
260+
261+
var block1 = Block.ParseStringLineA(parser);
262+
Assert.AreEqual("line1", block1);
263+
Assert.IsFalse(block1.BlankLine);
264+
Assert.AreEqual(0, block1.Offset);
265+
Assert.AreEqual(5, block1.Length);
266+
Assert.AreEqual(7, block1.Size);
267+
268+
var block2 = Block.ParseStringLineA(parser);
269+
Assert.AreEqual("line2", block2);
270+
Assert.IsFalse(block2.BlankLine);
271+
Assert.AreEqual(7, block2.Offset);
272+
Assert.AreEqual(5, block2.Length);
273+
Assert.AreEqual(6, block2.Size);
274+
275+
var block3 = Block.ParseStringLineA(parser);
276+
Assert.AreEqual("", block3);
277+
Assert.IsTrue(block3.BlankLine);
278+
Assert.AreEqual(13, block3.Offset);
279+
Assert.AreEqual(0, block3.Length);
280+
Assert.AreEqual(2, block3.Size);
281+
282+
var block4 = Block.ParseStringLineA(parser);
283+
Assert.AreEqual("line4", block4);
284+
Assert.IsFalse(block4.BlankLine);
285+
Assert.AreEqual(15, block4.Offset);
286+
Assert.AreEqual(5, block4.Length);
287+
Assert.AreEqual(6, block4.Size); // Includes null terminator
288+
289+
Assert.AreEqual(21, parser.Offset);
290+
Assert.AreEqual(4, parser.RemainingBytes);
291+
292+
// Verify other data is still there
293+
var otherData = Block.ParseT<uint>(parser);
294+
Assert.AreEqual(0xDDCCBBAA, otherData); // Little endian
295+
}
296+
297+
[TestMethod]
298+
public void BlankLine_OnlyBlankLines()
299+
{
300+
var bytes = new byte[]
301+
{
302+
// "\r\n" (blank line 1)
303+
0x0D, 0x0A, // 2 bytes
304+
// "\n" (blank line 2)
305+
0x0A, // 1 byte
306+
// "\r\n" (blank line 3)
307+
0x0D, 0x0A, // 2 bytes
308+
// Other data
309+
0x12, 0x34
310+
};
311+
var parser = new BinaryParser(bytes);
312+
313+
var block1 = Block.ParseStringLineA(parser);
314+
Assert.AreEqual("", block1);
315+
Assert.IsTrue(block1.BlankLine);
316+
Assert.AreEqual(0, block1.Offset);
317+
Assert.AreEqual(0, block1.Length);
318+
Assert.AreEqual(2, block1.Size);
319+
320+
var block2 = Block.ParseStringLineA(parser);
321+
Assert.AreEqual("", block2);
322+
Assert.IsTrue(block2.BlankLine);
323+
Assert.AreEqual(2, block2.Offset);
324+
Assert.AreEqual(0, block2.Length);
325+
Assert.AreEqual(1, block2.Size);
326+
327+
var block3 = Block.ParseStringLineA(parser);
328+
Assert.AreEqual("", block3);
329+
Assert.IsTrue(block3.BlankLine);
330+
Assert.AreEqual(3, block3.Offset);
331+
Assert.AreEqual(0, block3.Length);
332+
Assert.AreEqual(2, block3.Size);
333+
334+
Assert.AreEqual(5, parser.Offset);
335+
Assert.AreEqual(2, parser.RemainingBytes);
336+
}
337+
338+
[TestMethod]
339+
public void BlankLine_MixedLineEndings()
340+
{
341+
var bytes = new byte[]
342+
{
343+
// "text\r\n"
344+
0x74, 0x65, 0x78, 0x74, 0x0D, 0x0A, // 6 bytes
345+
// "\n" (blank line with LF only)
346+
0x0A, // 1 byte
347+
// "more\n"
348+
0x6D, 0x6F, 0x72, 0x65, 0x0A, // 5 bytes
349+
// "\r\n" (blank line with CRLF)
350+
0x0D, 0x0A // 2 bytes
351+
};
352+
var parser = new BinaryParser(bytes);
353+
354+
var block1 = Block.ParseStringLineA(parser);
355+
Assert.AreEqual("text", block1);
356+
Assert.IsFalse(block1.BlankLine);
357+
Assert.AreEqual(0, block1.Offset);
358+
Assert.AreEqual(4, block1.Length);
359+
Assert.AreEqual(6, block1.Size);
360+
361+
var block2 = Block.ParseStringLineA(parser);
362+
Assert.AreEqual("", block2);
363+
Assert.IsTrue(block2.BlankLine);
364+
Assert.AreEqual(6, block2.Offset);
365+
Assert.AreEqual(0, block2.Length);
366+
Assert.AreEqual(1, block2.Size);
367+
368+
var block3 = Block.ParseStringLineA(parser);
369+
Assert.AreEqual("more", block3);
370+
Assert.IsFalse(block3.BlankLine);
371+
Assert.AreEqual(7, block3.Offset);
372+
Assert.AreEqual(4, block3.Length);
373+
Assert.AreEqual(5, block3.Size);
374+
375+
var block4 = Block.ParseStringLineA(parser);
376+
Assert.AreEqual("", block4);
377+
Assert.IsTrue(block4.BlankLine);
378+
Assert.AreEqual(12, block4.Offset);
379+
Assert.AreEqual(0, block4.Length);
380+
Assert.AreEqual(2, block4.Size);
381+
382+
Assert.AreEqual(14, parser.Offset);
383+
Assert.AreEqual(0, parser.RemainingBytes);
384+
}
203385
}
204386
}

MAPIInspector/Source/Parsers/MSOXCMAPIHTTP/auxiliary/AUX_EXCEPTION_TRACE.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ protected override void Parse()
3232
str = ParseStringLineA(parser);
3333
exceptionMessage.Add(str);
3434

35-
if (str.Empty) break;
35+
if (str.Empty && !str.BlankLine) break;
3636
}
3737

3838
ExceptionMessage = exceptionMessage.ToArray();

0 commit comments

Comments
 (0)