foliojs / fontkit

An advanced font engine for Node and the browser
1.44k stars 210 forks source link

.advanceWidth triggers RangeError: Offset is outside the bounds of the DataView #303

Open iamakulov opened 1 year ago

iamakulov commented 1 year ago

Here’s a font called Noto Sans New Tai Lue from Google Fonts: H4cKBW-Pl9DZ0Xe_nHUapt7PovLXAhAnY7wqaLy-OJgU3p_pdeXAYUbghFPKzeY.ttf.zip

If you open this font file with Fontkit and try to read the advanceWidth of the space glyph, you’ll get a RangeError: Offset is outside the bounds of the DataView exception.

Steps to reproduce the issue:

  1. Download the font

  2. Run

    const fs = require("fs")
    const font = fs.readFileSync("./H4cKBW-Pl9DZ0Xe_nHUapt7PovLXAhAnY7wqaLy-OJgU3p_pdeXAYUbghFPKzeY.ttf")
    const fontObject = fontkit.create(font)
    console.log(fontObject.glyphsForString(" ")[0].advanceWidth)
  3. Observe the following error:

    RangeError: Offset is outside the bounds of the DataView
        at DataView.getInt16 (<anonymous>)
        at $8ae20583b93e4933$export$c18b354bac7948e9.<computed> [as readInt16BE] (/Users/iamakulov/Repos/FramerStudio/node_modules/restructure/dist/src/DecodeStream.js:72:33)
        at $af65abf7bf65ac42$export$fffa67e515d04022.decode (/Users/iamakulov/Repos/FramerStudio/node_modules/restructure/dist/src/Number.js:20:36)
        at $aa8b66bae6abe658$export$eabc71f011df675a._parseFields (/Users/iamakulov/Repos/FramerStudio/node_modules/restructure/dist/src/Struct.js:41:20)
        at $aa8b66bae6abe658$export$eabc71f011df675a.decode (/Users/iamakulov/Repos/FramerStudio/node_modules/restructure/dist/src/Struct.js:12:10)
        at $f680320fa07ef53d$export$2e2bcd8739ae039._getCBox (/Users/iamakulov/Repos/FramerStudio/node_modules/fontkit/dist/src/glyph/TTFGlyph.js:79:28)
        at $f680320fa07ef53d$export$2e2bcd8739ae039._getMetrics (/Users/iamakulov/Repos/FramerStudio/node_modules/fontkit/dist/src/glyph/TTFGlyph.js:318:21)
        at $f680320fa07ef53d$export$2e2bcd8739ae039.get advanceWidth (/Users/iamakulov/Repos/FramerStudio/node_modules/fontkit/dist/src/glyph/Glyph.js:146:17)
        at $f680320fa07ef53d$export$2e2bcd8739ae039.descriptor.get (/Users/iamakulov/Repos/FramerStudio/node_modules/fontkit/dist/src/decorators.js:10:23)
        at ...

Possibly related issue: https://github.com/foliojs/fontkit/issues/179\

Pomax commented 1 year ago

As a slightly more elaborate test, using https://fonts.google.com/noto/specimen/Noto+Sans+New+Tai+Lue:

const fs = require("fs");
const fontkit = require("fontkit");
const font = fs.readFileSync("./NotoSansNewTaiLue-Regular.ttf");
const fontObject = fontkit.create(font);
const glyphs = fontObject.glyphsForString(" ");
console.log(glyphs[0]);
console.log(glyphs[0].advanceWidth);

yields:

<ref *1> $f680320fa07ef53d$export$2e2bcd8739ae039 {
  id: 440,
  codePoints: [ 32 ],
  _font: $0a8ef2660a6ce4b6$export$2e2bcd8739ae039 {
    type: 'TTF',
    defaultLanguage: null,
    stream: $8ae20583b93e4933$export$c18b354bac7948e9 {
      buffer: <Buffer 00 01 00 00 00 10 01 00 00 04 00 00 47 44 45 46 09 41 09 81 00 00 01 c8 00 00 00 54 47 50 4f 53 a6 ee 44 e4 00 00 25 00 00 00 1d 04 47 53 55 42 9a 2e ... 47330 more bytes>,
      view: [DataView],
      pos: 268,
      length: 47380
    },
    variationCoords: null,
    _directoryPos: 0,
    _tables: { cmap: [Object] },
    _glyphs: { '440': [Circular *1] },
    directory: {
      tag: '\x00\x01\x00\x00',
      numTables: 16,
      searchRange: 256,
      entrySelector: 4,
      rangeShift: 0,
      tables: [Object]
    }
  },
  isMark: false,
  isLigature: false,
  type: 'TTF'
}
d:\temp\node_modules\restructure\dist\main.cjs:91
        const ret = this.view[key](this.pos, false);
                                  ^

RangeError: Offset is outside the bounds of the DataView
    at DataView.getInt16 (<anonymous>)
    at $8ae20583b93e4933$export$c18b354bac7948e9.<computed> [as readInt16BE] (d:\temp\node_modules\restructure\dist\main.cjs:91:35)
    at $af65abf7bf65ac42$export$fffa67e515d04022.decode (d:\temp\node_modules\restructure\dist\main.cjs:268:40)
    at $aa8b66bae6abe658$export$eabc71f011df675a._parseFields (d:\temp\node_modules\restructure\dist\main.cjs:732:29)
    at $aa8b66bae6abe658$export$eabc71f011df675a.decode (d:\temp\node_modules\restructure\dist\main.cjs:703:14)
    at $f680320fa07ef53d$export$2e2bcd8739ae039._getCBox (d:\temp\node_modules\fontkit\dist\main.cjs:10906:54)
    at $f680320fa07ef53d$export$2e2bcd8739ae039._getMetrics (d:\temp\node_modules\fontkit\dist\main.cjs:11074:25)
    at get advanceWidth (d:\temp\node_modules\fontkit\dist\main.cjs:10764:21)
    at descriptor.get (d:\temp\node_modules\fontkit\dist\main.cjs:92:29)
    at Object.<anonymous> (d:\temp\test.js:7:23)

Node.js v18.14.1
iamakulov commented 1 year ago

Yup, indeed! The exception happens only when you access .advanceWidth.