diff options
Diffstat (limited to 'src/sfnt.c')
-rw-r--r-- | src/sfnt.c | 726 |
1 files changed, 445 insertions, 281 deletions
diff --git a/src/sfnt.c b/src/sfnt.c index aa8b49a9ecd..8598b052044 100644 --- a/src/sfnt.c +++ b/src/sfnt.c @@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <fcntl.h> #include <intprops.h> #include <inttypes.h> +#include <stdckdint.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -663,14 +664,13 @@ sfnt_read_cmap_format_8 (int fd, min_size = SFNT_ENDOF (struct sfnt_cmap_format_8, num_groups, uint32_t); - if (INT_MULTIPLY_WRAPV (format8->num_groups, sizeof *format8->groups, - &temp)) + if (ckd_mul (&temp, format8->num_groups, sizeof *format8->groups)) { xfree (format8); return NULL; } - if (INT_ADD_WRAPV (min_size, temp, &min_size)) + if (ckd_add (&min_size, min_size, temp)) { xfree (format8); return NULL; @@ -755,14 +755,13 @@ sfnt_read_cmap_format_12 (int fd, min_size = SFNT_ENDOF (struct sfnt_cmap_format_12, num_groups, uint32_t); - if (INT_MULTIPLY_WRAPV (format12->num_groups, sizeof *format12->groups, - &temp)) + if (ckd_mul (&temp, format12->num_groups, sizeof *format12->groups)) { xfree (format12); return NULL; } - if (INT_ADD_WRAPV (min_size, temp, &min_size)) + if (ckd_add (&min_size, min_size, temp)) { xfree (format12); return NULL; @@ -841,9 +840,8 @@ sfnt_read_cmap_format_14 (int fd, 14 cmap table. */ size = sizeof *format14; - if (INT_MULTIPLY_WRAPV (num_records, sizeof *format14->records, - &temp) - || INT_ADD_WRAPV (size, temp, &size)) + if (ckd_mul (&temp, num_records, sizeof *format14->records) + || ckd_add (&size, size, temp)) return NULL; format14 = xmalloc (size); @@ -901,7 +899,7 @@ sfnt_read_cmap_table_1 (int fd, uint32_t directory_offset, off_t offset; struct sfnt_cmap_encoding_subtable_data header; - if (INT_ADD_WRAPV (directory_offset, table_offset, &offset)) + if (ckd_add (&offset, directory_offset, table_offset)) return (struct sfnt_cmap_encoding_subtable_data *) -1; if (lseek (fd, offset, SEEK_SET) == (off_t) -1) @@ -1937,8 +1935,11 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, simple->instructions comes one word past number_of_contours, because end_pts_of_contours also contains the instruction length. */ - simple->instructions = (uint8_t *) (simple->end_pts_of_contours - + glyph->number_of_contours + 1); + + simple->x_coordinates = (int16_t *) (simple->end_pts_of_contours + + glyph->number_of_contours + 1); + simple->y_coordinates = simple->x_coordinates + number_of_points; + simple->instructions = (uint8_t *) (simple->y_coordinates + number_of_points); simple->flags = simple->instructions + simple->instruction_length; /* Read instructions into the glyph. */ @@ -2022,7 +2023,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, /* Now that the flags have been decoded, start decoding the vectors. */ - simple->x_coordinates = (int16_t *) (simple->flags + number_of_points); vec_start = flags_start; i = 0; x = 0; @@ -2080,7 +2080,6 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph, pointer to the flags for the current vector. */ flags_start = simple->flags; y = 0; - simple->y_coordinates = simple->x_coordinates + i; i = 0; while (i < number_of_points) @@ -2631,24 +2630,21 @@ sfnt_expand_compound_glyph_context (struct sfnt_compound_glyph_context *context, size_t size_bytes; /* Add each field while checking for overflow. */ - if (INT_ADD_WRAPV (number_of_contours, context->num_end_points, - &context->num_end_points)) + if (ckd_add (&context->num_end_points, number_of_contours, + context->num_end_points)) return 1; - if (INT_ADD_WRAPV (number_of_points, context->num_points, - &context->num_points)) + if (ckd_add (&context->num_points, number_of_points, context->num_points)) return 1; /* Reallocate each array to the new size if necessary. */ if (context->points_size < context->num_points) { - if (INT_MULTIPLY_WRAPV (context->num_points, 2, - &context->points_size)) + if (ckd_mul (&context->points_size, context->num_points, 2)) context->points_size = context->num_points; - if (INT_MULTIPLY_WRAPV (context->points_size, - sizeof *context->x_coordinates, - &size_bytes)) + if (ckd_mul (&size_bytes, context->points_size, + sizeof *context->x_coordinates)) return 1; context->x_coordinates = xrealloc (context->x_coordinates, @@ -2672,13 +2668,11 @@ sfnt_expand_compound_glyph_context (struct sfnt_compound_glyph_context *context, if (context->end_points_size < context->num_end_points) { - if (INT_MULTIPLY_WRAPV (context->num_end_points, 2, - &context->end_points_size)) + if (ckd_mul (&context->end_points_size, context->num_end_points, 2)) context->end_points_size = context->num_end_points; - if (INT_MULTIPLY_WRAPV (context->end_points_size, - sizeof *context->contour_end_points, - &size_bytes)) + if (ckd_mul (&size_bytes, context->end_points_size, + sizeof *context->contour_end_points)) return 1; context->contour_end_points @@ -2804,12 +2798,6 @@ sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph, if (component->flags & 04000) /* SCALED_COMPONENT_OFFSET */ sfnt_transform_coordinates (component, &x, &y, 1, 0, 0); - - if (component->flags & 04) /* ROUND_XY_TO_GRID */ - { - x = sfnt_round_fixed (x); - y = sfnt_round_fixed (y); - } } else { @@ -3766,7 +3754,23 @@ sfnt_multiply_divide_2 (struct sfnt_large_integer *ab, return q; } -#endif +/* Add the specified unsigned 32-bit N to the large integer + INTEGER. */ + +static void +sfnt_large_integer_add (struct sfnt_large_integer *integer, + uint32_t n) +{ + struct sfnt_large_integer number; + + number.low = integer->low + n; + number.high = integer->high + (number.low + < integer->low); + + *integer = number; +} + +#endif /* !INT64_MAX */ /* Calculate (A * B) / C with no rounding and return the result, using a 64 bit integer if necessary. */ @@ -3779,32 +3783,37 @@ sfnt_multiply_divide (unsigned int a, unsigned int b, unsigned int c) sfnt_multiply_divide_1 (a, b, &temp); return sfnt_multiply_divide_2 (&temp, c); -#else +#else /* INT64_MAX */ uint64_t temp; temp = (uint64_t) a * (uint64_t) b; return temp / c; -#endif +#endif /* !INT64_MAX */ } -#ifndef INT64_MAX - -/* Add the specified unsigned 32-bit N to the large integer - INTEGER. */ +/* Calculate (A * B) / C with rounding and return the result, using a + 64 bit integer if necessary. */ -static void -sfnt_large_integer_add (struct sfnt_large_integer *integer, - uint32_t n) +static unsigned int +sfnt_multiply_divide_rounded (unsigned int a, unsigned int b, + unsigned int c) { - struct sfnt_large_integer number; +#ifndef INT64_MAX + struct sfnt_large_integer temp; - number.low = integer->low + n; - number.high = integer->high + (number.low - < integer->low); + sfnt_multiply_divide_1 (a, b, &temp); + sfnt_large_integer_add (&temp, c / 2); + return sfnt_multiply_divide_2 (&temp, c); +#else /* INT64_MAX */ + uint64_t temp; - *integer = number; + temp = (uint64_t) a * (uint64_t) b + c / 2; + return temp / c; +#endif /* !INT64_MAX */ } +#ifndef INT64_MAX + /* Calculate (A * B) / C, rounding the result with a threshold of N. Use a 64 bit temporary. */ @@ -3819,9 +3828,9 @@ sfnt_multiply_divide_round (unsigned int a, unsigned int b, return sfnt_multiply_divide_2 (&temp, c); } -#endif /* INT64_MAX */ +#endif /* !INT64_MAX */ -/* The same as sfnt_multiply_divide, but handle signed values +/* The same as sfnt_multiply_divide_rounded, but handle signed values instead. */ MAYBE_UNUSED static int @@ -3840,8 +3849,8 @@ sfnt_multiply_divide_signed (int a, int b, int c) if (c < 0) sign = -sign; - return (sfnt_multiply_divide (abs (a), abs (b), abs (c)) - * sign); + return (sfnt_multiply_divide_rounded (abs (a), abs (b), + abs (c)) * sign); } /* Multiply the two 16.16 fixed point numbers X and Y. Return the @@ -3857,7 +3866,7 @@ sfnt_mul_fixed (sfnt_fixed x, sfnt_fixed y) /* This can be done quickly with int64_t. */ return product / (int64_t) 65536; -#else +#else /* !INT64_MAX */ int sign; sign = 1; @@ -3870,7 +3879,7 @@ sfnt_mul_fixed (sfnt_fixed x, sfnt_fixed y) return sfnt_multiply_divide (abs (x), abs (y), 65536) * sign; -#endif +#endif /* INT64_MAX */ } /* Multiply the two 16.16 fixed point numbers X and Y, with rounding @@ -3887,7 +3896,7 @@ sfnt_mul_fixed_round (sfnt_fixed x, sfnt_fixed y) /* This can be done quickly with int64_t. */ return (product + round) / (int64_t) 65536; -#else +#else /* !INT64_MAX */ int sign; sign = 1; @@ -3900,7 +3909,7 @@ sfnt_mul_fixed_round (sfnt_fixed x, sfnt_fixed y) return sfnt_multiply_divide_round (abs (x), abs (y), 32768, 65536) * sign; -#endif +#endif /* INT64_MAX */ } /* Set the pen size to the specified point and return. POINT will be @@ -5087,7 +5096,7 @@ sfnt_poly_edges_exact (struct sfnt_fedge *edges, size_t nedges, raster.scanlines = height; raster.chunks = NULL; - if (!INT_MULTIPLY_OK (height, sizeof *raster.steps, &size)) + if (ckd_mul (&size, height, sizeof *raster.steps)) abort (); raster.steps = xzalloc (size); @@ -5473,8 +5482,6 @@ be as well. */ next = next->next; xfree (last); } - -#undef ONE_PIXEL } /* Apply winding rule to the coverage value VALUE. Convert VALUE to a @@ -6020,11 +6027,10 @@ sfnt_read_meta_table (int fd, struct sfnt_offset_subtable *subtable) so an unswapped copy of the whole meta contents must be retained. */ - if (INT_MULTIPLY_WRAPV (sizeof *meta->data_maps, meta->num_data_maps, - &map_size) + if (ckd_mul (&map_size, sizeof *meta->data_maps, meta->num_data_maps) /* Do so while checking for overflow from bad sfnt files. */ - || INT_ADD_WRAPV (map_size, sizeof *meta, &data_size) - || INT_ADD_WRAPV (data_size, directory->length, &data_size)) + || ckd_add (&data_size, map_size, sizeof *meta) + || ckd_add (&data_size, data_size, directory->length)) { xfree (meta); return NULL; @@ -6074,9 +6080,8 @@ sfnt_read_meta_table (int fd, struct sfnt_offset_subtable *subtable) /* Verify the data offsets. Overflow checking is particularly important here. */ - if (INT_ADD_WRAPV (meta->data_maps[i].data_offset, - meta->data_maps[i].data_length, - &offset)) + if (ckd_add (&offset, meta->data_maps[i].data_offset, + meta->data_maps[i].data_length)) { xfree (meta); return NULL; @@ -6162,9 +6167,7 @@ sfnt_read_ttc_header (int fd) /* Now, read the variable length data. Make sure to check for overflow. */ - if (INT_MULTIPLY_WRAPV (ttc->num_fonts, - sizeof *ttc->offset_table, - &size)) + if (ckd_mul (&size, ttc->num_fonts, sizeof *ttc->offset_table)) { xfree (ttc); return NULL; @@ -6195,7 +6198,7 @@ sfnt_read_ttc_header (int fd) size = (SFNT_ENDOF (struct sfnt_ttc_header, ul_dsig_offset, uint32_t) - offsetof (struct sfnt_ttc_header, ul_dsig_tag)); - rc = read (fd, &ttc->ul_dsig_offset, size); + rc = read (fd, &ttc->ul_dsig_tag, size); if (rc == -1 || rc < size) { xfree (ttc); @@ -6283,7 +6286,7 @@ sfnt_read_cvt_table (int fd, struct sfnt_offset_subtable *subtable) return NULL; /* Figure out the minimum amount that has to be read. */ - if (INT_ADD_WRAPV (sizeof *cvt, directory->length, &required)) + if (ckd_add (&required, directory->length, sizeof *cvt)) return NULL; /* Allocate enough for that much data. */ @@ -6334,7 +6337,7 @@ sfnt_read_fpgm_table (int fd, struct sfnt_offset_subtable *subtable) return NULL; /* Figure out the minimum amount that has to be read. */ - if (INT_ADD_WRAPV (sizeof *fpgm, directory->length, &required)) + if (ckd_add (&required, directory->length, sizeof *fpgm)) return NULL; /* Allocate enough for that much data. */ @@ -6382,7 +6385,7 @@ sfnt_read_prep_table (int fd, struct sfnt_offset_subtable *subtable) return NULL; /* Figure out the minimum amount that has to be read. */ - if (INT_ADD_WRAPV (sizeof *prep, directory->length, &required)) + if (ckd_add (&required, directory->length, sizeof *prep)) return NULL; /* Allocate enough for that much data. */ @@ -6470,19 +6473,21 @@ sfnt_mul_f26dot6 (sfnt_f26dot6 a, sfnt_f26dot6 b) #endif } -/* Multiply the specified 2.14 number with another signed 32 bit - number. Return the result as a signed 32 bit number. */ +/* Multiply the specified two 26.6 fixed point numbers A and B, with + rounding. Return the result, or an undefined value upon + overflow. */ -static int32_t -sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) +static sfnt_f26dot6 +sfnt_mul_f26dot6_round (sfnt_f26dot6 a, sfnt_f26dot6 b) { #ifdef INT64_MAX int64_t product; product = (int64_t) a * (int64_t) b; - return product / (int64_t) 16384; -#else + /* This can be done quickly with int64_t. */ + return (product + 32) / (int64_t) 64; +#else /* !INT64_MAX */ int sign; sign = 1; @@ -6493,61 +6498,48 @@ sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) if (b < 0) sign = -sign; - return sfnt_multiply_divide (abs (a), abs (b), - 16384) * sign; -#endif + return sfnt_multiply_divide_round (abs (a), abs (b), + 32, 64) * sign; +#endif /* INT64_MAX */ } -/* Multiply the specified 26.6 fixed point number X by the specified - 16.16 fixed point number Y with symmetric rounding. - - The 26.6 fixed point number must fit inside -32768 to 32767.ffff. - Value is otherwise undefined. */ +/* Multiply the specified 2.14 number with another signed 32 bit + number. Return the result as a signed 32 bit number. */ -static sfnt_f26dot6 -sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y) +static int32_t +sfnt_mul_f2dot14 (sfnt_f2dot14 a, int32_t b) { #ifdef INT64_MAX - uint64_t product; - int sign; - - sign = 1; - - if (x < 0) - { - x = -x; - sign = -sign; - } - - if (y < 0) - { - y = -y; - sign = -sign; - } + int64_t product; - product = (uint64_t) y * (uint64_t) x; + product = (int64_t) a * (int64_t) b; - /* This can be done quickly with int64_t. */ - return ((int64_t) (product + 32768) - / (int64_t) 65536) * sign; + return product / (int64_t) 16384; #else - struct sfnt_large_integer temp; int sign; sign = 1; - if (x < 0) + if (a < 0) sign = -sign; - if (y < 0) + if (b < 0) sign = -sign; - sfnt_multiply_divide_1 (abs (x), abs (y), &temp); - sfnt_large_integer_add (&temp, 32676); - return sfnt_multiply_divide_2 (&temp, 65536) * sign; + return sfnt_multiply_divide (abs (a), abs (b), + 16384) * sign; #endif } +/* Multiply the specified 26.6 fixed point number X by the specified + 16.16 fixed point number Y with rounding. */ + +static sfnt_f26dot6 +sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y) +{ + return sfnt_mul_fixed_round (x, y); +} + /* Return the floor of the specified 26.6 fixed point value X. */ static sfnt_f26dot6 @@ -6645,59 +6637,51 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp, size = sizeof (*interpreter); /* Add program stack. */ - if (INT_ADD_WRAPV ((maxp->max_stack_elements - * sizeof *interpreter->stack), - size, &size)) + if (ckd_add (&size, size, (maxp->max_stack_elements + * sizeof *interpreter->stack))) return NULL; /* Add twilight zone. */ - if (INT_ADD_WRAPV ((maxp->max_twilight_points - * sizeof *interpreter->twilight_x), - size, &size)) + if (ckd_add (&size, size, (maxp->max_twilight_points + * sizeof *interpreter->twilight_x))) return NULL; - if (INT_ADD_WRAPV ((maxp->max_twilight_points - * sizeof *interpreter->twilight_y), - size, &size)) + if (ckd_add (&size, size, (maxp->max_twilight_points + * sizeof *interpreter->twilight_y))) return NULL; - if (INT_ADD_WRAPV ((maxp->max_twilight_points - * sizeof *interpreter->twilight_y), - size, &size)) + if (ckd_add (&size, size, (maxp->max_twilight_points + * sizeof *interpreter->twilight_y))) return NULL; - if (INT_ADD_WRAPV ((maxp->max_twilight_points - * sizeof *interpreter->twilight_y), - size, &size)) + if (ckd_add (&size, size, (maxp->max_twilight_points + * sizeof *interpreter->twilight_y))) return NULL; /* Add the storage area. */ storage_size = maxp->max_storage * sizeof *interpreter->storage; - if (INT_ADD_WRAPV (storage_size, size, &size)) + if (ckd_add (&size, size, storage_size)) return NULL; /* Add padding for the storage area. */ pad = alignof (struct sfnt_interpreter_definition); pad -= size & (pad - 1); - if (INT_ADD_WRAPV (pad, size, &size)) + if (ckd_add (&size, size, pad)) return NULL; /* Add function and instruction definitions. */ - if (INT_ADD_WRAPV ((((int) maxp->max_instruction_defs - + maxp->max_function_defs) - * sizeof *interpreter->function_defs), - size, &size)) + if (ckd_add (&size, size, (((int) maxp->max_instruction_defs + + maxp->max_function_defs) + * sizeof *interpreter->function_defs))) return NULL; /* Add control value table. */ if (cvt) { - if (INT_MULTIPLY_WRAPV (cvt->num_elements, - sizeof *interpreter->cvt, - &temp) - || INT_ADD_WRAPV (temp, size, &size)) + if (ckd_mul (&temp, cvt->num_elements, sizeof *interpreter->cvt) + || ckd_add (&size, size, temp)) return NULL; } @@ -6840,7 +6824,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, (interpreter->SP - interpreter->stack) #define TRAP(why) \ - sfnt_interpret_trap (interpreter, (why)) + sfnt_interpret_trap (interpreter, why) #define MOVE(a, b, n) \ memmove (a, b, (n) * sizeof (uint32_t)) @@ -6944,7 +6928,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, { \ int16_t word; \ \ - word = (((int8_t) high) << 8 | low); \ + word = (((uint8_t) high) << 8 | low); \ PUSH_UNCHECKED (word); \ } \ @@ -7024,14 +7008,18 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, #define SLOOP() \ { \ - uint32_t loop; \ + int32_t loop; \ \ loop = POP (); \ \ - if (!loop) \ - TRAP ("loop set to 0"); \ + if (loop < 0) \ + TRAP ("loop set to invalid value"); \ \ - interpreter->state.loop = loop; \ + /* N.B. loop might be greater than 65535, \ + but no reasonable font should define \ + such values. */ \ + interpreter->state.loop \ + = MIN (65535, loop); \ } #define SMD() \ @@ -7558,12 +7546,13 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter, #define MUL() \ { \ - sfnt_f26dot6 n2, n1; \ + sfnt_f26dot6 n2, n1, r; \ \ n2 = POP (); \ n1 = POP (); \ \ - PUSH_UNCHECKED (sfnt_mul_f26dot6 (n2, n1)); \ + r = sfnt_mul_f26dot6_round (n2, n1); \ + PUSH_UNCHECKED (r); \ } #define ABS() \ @@ -8549,8 +8538,12 @@ sfnt_address_zp2 (struct sfnt_interpreter *interpreter, if (number >= interpreter->twilight_zone_size) TRAP ("address to ZP2 (twilight zone) out of bounds"); + if (!x || !y) + goto next; + *x = interpreter->twilight_x[number]; *y = interpreter->twilight_y[number]; + next: if (!x_org || !y_org) return; @@ -8570,8 +8563,11 @@ sfnt_address_zp2 (struct sfnt_interpreter *interpreter, if (number >= interpreter->glyph_zone->num_points) TRAP ("address to ZP2 (glyph zone) out of bounds"); - *x = interpreter->glyph_zone->x_current[number]; - *y = interpreter->glyph_zone->y_current[number]; + if (x && y) + { + *x = interpreter->glyph_zone->x_current[number]; + *y = interpreter->glyph_zone->y_current[number]; + } if (x_org && y_org) { @@ -8597,8 +8593,12 @@ sfnt_address_zp1 (struct sfnt_interpreter *interpreter, if (number >= interpreter->twilight_zone_size) TRAP ("address to ZP1 (twilight zone) out of bounds"); + if (!x || !y) + goto next; + *x = interpreter->twilight_x[number]; *y = interpreter->twilight_y[number]; + next: if (!x_org || !y_org) return; @@ -8618,8 +8618,11 @@ sfnt_address_zp1 (struct sfnt_interpreter *interpreter, if (number >= interpreter->glyph_zone->num_points) TRAP ("address to ZP1 (glyph zone) out of bounds"); - *x = interpreter->glyph_zone->x_current[number]; - *y = interpreter->glyph_zone->y_current[number]; + if (x && y) + { + *x = interpreter->glyph_zone->x_current[number]; + *y = interpreter->glyph_zone->y_current[number]; + } if (x_org && y_org) { @@ -8645,8 +8648,12 @@ sfnt_address_zp0 (struct sfnt_interpreter *interpreter, if (number >= interpreter->twilight_zone_size) TRAP ("address to ZP0 (twilight zone) out of bounds"); + if (!x || !y) + goto next; + *x = interpreter->twilight_x[number]; *y = interpreter->twilight_y[number]; + next: if (!x_org || !y_org) return; @@ -8666,8 +8673,11 @@ sfnt_address_zp0 (struct sfnt_interpreter *interpreter, if (number >= interpreter->glyph_zone->num_points) TRAP ("address to ZP0 (glyph zone) out of bounds"); - *x = interpreter->glyph_zone->x_current[number]; - *y = interpreter->glyph_zone->y_current[number]; + if (x && y) + { + *x = interpreter->glyph_zone->x_current[number]; + *y = interpreter->glyph_zone->y_current[number]; + } if (x_org && y_org) { @@ -8954,7 +8964,7 @@ sfnt_dual_project_vector (struct sfnt_interpreter *interpreter, static void sfnt_interpret_fliprgoff (struct sfnt_interpreter *interpreter, - uint32_t l, uint32_t h) + uint32_t h, uint32_t l) { uint32_t i; @@ -8964,7 +8974,7 @@ sfnt_interpret_fliprgoff (struct sfnt_interpreter *interpreter, if (!interpreter->state.zp0) return; - for (i = l; i < h; ++i) + for (i = l; i <= h; ++i) interpreter->glyph_zone->flags[i] &= ~01; } @@ -8973,7 +8983,7 @@ sfnt_interpret_fliprgoff (struct sfnt_interpreter *interpreter, static void sfnt_interpret_fliprgon (struct sfnt_interpreter *interpreter, - uint32_t l, uint32_t h) + uint32_t h, uint32_t l) { uint32_t i; @@ -8983,8 +8993,8 @@ sfnt_interpret_fliprgon (struct sfnt_interpreter *interpreter, if (!interpreter->state.zp0) return; - for (i = l; i < h; ++i) - interpreter->glyph_zone->flags[i] |= ~01; + for (i = l; i <= h; ++i) + interpreter->glyph_zone->flags[i] |= 01; } /* Interpret a FLIPPT instruction in INTERPRETER. For loop times, pop @@ -9628,6 +9638,8 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter) sfnt_f26dot6 new_distance; uint32_t p; sfnt_f26dot6 x, y, original_x, original_y; + struct sfnt_interpreter_zone *zone; + bool scale; /* First load both reference points. */ sfnt_address_zp0 (interpreter, interpreter->state.rp1, @@ -9637,6 +9649,57 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter) &rp2x, &rp2y, &rp2_original_x, &rp2_original_y); + /* If RP1, RP2, and all arguments all fall within the glyph zone and + a simple glyph is loaded, replace their original coordinates as + loaded here with coordinates from the unscaled glyph outline. */ + + zone = interpreter->glyph_zone; + scale = false; + + if (zone && zone->simple + && interpreter->state.zp0 + && interpreter->state.zp1 + && interpreter->state.zp2) + { + p = interpreter->state.rp1; + + /* If P is a phantom point... */ + if (p >= zone->simple->number_of_points) + { + /* ...scale the phantom point to the size of the original + outline. */ + rp1_original_x = sfnt_div_fixed (rp1_original_x, + interpreter->scale); + rp1_original_y = sfnt_div_fixed (rp1_original_y, + interpreter->scale); + } + else + { + rp1_original_x = zone->simple->x_coordinates[p]; + rp1_original_y = zone->simple->y_coordinates[p]; + } + + p = interpreter->state.rp2; + + /* If P is a phantom point... */ + if (p >= zone->simple->number_of_points) + { + /* ...scale the phantom point to the size of the original + outline. */ + rp2_original_x = sfnt_div_fixed (rp2_original_x, + interpreter->scale); + rp2_original_y = sfnt_div_fixed (rp2_original_y, + interpreter->scale); + } + else + { + rp2_original_x = zone->simple->x_coordinates[p]; + rp2_original_y = zone->simple->y_coordinates[p]; + } + + scale = true; + } + /* Get the original distance between of RP1 and RP2 measured relative to the dual projection vector. */ range = sfnt_dual_project_vector (interpreter, @@ -9645,6 +9708,9 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter) sfnt_sub (rp2_original_y, rp1_original_y)); + if (scale) + range = sfnt_mul_fixed_round (range, interpreter->scale); + /* Get the new distance. */ new_range = sfnt_dual_project_vector (interpreter, sfnt_sub (rp2x, rp1x), @@ -9658,6 +9724,25 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter) sfnt_address_zp2 (interpreter, p, &x, &y, &original_x, &original_y); + if (scale) + { + /* If P is a phantom point... */ + if (p >= zone->simple->number_of_points) + { + /* ...scale the phantom point to the size of the original + outline. */ + original_x = sfnt_div_fixed (original_x, + interpreter->scale); + original_y = sfnt_div_fixed (original_y, + interpreter->scale); + } + else + { + original_x = zone->simple->x_coordinates[p]; + original_y = zone->simple->y_coordinates[p]; + } + } + /* Now compute the old distance from this point to rp1. */ org_distance = sfnt_dual_project_vector (interpreter, @@ -9666,6 +9751,10 @@ sfnt_interpret_ip (struct sfnt_interpreter *interpreter) sfnt_sub (original_y, rp1_original_y)); + if (scale) + org_distance = sfnt_mul_fixed_round (org_distance, + interpreter->scale); + /* And the current distance from this point to rp1, so how much to move can be determined. */ cur_distance @@ -10570,6 +10659,7 @@ sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by) return (int32_t) (((uint32_t) hi << 18) | (l >> 14)); #else int64_t xx, yy; + int64_t temp; xx = (int64_t) ax * bx; yy = (int64_t) ay * by; @@ -10578,7 +10668,12 @@ sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by) yy = xx >> 63; xx += 0x2000 + yy; - return (int32_t) (xx / (1 << 14)); + /* TrueType fonts rely on "division" here truncating towards + negative infinity, so compute the arithmetic right shift in place + of division. */ + temp = -(xx < 0); + temp = (temp ^ xx) >> 14 ^ temp; + return (int32_t) (temp); #endif } @@ -10668,6 +10763,7 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 *restrict y, sfnt_f26dot6 versor, k; sfnt_f2dot14 dot_product; size_t num; + unsigned char *flags_start; dot_product = interpreter->state.vector_dot_product; @@ -10680,6 +10776,10 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 *restrict y, other out, so the result is 26.6. */ versor = interpreter->state.freedom_vector.x; + /* Save flags that it may be restored for the second Y axis + loop. */ + flags_start = flags; + if (versor) { /* Move along X axis, converting the distance to the freedom @@ -10699,6 +10799,7 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 *restrict y, } } + flags = flags_start; versor = interpreter->state.freedom_vector.y; if (versor) @@ -11040,6 +11141,11 @@ sfnt_interpret_shp (struct sfnt_interpreter *interpreter, ? interpreter->glyph_zone->x_points[p] \ : interpreter->glyph_zone->y_points[p]) +#define load_unscaled(p) \ + (opcode == 0x31 \ + ? interpreter->glyph_zone->simple->x_coordinates[p] \ + : interpreter->glyph_zone->simple->y_coordinates[p]) + #define IUP_SINGLE_PAIR() \ /* Now make touch_start the first point before, i.e. the first \ touched point in this pair. */ \ @@ -11089,23 +11195,40 @@ sfnt_interpret_shp (struct sfnt_interpreter *interpreter, if (position >= original_min_pos \ && position <= original_max_pos) \ { \ + /* Compute the ratio between the two touched point positions \ + and the original position of the point being touched with \ + positions from the unscaled outline, if at all \ + possible. */ \ + \ + if (interpreter->glyph_zone->simple) \ + { \ + org_max_pos = load_unscaled (point_max); \ + org_min_pos = load_unscaled (point_min); \ + position = load_unscaled (i); \ + } \ + else \ + { \ + org_max_pos = original_max_pos; \ + org_min_pos = original_min_pos; \ + } \ + \ /* Handle the degenerate case where original_min_pos and \ original_max_pos have not changed by placing the point in \ the middle. */ \ - if (original_min_pos == original_max_pos) \ + if (org_min_pos == org_max_pos) \ ratio = 077777; \ else \ /* ... preserve the ratio of i between min_pos and \ max_pos... */ \ ratio = sfnt_div_fixed ((sfnt_sub (position, \ - original_min_pos) \ + org_min_pos) \ * 1024), \ - (sfnt_sub (original_max_pos, \ - original_min_pos) \ + (sfnt_sub (org_max_pos, \ + org_min_pos) \ * 1024)); \ \ delta = sfnt_sub (max_pos, min_pos); \ - delta = sfnt_mul_fixed (ratio, delta); \ + delta = sfnt_mul_fixed_round (ratio, delta); \ store_point (i, sfnt_add (min_pos, delta)); \ } \ else \ @@ -11140,8 +11263,8 @@ sfnt_interpret_iup_1 (struct sfnt_interpreter *interpreter, size_t first_point; size_t point_min, point_max, i; sfnt_f26dot6 position, min_pos, max_pos, delta, ratio; - sfnt_f26dot6 original_max_pos; - sfnt_f26dot6 original_min_pos; + sfnt_f26dot6 original_max_pos, org_max_pos; + sfnt_f26dot6 original_min_pos, org_min_pos; /* Find the first touched point. If none is found, simply return. */ @@ -11227,6 +11350,7 @@ sfnt_interpret_iup_1 (struct sfnt_interpreter *interpreter, #undef load_point #undef store_point #undef load_original +#undef load_unscaled /* Interpret an IUP (``interpolate untouched points'') instruction. INTERPRETER is the interpreter, and OPCODE is the instruction @@ -11412,6 +11536,64 @@ sfnt_interpret_mirp (struct sfnt_interpreter *interpreter, interpreter->state.rp0 = p; } +/* Return the projection of the two points P1 and P2's original values + along the dual projection vector, with P1 inside ZP0 and P2 inside + ZP1. If this zone is the glyph zone and the outline positions of + those points are directly accessible, project their original + positions and scale the result with rounding, so as to prevent + rounding-introduced inaccuracies. + + The scenario where such inaccuracies are significant is generally + where an Italic glyph is being instructed at small PPEM sizes, + during which a point moved by MDAP[rN] is within 1/64th of a + pixel's distance from a point on the grid, yet the measurements + taken between such a point and the reference point against which + the distance to move is computed is such that the position of the + point after applying their rounded values differs by one grid + coordinate from the font designer's intentions, either exaggerating + or neutralizing the slant of the stem to which it belongs. + + This behavior applies only to MDRP (which see), although a similar + strategy is also applied while interpreting IP instructions. */ + +static sfnt_f26dot6 +sfnt_project_zp1_zp0_org (struct sfnt_interpreter *interpreter, + uint32_t p1, uint32_t p2) +{ + sfnt_fword x1, y1, x2, y2, projection; + struct sfnt_simple_glyph *simple; + sfnt_f26dot6 org_x1, org_y1, org_x2, org_y2; + + /* Addressing the twilight zone, perhaps only partially. */ + if (!interpreter->state.zp0 + || !interpreter->state.zp1 + /* Not interpreting a glyph. */ + || !interpreter->glyph_zone + /* Not interpreting a simple glyph. */ + || !interpreter->glyph_zone->simple + /* P1 or P2 are phantom points. */ + || p1 >= interpreter->glyph_zone->simple->number_of_points + || p2 >= interpreter->glyph_zone->simple->number_of_points) + goto project_normally; + + simple = interpreter->glyph_zone->simple; + x1 = simple->x_coordinates[p1]; + y1 = simple->y_coordinates[p1]; + x2 = simple->x_coordinates[p2]; + y2 = simple->y_coordinates[p2]; + + /* Compute the projection. */ + projection = DUAL_PROJECT (x1 - x2, y1 - y2); + + /* Return the projection, scaled with rounding. */ + return sfnt_mul_fixed_round (projection, interpreter->scale); + + project_normally: + sfnt_address_zp1 (interpreter, p1, NULL, NULL, &org_x1, &org_y1); + sfnt_address_zp0 (interpreter, p2, NULL, NULL, &org_x2, &org_y2); + return DUAL_PROJECT (org_x1 - org_x2, org_y1 - org_y2); +} + /* Interpret an MDRP instruction with the specified OPCODE in INTERPRETER. Pop a point in ZP1, and move the point until its distance from RP0 in ZP0 is the same as in the original outline. @@ -11428,20 +11610,19 @@ sfnt_interpret_mdrp (struct sfnt_interpreter *interpreter, uint32_t p; sfnt_f26dot6 distance, applied; sfnt_f26dot6 current_projection; - sfnt_f26dot6 x, y, org_x, org_y; - sfnt_f26dot6 rx, ry, org_rx, org_ry; + sfnt_f26dot6 x, y, rx, ry; /* Point number. */ p = POP (); /* Load the points. */ - sfnt_address_zp1 (interpreter, p, &x, &y, &org_x, &org_y); + sfnt_address_zp1 (interpreter, p, &x, &y, NULL, NULL); sfnt_address_zp0 (interpreter, interpreter->state.rp0, - &rx, &ry, &org_rx, &org_ry); + &rx, &ry, NULL, NULL); /* Calculate the distance between P and rp0 prior to hinting. */ - distance = DUAL_PROJECT (org_x - org_rx, - org_y - org_ry); + distance = sfnt_project_zp1_zp0_org (interpreter, p, + interpreter->state.rp0); /* Calculate the distance between P and rp0 as of now in the hinting process. */ @@ -12159,10 +12340,10 @@ sfnt_interpret_control_value_program (struct sfnt_interpreter *interpreter, sfnt_interpret_run (interpreter, SFNT_RUN_CONTEXT_CONTROL_VALUE_PROGRAM); - /* If instruct_control & 4, then changes to the graphics state made + /* If instruct_control & 2, then changes to the graphics state made in this program should be reverted. */ - if (interpreter->state.instruct_control & 4) + if (interpreter->state.instruct_control & 2) sfnt_init_graphics_state (&interpreter->state); else { @@ -12442,19 +12623,16 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph, /* Calculate the size of the zone structure. */ - if (INT_MULTIPLY_WRAPV (glyph->simple->number_of_points + 2, - sizeof *zone->x_points * 4, - &temp) - || INT_ADD_WRAPV (temp, zone_size, &zone_size) - || INT_MULTIPLY_WRAPV (glyph->number_of_contours, - sizeof *zone->contour_end_points, - &temp) - || INT_ADD_WRAPV (temp, zone_size, &zone_size) - || INT_MULTIPLY_WRAPV (glyph->simple->number_of_points + 2, - sizeof *zone->flags, - &temp) - || INT_ADD_WRAPV (temp, zone_size, &zone_size) - || INT_ADD_WRAPV (sizeof *zone, zone_size, &zone_size)) + if (ckd_mul (&temp, glyph->simple->number_of_points + 2, + sizeof *zone->x_points * 4) + || ckd_add (&zone_size, zone_size, temp) + || ckd_mul (&temp, glyph->number_of_contours, + sizeof *zone->contour_end_points) + || ckd_add (&zone_size, zone_size, temp) + || ckd_mul (&temp, glyph->simple->number_of_points + 2, + sizeof *zone->flags) + || ckd_add (&zone_size, zone_size, temp) + || ckd_add (&zone_size, zone_size, sizeof *zone)) return "Glyph exceeded maximum permissible size"; /* Don't use malloc if possible. */ @@ -12478,6 +12656,7 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph, zone->y_current = zone->y_points + zone->num_points; zone->flags = (unsigned char *) (zone->y_current + zone->num_points); + zone->simple = glyph->simple; /* Load x_points and x_current. */ for (i = 0; i < glyph->simple->number_of_points; ++i) @@ -12740,19 +12919,13 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph *glyph, zone_size = 0; zone_was_allocated = false; - if (INT_MULTIPLY_WRAPV (num_points + 2, - sizeof *zone->x_points * 4, - &temp) - || INT_ADD_WRAPV (temp, zone_size, &zone_size) - || INT_MULTIPLY_WRAPV (num_contours, - sizeof *zone->contour_end_points, - &temp) - || INT_ADD_WRAPV (temp, zone_size, &zone_size) - || INT_MULTIPLY_WRAPV (num_points + 2, - sizeof *zone->flags, - &temp) - || INT_ADD_WRAPV (temp, zone_size, &zone_size) - || INT_ADD_WRAPV (sizeof *zone, zone_size, &zone_size)) + if (ckd_mul (&temp, num_points + 2, sizeof *zone->x_points * 4) + || ckd_add (&zone_size, zone_size, temp) + || ckd_mul (&temp, num_contours, sizeof *zone->contour_end_points) + || ckd_add (&zone_size, zone_size, temp) + || ckd_mul (&temp, num_points + 2, sizeof *zone->flags) + || ckd_add (&zone_size, zone_size, temp) + || ckd_add (&zone_size, zone_size, sizeof *zone)) return "Glyph exceeded maximum permissible size"; /* Don't use malloc if possible. */ @@ -12776,6 +12949,7 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph *glyph, zone->y_current = zone->y_points + zone->num_points; zone->flags = (unsigned char *) (zone->y_current + zone->num_points); + zone->simple = NULL; /* Copy and renumber all contour end points to start from base_index. */ @@ -13394,16 +13568,12 @@ sfnt_interpret_compound_glyph (struct sfnt_glyph *glyph, /* Copy the compound glyph data into an instructed outline. */ outline_size = sizeof (*outline); - if (INT_MULTIPLY_WRAPV (context.num_end_points, - sizeof *outline->contour_end_points, - &temp) - || INT_ADD_WRAPV (outline_size, temp, &outline_size) - || INT_MULTIPLY_WRAPV (context.num_points, - sizeof *outline->x_points * 2, - &temp) - || INT_ADD_WRAPV (outline_size, temp, &outline_size) - || INT_ADD_WRAPV (context.num_points, outline_size, - &outline_size)) + if (ckd_mul (&temp, context.num_end_points, + sizeof *outline->contour_end_points) + || ckd_add (&outline_size, outline_size, temp) + || ckd_mul (&temp, context.num_points, sizeof *outline->x_points * 2) + || ckd_add (&outline_size, outline_size, temp) + || ckd_add (&outline_size, outline_size, context.num_points)) { xfree (context.x_coordinates); xfree (context.y_coordinates); @@ -13526,9 +13696,8 @@ sfnt_read_default_uvs_table (int fd, off_t offset) /* Now, allocate enough to hold the UVS table. */ size = sizeof *uvs; - if (INT_MULTIPLY_WRAPV (sizeof *uvs->ranges, num_ranges, - &temp) - || INT_ADD_WRAPV (temp, size, &size)) + if (ckd_mul (&temp, num_ranges, sizeof *uvs->ranges) + || ckd_add (&size, size, temp)) return NULL; uvs = xmalloc (size); @@ -13597,9 +13766,8 @@ sfnt_read_nondefault_uvs_table (int fd, off_t offset) /* Now, allocate enough to hold the UVS table. */ size = sizeof *uvs; - if (INT_MULTIPLY_WRAPV (sizeof *uvs->mappings, num_mappings, - &temp) - || INT_ADD_WRAPV (temp, size, &size)) + if (ckd_mul (&temp, num_mappings, sizeof *uvs->mappings) + || ckd_add (&size, size, temp)) return NULL; uvs = xmalloc (size); @@ -13679,9 +13847,9 @@ sfnt_create_uvs_context (struct sfnt_cmap_format_14 *cmap, int fd) off_t offset; struct sfnt_uvs_context *context; - if (INT_MULTIPLY_WRAPV (cmap->num_var_selector_records, - sizeof *table_offsets, &size) - || INT_MULTIPLY_WRAPV (size, 2, &size)) + if (ckd_mul (&size, cmap->num_var_selector_records, + sizeof *table_offsets) + || ckd_mul (&size, size, 2)) return NULL; context = NULL; @@ -13701,9 +13869,8 @@ sfnt_create_uvs_context (struct sfnt_cmap_format_14 *cmap, int fd) if (cmap->records[i].default_uvs_offset) { - if (INT_ADD_WRAPV (cmap->offset, - cmap->records[i].default_uvs_offset, - &table_offsets[j].offset)) + if (ckd_add (&table_offsets[j].offset, cmap->offset, + cmap->records[i].default_uvs_offset)) goto bail; table_offsets[j++].is_nondefault_table = false; @@ -13711,9 +13878,8 @@ sfnt_create_uvs_context (struct sfnt_cmap_format_14 *cmap, int fd) if (cmap->records[i].nondefault_uvs_offset) { - if (INT_ADD_WRAPV (cmap->offset, - cmap->records[i].nondefault_uvs_offset, - &table_offsets[j].offset)) + if (ckd_add (&table_offsets[j].offset, cmap->offset, + cmap->records[i].nondefault_uvs_offset)) goto bail; table_offsets[j++].is_nondefault_table = true; @@ -14151,14 +14317,12 @@ sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable) name identifier, or 3 * sizeof (uint16_t) + axisCount * sizeof (sfnt_fixed), meaning there is. */ - if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof (sfnt_fixed), - &temp) - || INT_ADD_WRAPV (2 * sizeof (uint16_t), temp, &non_ps_size)) + if (ckd_mul (&temp, fvar->axis_count, sizeof (sfnt_fixed)) + || ckd_add (&non_ps_size, temp, 2 * sizeof (uint16_t))) goto bail; - if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof (sfnt_fixed), - &temp) - || INT_ADD_WRAPV (3 * sizeof (uint16_t), temp, &ps_size)) + if (ckd_mul (&temp, fvar->axis_count, sizeof (sfnt_fixed)) + || ckd_add (&ps_size, temp, 3 * sizeof (uint16_t))) goto bail; if (fvar->instance_size != non_ps_size @@ -14168,8 +14332,7 @@ sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable) /* Now compute the offset of the axis data from the start of the font file. */ - if (INT_ADD_WRAPV (fvar->offset_to_data, directory->offset, - &offset)) + if (ckd_add (&offset, fvar->offset_to_data, directory->offset)) goto bail; /* Seek there. */ @@ -14186,28 +14349,23 @@ sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable) sfnt_instance) + sizeof (sfnt_fixed) * fvar->instance_count * fvar->axis_count. */ - if (INT_MULTIPLY_WRAPV (fvar->axis_count, sizeof *fvar->axis, - &temp) - || INT_ADD_WRAPV (min_bytes, temp, &min_bytes)) + if (ckd_mul (&temp, fvar->axis_count, sizeof *fvar->axis) + || ckd_add (&min_bytes, min_bytes, temp)) goto bail; - pad = alignof (struct sfnt_variation_axis); + pad = alignof (struct sfnt_instance); pad -= min_bytes & (pad - 1); - if (INT_ADD_WRAPV (min_bytes, pad, &min_bytes)) + if (ckd_add (&min_bytes, min_bytes, pad)) goto bail; - if (INT_MULTIPLY_WRAPV (fvar->instance_count, - sizeof *fvar->instance, - &temp) - || INT_ADD_WRAPV (min_bytes, temp, &min_bytes)) + if (ckd_mul (&temp, fvar->instance_count, sizeof *fvar->instance) + || ckd_add (&min_bytes, min_bytes, temp)) goto bail; - if (INT_MULTIPLY_WRAPV (fvar->instance_count, - sizeof *fvar->instance->coords, - &temp) - || INT_MULTIPLY_WRAPV (temp, fvar->axis_count, &temp) - || INT_ADD_WRAPV (min_bytes, temp, &min_bytes)) + if (ckd_mul (&temp, fvar->instance_count, sizeof *fvar->instance->coords) + || ckd_mul (&temp, temp, fvar->axis_count) + || ckd_add (&min_bytes, min_bytes, temp)) goto bail; /* Reallocate fvar. */ @@ -14389,9 +14547,9 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable) goto bail; /* Figure out how big gvar needs to be. */ - if (INT_ADD_WRAPV (sizeof *gvar, coordinate_size, &min_bytes) - || INT_ADD_WRAPV (min_bytes, off_size, &min_bytes) - || INT_ADD_WRAPV (min_bytes, data_size, &min_bytes)) + if (ckd_add (&min_bytes, coordinate_size, sizeof *gvar) + || ckd_add (&min_bytes, min_bytes, off_size) + || ckd_add (&min_bytes, min_bytes, data_size)) goto bail; /* Now allocate enough for all of this extra data. */ @@ -14427,8 +14585,7 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable) if (gvar->shared_coord_count) { - if (INT_ADD_WRAPV (gvar->offset_to_coord, directory->offset, - &offset)) + if (ckd_add (&offset, gvar->offset_to_coord, directory->offset)) goto bail; if (lseek (fd, offset, SEEK_SET) != offset) @@ -14452,8 +14609,7 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable) if (gvar->data_size) { - if (INT_ADD_WRAPV (gvar->offset_to_data, directory->offset, - &offset)) + if (ckd_add (&offset, gvar->offset_to_data, directory->offset)) goto bail; if (lseek (fd, offset, SEEK_SET) != offset) @@ -14549,10 +14705,10 @@ sfnt_read_avar_table (int fd, struct sfnt_offset_subtable *subtable) /* Now add one struct sfnt_short_frac_segment for each axis and each of its correspondences. */ - if (INT_ADD_WRAPV (sizeof (struct sfnt_short_frac_segment), - min_size, &min_size) - || INT_ADD_WRAPV (sizeof (struct sfnt_short_frac_correspondence) - * buffer[k], min_size, &min_size)) + if (ckd_add (&min_size, min_size, sizeof (struct sfnt_short_frac_segment)) + || ckd_add (&min_size, min_size, + (sizeof (struct sfnt_short_frac_correspondence) + * buffer[k]))) goto bail1; /* Verify that words from here to buffer[1 + buffer[k] * 2], the @@ -14901,8 +15057,7 @@ sfnt_read_cvar_table (int fd, struct sfnt_offset_subtable *subtable, goto bail2; tuple += sizeof *coords * fvar->axis_count; - if (INT_ADD_WRAPV (size, sizeof *coords * fvar->axis_count, - &size)) + if (ckd_add (&size, size, sizeof *coords * fvar->axis_count)) goto bail2; } else @@ -14914,20 +15069,20 @@ sfnt_read_cvar_table (int fd, struct sfnt_offset_subtable *subtable, if (index & 0x4000) { tuple += fvar->axis_count * 4; - if (INT_ADD_WRAPV (size, fvar->axis_count * 4, &size)) + if (ckd_add (&size, size, fvar->axis_count * 4)) goto bail2; } /* Add one point and one delta for each CVT element. */ - if (INT_ADD_WRAPV (size, cvt->num_elements * 4, &size)) + if (ckd_add (&size, size, cvt->num_elements * 4)) goto bail2; /* Now add the size of the tuple. */ - if (INT_ADD_WRAPV (size, sizeof *cvar->variation, &size)) + if (ckd_add (&size, size, sizeof *cvar->variation)) goto bail2; } - if (INT_ADD_WRAPV (sizeof *cvar, size, &size)) + if (ckd_add (&size, size, sizeof *cvar)) goto bail2; /* Reallocate cvar. */ @@ -18459,13 +18614,13 @@ static struct sfnt_interpreter_test all_tests[] = "SLOOP", /* PUSHB[0] 2 SLOOP[] - PUSHB[0] 0 + PUSHW[0] 255 255 (-1) SLOOP[] */ (unsigned char []) { 0xb0, 2, 0x17, - 0xb0, 0, + 0xb8, 255, 255, 0x17, }, - 6, + 7, NULL, sfnt_check_sloop, }, @@ -20258,7 +20413,8 @@ sfnt_identify_instruction (struct sfnt_interpreter *interpreter) return buffer; } - if (exec_fpgm->instructions + if (exec_fpgm + && exec_fpgm->instructions && where >= exec_fpgm->instructions && where < (exec_fpgm->instructions + exec_fpgm->num_instructions)) @@ -20529,6 +20685,13 @@ main (int argc, char **argv) if (!interpreter) abort (); + if (getenv ("SFNT_VERBOSE")) + { + interpreter->run_hook = sfnt_verbose; + interpreter->push_hook = sfnt_push_hook; + interpreter->pop_hook = sfnt_pop_hook; + } + for (i = 0; i < ARRAYELTS (all_tests); ++i) sfnt_run_interpreter_test (&all_tests[i], interpreter); @@ -20631,8 +20794,8 @@ main (int argc, char **argv) return 1; } -#define FANCY_PPEM 44 -#define EASY_PPEM 44 +#define FANCY_PPEM 18 +#define EASY_PPEM 18 interpreter = NULL; head = sfnt_read_head_table (fd, font); @@ -21023,6 +21186,16 @@ main (int argc, char **argv) interpreter = sfnt_make_interpreter (maxp, cvt, head, fvar, FANCY_PPEM, FANCY_PPEM); + + if (getenv ("SFNT_DEBUG")) + interpreter->run_hook = sfnt_run_hook; + else if (getenv ("SFNT_VERBOSE")) + { + interpreter->run_hook = sfnt_verbose; + interpreter->push_hook = sfnt_push_hook; + interpreter->pop_hook = sfnt_pop_hook; + } + state = interpreter->state; if (instance && gvar) @@ -21236,15 +21409,6 @@ main (int argc, char **argv) if (interpreter) { - if (getenv ("SFNT_DEBUG")) - interpreter->run_hook = sfnt_run_hook; - else if (getenv ("SFNT_VERBOSE")) - { - interpreter->run_hook = sfnt_verbose; - interpreter->push_hook = sfnt_push_hook; - interpreter->pop_hook = sfnt_pop_hook; - } - if (!sfnt_lookup_glyph_metrics (code, &metrics, hmtx, hhea, maxp)) { |