/* uuterm, Copyright (C) 2006 Rich Felker; licensed under GNU GPL v2 only */ /* note: the following implementation of ucf is NOT SECURE. malicious or * damaged files can cause it to crash or possibly enter into an infinite * loop, or cause other parts of the process core to be read as a font, * possibly leading to information leaks. however there is no possibility * of privilege elevation as ucf never writes to memory. * * users needing a robust implementation would be advised to simply run a * sanity check across the whole font file before accepting it, rather than * incurring large bounds-checking penalties at each glyph lookup. */ #include #include #include "ucf.h" #define U24(p) ( ((p)[0]<<16) | ((p)[1]<<8) | (p)[2] ) #define U32(p) ( ((p)[0]<<24) | U24((p)+1) ) int ucf_init(struct ucf *f, const unsigned char *map, size_t len) { size_t n; if (memcmp(map, "ucf\300\000\001\000\000", 8)) return -1; f->w = map[8]; f->h = map[9]; f->s = (f->w+7)>>3; f->S = f->s * f->h; f->ranges = map + U32(map+20) + 4; f->gmap = map + U32(map+24); f->glyphs = map + U32(map+28); f->nglyphs = (len - (f->glyphs - map)) / f->S; f->ctab = f->ranges + 8*(f->nranges = U32(f->ranges - 4)); return 0; } #define GMAP_WIDTH 1 #define GMAP_FINAL1 0 #define GMAP_FINAL2 1 #define GMAP_GLYPH1 2 #define GMAP_GLYPH2 3 #define RULE_RANGE 4 #define RULE_ATTACHED_TO 5 #define RULE_WITH_ATTACHED 6 #define RULE_FOLLOWS 7 #define RULE_PRECEDES 8 #define CTAB_MASK 0x3fffffff #define CTAB_INDIRECT 0x80000000 #define CTAB_WIDTH 30 int ucf_lookup(struct ucf *f, int idx, const unsigned *cc, const unsigned *pc, const unsigned *nc, int width) { unsigned ch = cc[idx]; unsigned a, l, x, i; const unsigned *c; const unsigned char *p; for (p=f->ranges, a=0; ch>=(a+=U32(p)); p+=8) { if (ch-a < (l=U32(p+4))) { x = U32(f->ctab+4*(a-1)); if (x>>30 != width-1) return -1; return (x & 0x3fffffff) + (ch-a)*width; } ch -= l; } x = U32(f->ctab+4*ch); if (!((x+1) & CTAB_INDIRECT)) { if (x>>CTAB_WIDTH != width-1) return -1; return x & CTAB_MASK; } x &= 0x7fffffff; i = idx; c = cc; for (p=f->gmap+x; ; p+=4) { if (*p <= GMAP_GLYPH2) { if ((*p & GMAP_WIDTH) == width-1) break; else if (*p <= GMAP_FINAL2) return -1; i = idx; c = cc; continue; } x = *p; a = U24(p+1); if (p[4] == RULE_RANGE) { p += 4; l = U24(p+1); } else l = 1; switch (x) { case RULE_ATTACHED_TO: if (i > idx) i = idx; if (i && c[--i]-a < l) continue; break; case RULE_WITH_ATTACHED: if (i < idx) i = idx; if (c[++i]-a < l) continue; break; case RULE_FOLLOWS: if ((c=pc)[i=0]-a < l) continue; break; case RULE_PRECEDES: if ((c=nc)[i=0]-a < l) continue; break; } /* Skip until the next mapping */ for (; *p > GMAP_GLYPH2; p+=4); i = idx; c = cc; } return U24(p+1); } #if 0 #include #include int main(int argc, char *argv[]) { int i, j; struct ucf f; static char tmp[1000000]; ucf_init(&f, tmp, fread(tmp, 1, sizeof tmp, stdin)); for (i=1; i= 0) for (j=0; j<16; j++) printf("%.2X", f.glyphs[16*g+j]); printf("\n"); } return 0; } #endif