d2lang/d2 · error

invalid %s table bounds

Error message

invalid %s table bounds

What it means

sfntTable parses the sfnt table directory of a TrueType/OpenType font to extract a named table (e.g. 'kern'). It validates that the table's offset and length from the directory record fall within the raw font bytes before slicing. If offset/length would go outside src (including overflow making offset negative), it returns this error instead of panicking on a bad slice.

Source

Thrown at lib/textmeasure/fontface.go:218

		if base < 0 || base+12 > len(src) {
			return nil, fmt.Errorf("invalid font collection offset")
		}
	}

	n := int(binary.BigEndian.Uint16(src[base+4 : base+6]))
	records := base + 12
	if n > (len(src)-records)/16 {
		return nil, fmt.Errorf("invalid sfnt table directory")
	}
	for i := 0; i < n; i++ {
		record := src[records+16*i : records+16*(i+1)]
		if string(record[:4]) != tag {
			continue
		}
		offset := int(binary.BigEndian.Uint32(record[8:12]))
		length := int(binary.BigEndian.Uint32(record[12:16]))
		if offset < 0 || length < 0 || offset > len(src)-length {
			return nil, fmt.Errorf("invalid %s table bounds", tag)
		}
		return src[offset : offset+length], nil
	}
	return nil, nil
}

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Verify the font file is a complete, valid TTF/OTF (e.g. open with fonttools or check magic bytes 0x00010000/Otto/true/ttcf)
  2. Re-download or re-copy the font asset; check size against upstream
  3. If fonts ship via git-lfs, ensure files are actually materialized, not pointer stubs
  4. If processing untrusted fonts, treat this error as a rejection of the input rather than a bug

Example fix

// before
raw, _ := os.ReadFile("font.ttf") // truncated file
face, err := NewFontFace(raw)
// after
info, _ := os.Stat("font.ttf")
if info.Size() < 12 { return fmt.Errorf("font file truncated") }
face, err := NewFontFace(raw)
Defensive patterns

Strategy: validation

Validate before calling

func validateTTF(src []byte) error {
    if len(src) < 12 { return fmt.Errorf("font too short") }
    return nil // plus check non-truncated file size before use
}

Type guard

func looksLikeSFNT(src []byte) bool {
    if len(src) < 12 { return false }
    switch string(src[:4]) {
    case "\x00\x01\x00\x00", "Otto", "true", "ttcf":
        return true
    }
    return false
}

Try / catch

table, err := sfntTable(src, "kern")
if err != nil {
    log.Printf("rejecting font: %v", err)
    return ErrBadFontAsset
}

Prevention

When it happens

Trigger: Calling d2fonts/fontface loading with a corrupt or truncated .ttf/.otf file, a hand-crafted/malicious font whose table directory declares an offset+length beyond the file, or a font whose Uint32 offset overflows int on 32-bit platforms. Reached via parseLegacyKern while initializing a FontFace for text measurement.

Common situations: Embedding a partially-downloaded or git-lfs-pointer font file; bundling a corrupted font asset; fuzzed/hostile font input; wasm builds where int is 32-bit and large offsets overflow negative.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/7e2bd9c23925ac99. Report an issue: GitHub.