Skip to content

Commit 184a2f0

Browse files
committed
different form fill info allocation to fix mem read issues
1 parent 03191d3 commit 184a2f0

File tree

8 files changed

+118
-39
lines changed

8 files changed

+118
-39
lines changed

src/Docnet.Core/Bindings/DocumentWrapper.cs

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ internal sealed class DocumentWrapper : IDisposable
1010

1111
public FpdfDocumentT Instance { get; private set; }
1212

13-
private FPDF_FORMFILLINFO _formInfo;
14-
private FpdfFormHandleT _formHandle;
15-
1613
public DocumentWrapper(string filePath, string password)
1714
{
1815
Instance = fpdf_view.FPDF_LoadDocument(filePath, password);
@@ -47,42 +44,13 @@ public DocumentWrapper(FpdfDocumentT instance)
4744
}
4845
}
4946

50-
public FpdfFormHandleT GetFormHandle()
51-
{
52-
if (_formHandle != null)
53-
{
54-
return _formHandle;
55-
}
56-
57-
_formInfo = new FPDF_FORMFILLINFO();
58-
59-
for (var i = 1; i <= 2; i++)
60-
{
61-
_formInfo.version = i;
62-
63-
_formHandle = fpdf_view.FPDFDOCInitFormFillEnvironment(Instance, _formInfo);
64-
65-
if (_formHandle != null)
66-
{
67-
break;
68-
}
69-
}
70-
71-
return _formHandle;
72-
}
73-
7447
public void Dispose()
7548
{
7649
if (Instance == null)
7750
{
7851
return;
7952
}
8053

81-
if (_formHandle != null)
82-
{
83-
fpdf_view.FPDF_ExitFormFillEnvironment(_formHandle);
84-
}
85-
8654
fpdf_view.FPDF_CloseDocument(Instance);
8755

8856
Marshal.FreeHGlobal(_ptr);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace Docnet.Core.Bindings
5+
{
6+
internal sealed class FormWrapper : IDisposable
7+
{
8+
private readonly IntPtr _ptr;
9+
10+
public FormWrapper(DocumentWrapper docWrapper)
11+
{
12+
var formInfo = new FPDF_FORMFILLINFO();
13+
14+
_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(formInfo));
15+
16+
for (var i = 1; i <= 2; i++)
17+
{
18+
formInfo.version = i;
19+
20+
Marshal.StructureToPtr(formInfo, _ptr, false);
21+
22+
Instance = fpdf_view.FPDFDOCInitFormFillEnvironment(docWrapper.Instance, _ptr);
23+
24+
if (Instance != null)
25+
{
26+
break;
27+
}
28+
}
29+
}
30+
31+
public FpdfFormHandleT Instance { get; private set; }
32+
33+
public void Dispose()
34+
{
35+
if (Instance != null)
36+
{
37+
fpdf_view.FPDF_ExitFormFillEnvironment(Instance);
38+
}
39+
40+
Marshal.FreeHGlobal(_ptr);
41+
42+
Instance = null;
43+
}
44+
}
45+
}

src/Docnet.Core/Bindings/PdfiumWrapper.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,7 +1833,7 @@ internal static extern IntPtr FPDF_LoadDocument(
18331833
[SuppressUnmanagedCodeSecurity]
18341834
[DllImport("pdfium", CallingConvention = CallingConvention.Cdecl,
18351835
EntryPoint = "FPDFDOC_InitFormFillEnvironment")]
1836-
internal static extern IntPtr FPDFDOC_InitFormFillEnvironment(IntPtr document, FPDF_FORMFILLINFO formInfo);
1836+
internal static extern IntPtr FPDFDOC_InitFormFillEnvironment(IntPtr document, IntPtr formInfo);
18371837

18381838
[SuppressUnmanagedCodeSecurity]
18391839
[DllImport("pdfium", CallingConvention = CallingConvention.Cdecl,
@@ -2325,7 +2325,7 @@ public static FpdfBitmapT FPDFBitmapCreate(int width, int height, int alpha)
23252325
return __result0;
23262326
}
23272327

2328-
public static FpdfFormHandleT FPDFDOCInitFormFillEnvironment(FpdfDocumentT document, FPDF_FORMFILLINFO formInfo)
2328+
public static FpdfFormHandleT FPDFDOCInitFormFillEnvironment(FpdfDocumentT document, IntPtr formInfo)
23292329
{
23302330
var __arg0 = ReferenceEquals(document, null) ? IntPtr.Zero : document.__Instance;
23312331

src/Docnet.Core/Models/RenderFlags.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Docnet.Core.Models
55
[Flags]
66
public enum RenderFlags
77
{
8+
None = 0x00, // None
89
RenderAnnotations = 0x01, // FPDF_ANNOT: Set if annotations are to be rendered.
910
OptimizeTextForLcd = 0x02, // FPDF_LCD_TEXT: Set if using text rendering optimized for LCD display. This flag will only take effect if anti-aliasing is enabled for text.
1011
NoNativeText = 0x04, // FPDF_NO_NATIVETEXT: Don't use the native text output available on some platforms

src/Docnet.Core/Readers/PageReader.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ private byte[] WriteImageToBufferInternal(RenderFlags flags, byte[] result = nul
233233
throw new DocnetException($"result array length should be greater or equal than {length}");
234234
}
235235

236+
FormWrapper formWrapper = null;
237+
236238
try
237239
{
238240
// | | a b 0 |
@@ -253,18 +255,16 @@ private byte[] WriteImageToBufferInternal(RenderFlags flags, byte[] result = nul
253255
clipping.Bottom = 0;
254256
clipping.Top = height;
255257

256-
FpdfFormHandleT formHandle = null;
257-
258258
if (flags.HasFlag(RenderFlags.RenderAnnotations))
259259
{
260-
formHandle = _docWrapper.GetFormHandle();
260+
formWrapper = new FormWrapper(_docWrapper);
261261
}
262262

263263
fpdf_view.FPDF_RenderPageBitmapWithMatrix(bitmap, _page, matrix, clipping, (int)flags);
264264

265-
if (flags.HasFlag(RenderFlags.RenderAnnotations) && formHandle != null)
265+
if (flags.HasFlag(RenderFlags.RenderAnnotations) && formWrapper?.Instance != null)
266266
{
267-
fpdf_view.FPDFFFLDraw(formHandle, bitmap, _page, 0, 0, width, height, PageRotate.Normal, flags);
267+
fpdf_view.FPDFFFLDraw(formWrapper.Instance, bitmap, _page, 0, 0, width, height, PageRotate.Normal, flags);
268268
}
269269

270270
var buffer = fpdf_view.FPDFBitmapGetBuffer(bitmap);
@@ -278,6 +278,8 @@ private byte[] WriteImageToBufferInternal(RenderFlags flags, byte[] result = nul
278278
}
279279
finally
280280
{
281+
formWrapper?.Dispose();
282+
281283
fpdf_view.FPDFBitmapDestroy(bitmap);
282284
}
283285
}
20.8 KB
Binary file not shown.
31.4 KB
Binary file not shown.

src/Docnet.Tests.Integration/PageReaderTests.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Buffers;
3+
using System.IO;
34
using System.Linq;
45
using System.Threading.Tasks;
56
using Docnet.Core.Converters;
@@ -110,6 +111,11 @@ public void PageIndex_WhenCalled_ShouldReturnCorrectIndex(Input type)
110111

111112
ExecuteForDocument(type, "Docs/simple_0.pdf", null, 10, 10, index, pageReader =>
112113
{
114+
if (pageReader == null)
115+
{
116+
throw new ArgumentNullException(nameof(pageReader));
117+
}
118+
113119
Assert.Equal(index, pageReader.PageIndex);
114120
});
115121
}
@@ -409,6 +415,63 @@ public void WriteImageToBufferWithResultFromArrayPoolNoRenderFlags_WhenCalled_Sh
409415
});
410416
}
411417

418+
[Theory]
419+
[InlineData(RenderFlags.RenderAnnotations, "Docs/annotation_1.pdf", null, 0, 0)]
420+
[InlineData(RenderFlags.RenderAnnotations, "Docs/annotation_1.pdf", null, 0, 1)]
421+
[InlineData(RenderFlags.RenderAnnotations, "Docs/annotation_1.pdf", null, 0, 2)]
422+
[InlineData(RenderFlags.RenderAnnotations, "Docs/annotation_1.pdf", null, 0, 3)]
423+
[InlineData(RenderFlags.RenderAnnotations, "Docs/annotation_1.pdf", null, 0, 4)]
424+
[InlineData(RenderFlags.RenderAnnotations, "Docs/annotation_1.pdf", null, 0, 5)]
425+
public void Parallel_GetImage_WhenCalledWithFlags_ShouldWork(RenderFlags flags, string filePath, string password, int pageIndex, int run)
426+
{
427+
var numbers = Enumerable.Range(1, 1000);
428+
429+
Parallel.ForEach(numbers, i =>
430+
{
431+
ExecuteForDocument(Input.FromFile, filePath, password, 1, pageIndex, pageReader =>
432+
{
433+
var bytes = pageReader.GetImage(flags).ToArray();
434+
435+
Assert.NotEmpty(bytes);
436+
437+
// WriteToPPM($"{run}_{i}_image", bytes, pageReader.GetPageHeight(), pageReader.GetPageWidth());
438+
});
439+
});
440+
}
441+
442+
/// <summary>
443+
/// BGRA data to PPM file
444+
/// Alpha channel discarded
445+
/// https://netpbm.sourceforge.net/doc/ppm.html
446+
/// </summary>
447+
private static void WriteToPPM(string fileName, byte[] data, int height, int width)
448+
{
449+
fileName = $"{fileName}.ppm";
450+
451+
using (var writer = new StreamWriter(fileName))
452+
{
453+
writer.WriteLine("P6");
454+
writer.WriteLine($"{width} {height}");
455+
writer.WriteLine("255");
456+
}
457+
458+
using var writerB = new BinaryWriter(new FileStream(fileName, FileMode.Append));
459+
460+
for (var i = 0; i < data.Length / 4; i++)
461+
{
462+
var j = i * 4;
463+
464+
var blue = data[j];
465+
var green = data[j + 1];
466+
var red = data[j + 2];
467+
var alpha = data[j + 3];
468+
469+
writerB.Write((byte)((green * alpha + byte.MaxValue * (255 - alpha)) >> 8)); // G
470+
writerB.Write((byte)((blue * alpha + byte.MaxValue * (255 - alpha)) >> 8)); // B
471+
writerB.Write((byte)((red * alpha + byte.MaxValue * (255 - alpha)) >> 8)); // R
472+
}
473+
}
474+
412475
private static int GetNonZeroByteCount(Input type, string filePath, LibFixture fixture)
413476
{
414477
using (var reader = fixture.GetDocReader(type, filePath, null, 1000, 1000))

0 commit comments

Comments
 (0)