git.lucas.co / go_mono
git clone https://git.lucas.co/go_mono.git

commite6eecd499c2c22e58f3951ca087d4523a0b2860d
parent775e3b0c77
authorNigel Tao <[email protected]>
date2021-06-22 17:54
font/sfnt: fix parsing PostScript fonts' 4-byte numbers

Fixes golang/go#46836

Change-Id: Ie4ff2a9866d3f468d973e73857d6c44078c0695d
Reviewed-on: https://go-review.googlesource.com/c/image/+/329949
Trust: Nigel Tao <[email protected]>
Run-TryBot: Nigel Tao <[email protected]>
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Rob Pike <[email protected]>

 font/sfnt/postscript.go | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/font/sfnt/postscript.go b/font/sfnt/postscript.go
index b686e60..2a21997 100644
--- a/font/sfnt/postscript.go
+++ b/font/sfnt/postscript.go
@@ -795,6 +795,18 @@ func (p *psInterpreter) parseNumber() (hasResult bool, err error) {
 		}
 		number, hasResult = int32(u32(p.instructions[1:])), true
 		p.instructions = p.instructions[5:]
+		// 5177.Type2.pdf section 3.2 "Charstring Number Encoding" says "If the
+		// charstring byte contains the value 255... [this] number is
+		// interpreted as a Fixed; that is, a signed number with 16 bits of
+		// fraction".
+		//
+		// TODO: change the psType2CharstringsData.b.segments and
+		// psInterpreter.argStack data structures to optionally hold fixed
+		// point values, not just integer values. That's a substantial
+		// re-design, though. Until then, just round the 16.16 fixed point
+		// number to the closest integer value. This isn't just "number =
+		// ((number + 0x8000) >> 16)" because of potential overflow.
+		number = (number >> 16) + (1 & (number >> 15))
 	}
 
 	if hasResult {