The Type-2 CharString processing function (Type2BuildChar) implemented in the t2k font library as part of the Oracle Java Runtime Environment supports the "transient array" memory area, as specified in the "Type 2 Charstring format" specs [1]. While allocating the array, however, the routine does not clear the contents of the newly created buffer (which is a part of a larger structure storing the program state). If a reading PostScript instruction is then used to access an item in the array that has not been previously initialized, it is possible to leak data from the transient array into other structures and further use it e.g. as a parameter of the rendered font shapes. The possibility of such scenario is even mentioned in the [1] specification:
"If *get* is executed prior to *put* for /i/ during execution of the current charstring, the value returned is undefined."
As a result of the above JRE behavior, it is possible to read uninitialized memory via the "escape + get" PostScript instruction, which loads a 32-bit value from the transient array into the operand stack.
The bug is reproducible only with OTF fonts, because the "get" operator (and transient arrays in general) is not implemented in the Type-1 CharString processing function (Type1BuildChar). Therefore, the length of the transient array is always 32 elements, or 128 bytes (see the "Appendix B: Type 2 Charstring Implementation Limits" section of [1]).
The latest version of the t2k library at the time of this writing is confirmed to be affected (the one bundled with JRE 8u40), but we expect that all prior versions are prone to the bug, too. Attached is a Proof of Concept OTF font together with the source code of a Java class, which uses the enclosed font to render the glyph of letter 'a' in a window in an infinite loop. Since the font was designed so that the glyph shapes represent the leaked uninitialized memory, it is clearly visible that the problem exists, due to differences in how the glyph is displayed in respective runs.
More specifically, the font's letters 'a'-'z' are designed to disclose 128 bytes of process memory each by rendering each bit as a black 64x64 units square if the bit is set, or a white one if it is cleared. Therefore, each glyph is a 2048x2048 unit shape, with each of the 32 leaked DWORDs being represented as a separate column. The extraction of respective bits from a 32-bit value is not trivial with Type-2 CharString instructions, but is possible with the help of multiple arithmetic and conditional operations. The following is a Python function building a CharString payload to extract a specified bit off a specified leaked DWORD, used to create the attached POC font. Full source code of the script will be released at a later time.
While not all operators used in the POC font are supported by JRE, and thus the font does not render fully correctly in compliance with the specs, the seemingly non-deterministic nature of the rendered shapes still unquestionably show the flaw existence.
---
def leak_bit(dword, bit):
# Leak a complete dword to the operand stack.
payload = enc(dword) + cf2_cmdESC_GET
# Because of signed arithmetic, we must handle the MSB separately.
if bit == 31:
payload += enc(0) + enc(1) + enc(0) + enc(3) + cf2_cmdESC_INDEX + cf2_cmdESC_IFELSE + cf2_cmdESC_EXCH + cf2_cmdESC_DROP
else:
# If the value is negative, flip the MSB for all further calculations.
payload += enc(0) + enc_dword(2 ** 31) + enc(0) + enc(3) + cf2_cmdESC_INDEX + cf2_cmdESC_IFELSE + cf2_cmdESC_SUB
# Subtract all bits more significant than the one we're leaking.
for i in range(30, bit, -1):
payload += enc(0) + enc_dword(2 ** i) + enc(2) + cf2_cmdESC_INDEX + enc_dword((2 ** i) - 1) + cf2_cmdESC_IFELSE + cf2_cmdESC_SUB
# Return the specific bit by performing a 32-bit comparison.
payload += enc(0) + enc(1) + enc(2) + cf2_cmdESC_INDEX + enc_dword((2 ** bit) - 1) + cf2_cmdESC_IFELSE + cf2_cmdESC_EXCH + cf2_cmdESC_DROP
return payload
---
This bug is subject to a 90 day disclosure deadline. If 90 days elapse without a broadly available patch, then the bug report will automatically become visible to the public.
References:
[1] "The Type 2 Charstring Format, Technical Note #5177, 16 March 2000", http://partners.adobe.com/public/developer/en/font/5177.Type2.pdf