Linux-only NullReferenceException on Save after concatenating (22.7)

Unit tests that pass in our dev environment fail in CI, throwing a NullReferenceException up from obfuscated Aspose.Pdf.Document stack code.

Attached AsposeBugOnLinux.zip (1.8 KB) is a simple reproduction.

This will result in a two-page PDF being created if running in a Windows environment,
but if run in a Linux environment, crashes:

# dotnet AsposeBugOnLinux.dll
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at #=z$HFtu4h7MeeNpCkReDTZDfwCVDVe.#=zetu2Mzs=(#=znfCmefDmMB013VcLwGnRrXdz4S_2 #=ziocaaOgdqBXi)
   at #=zISc35fZbrRlU4tul9$bfVwg=.#=zd8Wstn4=(#=znfCmefDmMB013VcLwGnRrXdz4S_2 #=ziocaaOgdqBXi)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z7URyNe7NvDbxFpg5H7VVQC95y3RdEE$dPuLM76fwYkyf(Object #=zm2ekIcs=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=ziHMnAyNxv8VTxDNH4DTBhLY=(MethodBase #=zm2ekIcs=, Boolean #=z4CS35XU=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=zdSwThCHvamFUkdivJNYAbiFZLjHvKxNbbQ==(#=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M= #=zm2ekIcs=, #=qb1BnzI_hXJAzEwlEGsTlHP3G6ho40kEVQLJRwo5CKQA= #=z4CS35XU=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=zAICyB0vcYna$2QoeXw3lao_Lhx$F0ASj4A_cS0s=()
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z78MYQurxd9zZsKNK7XxjtEa_Hl41iBVGINdbMiY=(Boolean #=zm2ekIcs=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z7URyNe7NvDbxFpg5H7VVQC95y3RdEE$dPuLM76fwYkyf(Object #=zm2ekIcs=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z1H2D4MoI3t6diN8eb3vUm22xXWHVxhiGGg==()
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=zWNlPhV85lLnkgaPkuRXGFywc9nd_fvPkxg==(#=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M= #=zm2ekIcs=, #=qb1BnzI_hXJAzEwlEGsTlHP3G6ho40kEVQLJRwo5CKQA= #=z4CS35XU=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=zAICyB0vcYna$2QoeXw3lao_Lhx$F0ASj4A_cS0s=()
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z78MYQurxd9zZsKNK7XxjtEa_Hl41iBVGINdbMiY=(Boolean #=zm2ekIcs=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z7URyNe7NvDbxFpg5H7VVQC95y3RdEE$dPuLM76fwYkyf(Object #=zm2ekIcs=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z1H2D4MoI3t6diN8eb3vUm22xXWHVxhiGGg==()
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=zk6HZUS6ncW30d6sq_5BPwg$E1Ggu3jILlnTKDgY=(Object #=zm2ekIcs=, UInt32 #=z4CS35XU=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z78MYQurxd9zZsKNK7XxjtEa_Hl41iBVGINdbMiY=(Boolean #=zm2ekIcs=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=z78MYQurxd9zZsKNK7XxjtEa_Hl41iBVGINdbMiY=(Boolean #=zm2ekIcs=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=zHw1u0kdRJb8my$VU2907Od6Pa80L(Object[] #=zm2ekIcs=, Type[] #=z4CS35XU=, Type[] #=zpNB6c8g=, Object[] #=znZ93BY8=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=zIeN4oZuEBWy3dpLS2FwWmyIttKUw9HXtKHUlhV8=(Stream #=zm2ekIcs=, String #=z4CS35XU=, Object[] #=zpNB6c8g=)
   at #=qK5IoDj6SxwEpSQAma5mBiRzUkmKT9huStZ_ZBu$aH2M=.#=zC3JySfpmYg$FGfT_aFLLNpH44RA80kdcxKzipVs=(Stream #=zm2ekIcs=, String #=z4CS35XU=, Object[] #=zpNB6c8g=)
   at Aspose.Pdf.Document.#=zxCl$yh4YxA$y(Stream #=zz1mz6NE=, SaveOptions #=z5LvX9e7QCw5b)
   at Aspose.Pdf.Document.#=zzVLj$_JhiwK4(Stream #=zqMZHDqiBx7YG, SaveOptions #=zNmRHUEo=)
   at Aspose.Pdf.Document.#=zzVLj$_JhiwK4(Stream #=zqMZHDqiBx7YG, SaveFormat #=z6bgwQ60=)
   at Aspose.Pdf.Document.Save(Stream outputStream, SaveFormat format)
   at Program.<Main>$(String[] args) in C:\Users\grant.bowering\source\repos\AsposeBugOnLinux\AsposeBugOnLinux\Program.cs:line 19
Aborted

I saw that a bunch of similar stuff was fixed in 22.6, so I upgraded from 22.4 up to 22.7, but this still occurs.

@grant.bowering

Could you please ZIP and attach your input files here for testing? We will investigate the issue and provide you more information on it.

The zip already attached to the original post is self-contained, there are no input files needed because the example generates them on the fly. Please have a look at AsposeBugOnLinux.zip above.

@grant.bowering

We have logged this problem in our issue tracking system as PDFNET-52185. You will be notified via this forum thread once this issue is resolved.

We apologize for your inconvenience.

@grant.bowering

After further testing and investigation, we found that you are facing this issue due to missing of fonts at Linux system.

Please try to install the package of msttcorefonts. Also, please note that these fonts should be placed in “/usr/share/fonts/truetype/msttcorefonts” directory as Aspose.PDF scans this folder on Linux like operating systems.

This is happening in a hosted build pipeline in Azure DevOps.

Installing some font package on the newly instantiated build container every build as part of our build pipeline, just so these tests pass, is not a very good solution (I’m not even sure that it would work; I don’t know offhand if those paths are writeable).

Do you have an ETA on resolving PDFNET-52185 without altering the build machine? (In the meantime, the two unit tests are simply set to Skip.)

@grant.bowering

The issue PDFNET-52185 was reproduced without installing fonts on Linux system. After installing the fonts, there is no exception and PDF file is saved successfully. The issue PDFNET-52185 has closed as ‘Not a bug’.

Please execute the following commands on your Linux system to avoid this issue.

RUN apt-get update && apt-get install -y libgdiplus
RUN sed -i’.bak’ ‘s/$/ contrib/’ /etc/apt/sources.list
RUN apt-get update; apt-get install -y ttf-mscorefonts-installer fontconfig

Please do not close “We throw a NullReferenceException with no explanation when the system doesn’t have a Microsoft truetype font package installed” as “Not a bug”.

First of all, for anyone who has this problem on a DevOps CI pipeline, here’s how I solved the problem:

The good news is that on the standard Azure Pipelines ubuntu-latest Hosted Agent,

  1. the pipeline runs as a passwordless sudo user, so you can in fact install packages,
  2. and you don’t need to update the package list or amend the sources,
  3. and running this task only added 13 seconds to my build time.

The bad news is just that the ttf-mscorefonts-installer package presents a EULA screen that needs user acknowledgement before it’ll Do the Thing…
But I found how to pre-seed the acceptance so it can run unattended after all.

Here’s the yaml of the task that worked for me when inserted right before the test running task:

      - task: Bash@3
        displayName: "Install extra packages for Aspose on Linux"
        inputs:
          targetType: "inline"
          script: |
            # pre-seed eula acceptance for fonts
            echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | sudo debconf-set-selections
            # install packages
            sudo apt-get install -y libgdiplus ttf-mscorefonts-installer fontconfig

In order for this to be an okay solution to the problem though, I really think Aspose should check for null or catch the NullReferenceException, so it can throw with a message that actually tells people that they need to install fonts!
These fonts aren’t installed by default on any linux distro, because they’re under a less permissive license and require eula acceptance.
So the potential surface of this is pretty wide, and it’s a quick win to if == null or try-catch and throw a helpful message instead.
The issue tracker at the bottom of this post says that PDFNET-52185's status is Open, not closed as Not a Bug. If that’s correct, just make the scope of that issue to add a descriptive error message about missing fonts. If it’s not, please re-open it in order to do so. :slight_smile:

@grant.bowering

It is nice to hear from you that your issue has been solved. We have logged your concerns in our issue tracking system and created separate ticket as PDFNET-52188 to throw meaningful exception for missing fonts.