summaryrefslogtreecommitdiff
path: root/src/lib/evas/common/evas_font_main.c
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-10-31 12:21:59 +0000
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-10-31 12:31:52 +0000
commit80d317f20ebdc521d62a443a30482cf05bf89a07 (patch)
tree179b38501272eab8fb79a249bd479309ebb01d4d /src/lib/evas/common/evas_font_main.c
parent72a5367f8dd0ceeefea3729dafedb970e47d0613 (diff)
evas - revert evas variation sequence support - out of bound accesses
This code is filled with out of bounds accesses now after the reverted patch. All those base_char+1, itr+1 etc. in evas_common_font_query_run_font_end_get() are accessing BEYOND the end of the run. textgrid shows this instantly to fall over as it uses single unicode codepoint chars with no nul terminator. As this api takes an explicit run_len we should never access beyond the end of the run_len. Please revisit this code and keep in mind proper memory/bounds accessing. If there was ano run_len and it assumed strings were regular strings that had to be nul terminated... then it might be ok, but not here. of course if i put in guards for these +1's then it ends up in infintie loops, so enough debugging and send it back for a rethink. :) .... Revert "evas_object_textblock: add support for variation sequences" This reverts commit 46f2d8acdcda3f374c9e393ecb734ff9d00fef7d.
Diffstat (limited to '')
-rw-r--r--src/lib/evas/common/evas_font_main.c296
1 files changed, 28 insertions, 268 deletions
diff --git a/src/lib/evas/common/evas_font_main.c b/src/lib/evas/common/evas_font_main.c
index c41e350dcf..1a163748ca 100644
--- a/src/lib/evas/common/evas_font_main.c
+++ b/src/lib/evas/common/evas_font_main.c
@@ -355,182 +355,33 @@ end:
355/* Set of common functions that are used in a couple of places. */ 355/* Set of common functions that are used in a couple of places. */
356 356
357static void 357static void
358_fash_int_map_and_variations_free(Fash_Int_Map *map)
359 {
360 if(!map)
361 return;
362 int i;
363
364 for (i = 0; i < 256; i++)
365 {
366 if (map->items[i].variations)
367 {
368 if (map->items[i].variations->list)
369 {
370 free(map->items[i].variations->list);
371 map->items[i].variations->list = NULL;
372 map->items[i].variations->capacity = 0;
373 map->items[i].variations->length = 0;
374 }
375 free(map->items[i].variations);
376 map->items[i].variations = NULL;
377 }
378 }
379
380 free(map);
381}
382
383static void
384_fash_int2_free(Fash_Int_Map2 *fash) 358_fash_int2_free(Fash_Int_Map2 *fash)
385 { 359{
386 int i; 360 int i;
387 if (fash) 361
388 { 362 for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]);
389 for (i = 0; i < 256; i++) 363 free(fash);
390 if (fash->bucket[i])
391 {
392 _fash_int_map_and_variations_free(fash->bucket[i]);
393 fash->bucket[i] = NULL;
394 }
395 free(fash);
396 fash = NULL;
397 }
398} 364}
399 365
400static void 366static void
401_fash_int_free(Fash_Int *fash) 367_fash_int_free(Fash_Int *fash)
402{ 368{
403 int i; 369 int i;
404 if (fash)
405 {
406 if (fash->MAGIC != FASH_INT_MAGIC)
407 {
408 return;
409 }
410 370
411 for (i = 0; i < 256; i++) 371 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]);
412 { 372 free(fash);
413 if (fash->bucket[i])
414 {
415 _fash_int2_free(fash->bucket[i]);
416 fash->bucket[i] = NULL;
417 }
418 }
419 free(fash);
420 }
421} 373}
422 374
423static Fash_Int * 375static Fash_Int *
424_fash_int_new(void) 376_fash_int_new(void)
425{ 377{
426 Fash_Int *fash = calloc(1, sizeof(Fash_Int)); 378 Fash_Int *fash = calloc(1, sizeof(Fash_Int));
427 EINA_SAFETY_ON_NULL_RETURN_VAL(fash, NULL);
428 fash->MAGIC = FASH_INT_MAGIC;
429 fash->freeme = _fash_int_free; 379 fash->freeme = _fash_int_free;
430 return fash; 380 return fash;
431} 381}
432 382
433static Fash_Item_variation_List *
434_variations_list_new(void)
435{
436 Fash_Item_variation_List *variations = calloc(1, sizeof(Fash_Item_variation_List));
437 EINA_SAFETY_ON_NULL_RETURN_VAL(variations, NULL);
438 variations->capacity = 0;
439 variations->length = 0;
440 variations->list = 0;
441 return variations;
442}
443
444static void
445_variations_list_add(Fash_Item_variation_List *variations,RGBA_Font_Int *fint, int index, Eina_Unicode variation_sequence)
446{
447 Fash_Item_variation_Index_Item *list = variations->list;
448 if (variations->capacity == variations->length)
449 {
450 list = (Fash_Item_variation_Index_Item *) realloc(list, (variations->capacity + 4) * sizeof(Fash_Item_variation_Index_Item));
451 if (list)
452 {
453 variations->list = list;
454 variations->capacity += 4;
455 }
456 }
457
458 EINA_SAFETY_ON_NULL_RETURN(list);
459
460 int start = 0;
461 int end = variations->length;
462 if (end == 0)
463 {
464 // if only on element just add it in 0 index
465 variations->list[0].item.fint = fint;
466 variations->list[0].item.index = index;
467 variations->list[0].variation_sequence = variation_sequence;
468 variations->length++;
469 }
470 else
471 {
472 // find lower bound
473 while (end > start)
474 {
475 int middle = start + (end - start) / 2;
476 if (variations->list[middle].variation_sequence >= variation_sequence)
477 end = middle;
478 else
479 start = middle + 1;
480 }
481
482 // if passed value founded in list, just replace it
483 if (start < (int)variations->length && variations->list[start].variation_sequence == variation_sequence)
484 {
485 variations->list[start].item.fint = fint;
486 variations->list[start].item.index = index;
487 variations->list[start].variation_sequence = variation_sequence;
488 return;
489 }
490
491 // shift array to insert item
492 for (int i = (variations->length - 1) ; i >= start; i--)
493 {
494 variations->list[i + 1] = variations->list[i];
495 }
496
497 // insert new item and keep array sorted
498 variations->list[start].item.fint = fint;
499 variations->list[start].item.index = index;
500 variations->list[start].variation_sequence = variation_sequence;
501 variations->length++;
502 }
503}
504
505
506static Fash_Item_Index_Map * 383static Fash_Item_Index_Map *
507_variations_list_find(Fash_Item_variation_List * variations, Eina_Unicode variation_sequence) 384_fash_int_find(Fash_Int *fash, int item)
508{
509 if (!variations)
510 return NULL;
511
512 if (!variations->list)
513 return NULL;
514
515 int start = 0;
516 int end = variations->length;
517
518 while(end > start)
519 {
520 int middle = start + (end - start) / 2;
521 if (variations->list[middle].variation_sequence == variation_sequence)
522 return &(variations->list[middle].item);
523 else if (variations->list[middle].variation_sequence < variation_sequence)
524 start = middle + 1;
525 else
526 end = middle - 1;
527 }
528
529 return NULL;
530}
531
532static const Fash_Item_Index_Map *
533_fash_int_find(Fash_Int *fash, int item, Eina_Unicode variation_sequence)
534{ 385{
535 int grp, maj, min; 386 int grp, maj, min;
536 387
@@ -540,22 +391,14 @@ _fash_int_find(Fash_Int *fash, int item, Eina_Unicode variation_sequence)
540 min = item & 0xff; 391 min = item & 0xff;
541 if (!fash->bucket[grp]) return NULL; 392 if (!fash->bucket[grp]) return NULL;
542 if (!fash->bucket[grp]->bucket[maj]) return NULL; 393 if (!fash->bucket[grp]->bucket[maj]) return NULL;
543 if (!variation_sequence) 394 return &(fash->bucket[grp]->bucket[maj]->item[min]);
544 return &(fash->bucket[grp]->bucket[maj]->items[min].item);
545 else
546 return _variations_list_find(fash->bucket[grp]->bucket[maj]->items[min].variations, variation_sequence);
547} 395}
548 396
549static void 397static void
550_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx, Eina_Unicode variation_sequence) 398_fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx)
551{ 399{
552 int grp, maj, min; 400 int grp, maj, min;
553 401
554 // If we already have cached passed item, skip adding it again
555 const Fash_Item_Index_Map *fm = _fash_int_find(fash, item, variation_sequence);
556 if (fm && fm->fint)
557 return;
558
559 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) 402 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
560 grp = (item >> 16) & 0xff; 403 grp = (item >> 16) & 0xff;
561 maj = (item >> 8) & 0xff; 404 maj = (item >> 8) & 0xff;
@@ -566,20 +409,8 @@ _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int idx, Eina_Unico
566 if (!fash->bucket[grp]->bucket[maj]) 409 if (!fash->bucket[grp]->bucket[maj])
567 fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map)); 410 fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map));
568 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]); 411 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]);
569 if (variation_sequence) 412 fash->bucket[grp]->bucket[maj]->item[min].fint = fint;
570 { 413 fash->bucket[grp]->bucket[maj]->item[min].index = idx;
571 if (!fash->bucket[grp]->bucket[maj]->items[min].variations)
572 {
573 fash->bucket[grp]->bucket[maj]->items[min].variations =_variations_list_new();
574 EINA_SAFETY_ON_NULL_RETURN(fash->bucket[grp]->bucket[maj]->items[min].variations);
575 }
576 _variations_list_add(fash->bucket[grp]->bucket[maj]->items[min].variations, fint, idx, variation_sequence);
577 }
578 else
579 {
580 fash->bucket[grp]->bucket[maj]->items[min].item.fint = fint;
581 fash->bucket[grp]->bucket[maj]->items[min].item.index = idx;
582 }
583} 414}
584 415
585static void 416static void
@@ -631,45 +462,24 @@ _fash_gl2_free(Fash_Glyph_Map2 *fash)
631 int i; 462 int i;
632 463
633 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) 464 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
634 for (i = 0; i < 256; i++) 465 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_glyph_free(fash->bucket[i]);
635 {
636 if (fash->bucket[i])
637 {
638 _fash_glyph_free(fash->bucket[i]);
639 fash->bucket[i] = NULL;
640 }
641 }
642 free(fash); 466 free(fash);
643} 467}
644 468
645static void 469static void
646_fash_gl_free(Fash_Glyph *fash) 470_fash_gl_free(Fash_Glyph *fash)
647{ 471{
648 if (fash) 472 int i;
649 {
650 if (fash->MAGIC != FASH_GLYPH_MAGIC)
651 return;
652 473
653 int i; 474 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16)
654 // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) 475 for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]);
655 for (i = 0; i < 256; i++) 476 free(fash);
656 {
657 if (fash->bucket[i])
658 {
659 _fash_gl2_free(fash->bucket[i]);
660 fash->bucket[i] = NULL;
661 }
662 }
663 free(fash);
664 }
665} 477}
666 478
667static Fash_Glyph * 479static Fash_Glyph *
668_fash_gl_new(void) 480_fash_gl_new(void)
669{ 481{
670 Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph)); 482 Fash_Glyph *fash = calloc(1, sizeof(Fash_Glyph));
671 EINA_SAFETY_ON_NULL_RETURN_VAL(fash, NULL);
672 fash->MAGIC = FASH_GLYPH_MAGIC;
673 fash->freeme = _fash_gl_free; 483 fash->freeme = _fash_gl_free;
674 return fash; 484 return fash;
675} 485}
@@ -870,7 +680,7 @@ struct _Font_Char_Index
870}; 680};
871 681
872EAPI FT_UInt 682EAPI FT_UInt
873evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode variation_sequence) 683evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl)
874{ 684{
875 static const unsigned short mapfix[] = 685 static const unsigned short mapfix[] =
876 { 686 {
@@ -932,10 +742,7 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
932 * that something else try to use it. 742 * that something else try to use it.
933 */ 743 */
934 /* FTLOCK(); */ 744 /* FTLOCK(); */
935 if (variation_sequence) 745 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
936 result.index = FT_Face_GetCharVariantIndex(fi->src->ft.face, gl, variation_sequence);
937 else
938 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
939 /* FTUNLOCK(); */ 746 /* FTUNLOCK(); */
940 result.gl = gl; 747 result.gl = gl;
941 748
@@ -967,10 +774,7 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
967 { 774 {
968 gl = mapfix[(i << 1) + 1]; 775 gl = mapfix[(i << 1) + 1];
969 FTLOCK(); 776 FTLOCK();
970 if (variation_sequence) 777 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
971 result.index = FT_Face_GetCharVariantIndex(fi->src->ft.face, gl, variation_sequence);
972 else
973 result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
974 FTUNLOCK(); 778 FTUNLOCK();
975 break; 779 break;
976 } 780 }
@@ -995,49 +799,20 @@ evas_common_get_char_index(RGBA_Font_Int* fi, Eina_Unicode gl, Eina_Unicode vari
995 return result.index; 799 return result.index;
996} 800}
997 801
998
999/*
1000 * @internal
1001 * Search for unicode glyph inside all font files, and return font and glyph index
1002 *
1003 * @param[in] fn the font to use.
1004 * @param[out] fi_ret founded font.
1005 * @param[in] gl unicode glyph to search for
1006 * @param[in] variation_sequence for the gl glyph
1007 * @param[in] evas_font_search_options search options when searching font files
1008 *
1009 */
1010
1011EAPI int 802EAPI int
1012evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl, Eina_Unicode variation_sequence, uint32_t evas_font_search_options) 803evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicode gl)
1013{ 804{
1014 Eina_List *l; 805 Eina_List *l;
1015 806
1016 if (fn->fash) 807 if (fn->fash)
1017 { 808 {
1018 const Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl, variation_sequence); 809 Fash_Item_Index_Map *fm = _fash_int_find(fn->fash, gl);
1019 if (fm) 810 if (fm)
1020 { 811 {
1021 if (fm->fint) 812 if (fm->fint)
1022 { 813 {
1023 if (evas_font_search_options == EVAS_FONT_SEARCH_OPTION_NONE) 814 *fi_ret = fm->fint;
1024 { 815 return fm->index;
1025 *fi_ret = fm->fint;
1026 return fm->index;
1027 }
1028 else if( (evas_font_search_options & EVAS_FONT_SEARCH_OPTION_SKIP_COLOR) == EVAS_FONT_SEARCH_OPTION_SKIP_COLOR)
1029 {
1030 if (!fm->fint->src->ft.face)
1031 {
1032 evas_common_font_int_reload(fm->fint);
1033 }
1034
1035 if (fm->fint->src->ft.face && !FT_HAS_COLOR(fm->fint->src->ft.face))
1036 {
1037 *fi_ret = fm->fint;
1038 return fm->index;
1039 }
1040 }
1041 } 816 }
1042 else if (fm->index == -1) return 0; 817 else if (fm->index == -1) return 0;
1043 } 818 }
@@ -1076,35 +851,20 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, Eina_Unicod
1076 } 851 }
1077 if (fi->src->ft.face) 852 if (fi->src->ft.face)
1078 { 853 {
1079 Eina_Bool is_color_only = (evas_font_search_options & EVAS_FONT_SEARCH_OPTION_SKIP_COLOR) == EVAS_FONT_SEARCH_OPTION_SKIP_COLOR && 854 idx = evas_common_get_char_index(fi, gl);
1080 FT_HAS_COLOR(fi->src->ft.face);
1081
1082 if (is_color_only)
1083 {
1084 /* This is color font ignore it */
1085 continue;
1086 }
1087
1088 idx = (int) evas_common_get_char_index(fi, gl, variation_sequence);
1089 if (idx != 0) 855 if (idx != 0)
1090 { 856 {
1091 if (!fi->ft.size) 857 if (!fi->ft.size)
1092 evas_common_font_int_load_complete(fi); 858 evas_common_font_int_load_complete(fi);
1093 if (!is_color_only) 859 if (!fn->fash) fn->fash = _fash_int_new();
1094 { 860 if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx);
1095 if (!fn->fash) fn->fash = _fash_int_new();
1096 if (fn->fash) _fash_int_add(fn->fash, gl, fi, idx, variation_sequence);
1097 }
1098 *fi_ret = fi; 861 *fi_ret = fi;
1099 return idx; 862 return idx;
1100 } 863 }
1101 else 864 else
1102 { 865 {
1103 if (!is_color_only) 866 if (!fn->fash) fn->fash = _fash_int_new();
1104 { 867 if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1);
1105 if (!fn->fash) fn->fash = _fash_int_new();
1106 if (fn->fash) _fash_int_add(fn->fash, gl, NULL, -1, variation_sequence);
1107 }
1108 } 868 }
1109 } 869 }
1110 } 870 }