[Dev-luatex] Bug for subsetted CFF font output

Marcel Kr├╝ger tex at 2krueger.de
Tue Oct 23 10:53:07 CEST 2018


Hi,

another bug in LuaTeX: If LuaTeX tries to calculate the size of a CFF table where the second entry in the table is a real number,
`pack_real` is called with `work_buffer+i` for a small `i`.
This causes aliasing issues because `work_buffer` writes into `work_buffer` using `sprintf`.
So the output from `pack_real` modifies `work_buffer` before the digits are read completely,
causing LuaTeX to complain about a "invalid character".

An example to reproduce the issue:

Run the following plainTeX document with the attached version of `LOGO10.otf` (the font was created by reordering
the Private table entries and has an invalid checksum, but this is ignored by LuaTeX)

\directlua{
  font.current(font.define{
    name='logo',
    embedding='subset',
    encodingbytes=2,
    format='opentype',
    filename='LOGO10.otf',
    characters={
      [0x41] = {
        width = 1000,
        height = 1000,
        depth = 1000,
        index = 0x2,
      }
    },
  })
}
A
\bye


This can be fixed by adding a separate temporary buffer for `pack_real`:

diff --git a/source/texk/web2c/luatexdir/font/writecff.c b/source/texk/web2c/luatexdir/font/writecff.c
index cf0751179..1217d1a52 100644
--- a/source/texk/web2c/luatexdir/font/writecff.c
+++ b/source/texk/web2c/luatexdir/font/writecff.c
@@ -1171,6 +1171,7 @@ static long pack_integer(card8 * dest, long destlen, long value)
 
 static long pack_real(card8 * dest, long destlen, double value)
 {
+    static char temp_buffer[22];
     long e;
     int i = 0, pos = 2;
     int res;
@@ -1199,20 +1200,18 @@ static long pack_real(card8 * dest, long destlen, double value)
             e--;
         }
     }
-    res = sprintf(work_buffer, "%1.14g", value);
+    res = sprintf(temp_buffer, "%1.14g", value);
     if (res<0)
         normal_error("cff","invalid conversion");
-    if (res>CFF_REAL_MAX_LEN)
-        res=CFF_REAL_MAX_LEN;
     for (i = 0; i < res; i++) {
         unsigned char ch = 0;
-        if (work_buffer[i] == '\0') {
+        if (temp_buffer[i] == '\0') {
             /*tex In fact |res| should prevent this. */
             break;
-        } else if (work_buffer[i] == '.') {
+        } else if (temp_buffer[i] == '.') {
             ch = 0x0a;
-        } else if (work_buffer[i] >= '0' && work_buffer[i] <= '9') {
-            ch = (unsigned char) (work_buffer[i] - '0');
+        } else if (temp_buffer[i] >= '0' && temp_buffer[i] <= '9') {
+            ch = (unsigned char) (temp_buffer[i] - '0');
         } else {
             normal_error("cff","invalid character");
         }
@@ -1247,15 +1246,15 @@ static long pack_real(card8 * dest, long destlen, double value)
         pos++;
     }
     if (e != 0) {
-        sprintf(work_buffer, "%ld", e);
+        sprintf(temp_buffer, "%ld", e);
         for (i = 0; i < CFF_REAL_MAX_LEN; i++) {
             unsigned char ch = 0;
-            if (work_buffer[i] == '\0') {
+            if (temp_buffer[i] == '\0') {
                 break;
-            } else if (work_buffer[i] == '.') {
+            } else if (temp_buffer[i] == '.') {
                 ch = 0x0a;
-            } else if (work_buffer[i] >= '0' && work_buffer[i] <= '9') {
-                ch = (unsigned char) (work_buffer[i] - '0');
+            } else if (temp_buffer[i] >= '0' && temp_buffer[i] <= '9') {
+                ch = (unsigned char) (temp_buffer[i] - '0');
             } else {
                 normal_error("cff","invalid character");
             }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: LOGO10.otf
Type: application/octet-stream
Size: 2640 bytes
Desc: not available
URL: <http://mailman.ntg.nl/pipermail/dev-luatex/attachments/20181023/ae717dd8/attachment-0001.obj>


More information about the dev-luatex mailing list