[cairo-cff-subset] Propagate errors and review error paths.

Ensure that errors get duly propagated back to the caller and all
locally allocated resources are freed along error paths.
This commit is contained in:
Chris Wilson 2007-10-04 17:12:26 +01:00
parent add0959328
commit 37fd0d8967

View file

@ -385,6 +385,7 @@ cff_index_append_copy (cairo_array_t *index,
unsigned int length)
{
cff_index_element_t element;
cairo_status_t status;
element.length = length;
element.is_copy = TRUE;
@ -394,7 +395,13 @@ cff_index_append_copy (cairo_array_t *index,
memcpy (element.data, object, element.length);
return _cairo_array_append (index, &element);
status = _cairo_array_append (index, &element);
if (status) {
free (element.data);
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static void
@ -420,10 +427,14 @@ _cairo_cff_dict_equal (const void *key_a, const void *key_b)
return op_a->operator == op_b->operator;
}
static void
static cairo_status_t
cff_dict_init (cairo_hash_table_t **dict)
{
*dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
if (*dict == NULL)
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
static void
@ -697,6 +708,7 @@ cairo_cff_font_read_private_dict (cairo_cff_font_t *font,
unsigned char *ptr,
int size)
{
cairo_int_status_t status;
unsigned char buf[10];
unsigned char *end_buf;
int offset;
@ -704,16 +716,23 @@ cairo_cff_font_read_private_dict (cairo_cff_font_t *font,
unsigned char *operand;
unsigned char *p;
cff_dict_read (private_dict, ptr, size);
status = cff_dict_read (private_dict, ptr, size);
if (status)
return status;
operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
if (operand) {
decode_integer (operand, &offset);
p = ptr + offset;
cff_index_read (local_sub_index, &p, font->data_end);
status = cff_index_read (local_sub_index, &p, font->data_end);
if (status)
return status;
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
@ -791,11 +810,10 @@ cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
}
for (i = 0; i < font->num_fontdicts; i++) {
cff_dict_init (&font->fd_dict[i]);
if (font->fd_dict[i] == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = cff_dict_init (&font->fd_dict[i]);
if (status)
goto fail;
}
element = _cairo_array_index (&index, i);
status = cff_dict_read (font->fd_dict[i], element->data, element->length);
if (status)
@ -808,11 +826,10 @@ cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
}
operand = decode_integer (operand, &size);
decode_integer (operand, &offset);
cff_dict_init (&font->fd_private_dict[i]);
if (font->fd_private_dict[i] == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = cff_dict_init (&font->fd_private_dict[i]);
if (status)
goto fail;
}
cff_index_init (&font->fd_local_sub_index[i]);
status = cairo_cff_font_read_private_dict (font,
font->fd_private_dict[i],
@ -877,28 +894,49 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
if (font->is_cid) {
operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
decode_integer (operand, &offset);
cairo_cff_font_read_fdselect (font, font->data + offset);
status = cairo_cff_font_read_fdselect (font, font->data + offset);
if (status)
goto fail;
operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
decode_integer (operand, &offset);
cairo_cff_font_read_cid_fontdict (font, font->data + offset);
status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
if (status)
goto fail;
} else {
operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
operand = decode_integer (operand, &size);
decode_integer (operand, &offset);
cairo_cff_font_read_private_dict (font,
font->private_dict,
&font->local_sub_index,
font->data + offset,
size);
status = cairo_cff_font_read_private_dict (font,
font->private_dict,
&font->local_sub_index,
font->data + offset,
size);
if (status)
goto fail;
}
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
cff_dict_set_operands (font->top_dict, FDSELECT_OP, buf, end_buf - buf);
cff_dict_set_operands (font->top_dict, FDARRAY_OP, buf, end_buf - buf);
cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
status = cff_dict_set_operands (font->top_dict,
CHARSTRINGS_OP, buf, end_buf - buf);
if (status)
goto fail;
status = cff_dict_set_operands (font->top_dict,
FDSELECT_OP, buf, end_buf - buf);
if (status)
goto fail;
status = cff_dict_set_operands (font->top_dict,
FDARRAY_OP, buf, end_buf - buf);
if (status)
goto fail;
status = cff_dict_set_operands (font->top_dict,
CHARSET_OP, buf, end_buf - buf);
if (status)
goto fail;
cff_dict_remove (font->top_dict, ENCODING_OP);
cff_dict_remove (font->top_dict, PRIVATE_OP);
@ -952,9 +990,10 @@ cairo_cff_font_read_font (cairo_cff_font_t *font)
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
{
cairo_status_t status;
unsigned char buf[30];
unsigned char *p;
int sid1, sid2;
@ -974,10 +1013,16 @@ cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
p = encode_integer (buf, sid1);
p = encode_integer (p, sid2);
p = encode_integer (p, 0);
cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
if (status)
return status;
p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -1007,7 +1052,9 @@ cairo_cff_font_subset_dict_string(cairo_cff_font_t *font,
return status;
p = encode_integer (buf, sid);
cff_dict_set_operands (dict, operator, buf, p - buf);
status = cff_dict_set_operands (dict, operator, buf, p - buf);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
@ -1107,13 +1154,19 @@ cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
{
unsigned char buf[100];
unsigned char *end_buf;
cairo_status_t status;
font->num_fontdicts = 1;
font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
if (font->fd_dict == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
cff_dict_init (&font->fd_dict[0]);
if (cff_dict_init (&font->fd_dict[0])) {
free (font->fd_dict);
font->fd_dict = NULL;
font->num_fontdicts = 0;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
font->fd_subset_map = malloc (sizeof (int));
if (font->fd_subset_map == NULL)
@ -1130,7 +1183,9 @@ cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
* space for any value later */
end_buf = encode_integer_max (buf, 0);
end_buf = encode_integer_max (end_buf, 0);
cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
@ -1144,6 +1199,7 @@ cairo_cff_font_subset_strings (cairo_cff_font_t *font)
status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
if (status)
return status;
if (font->is_cid) {
for (i = 0; i < font->num_subset_fontdicts; i++) {
status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
@ -1166,16 +1222,20 @@ cairo_cff_font_subset_font (cairo_cff_font_t *font)
{
cairo_status_t status;
cairo_cff_font_set_ros_strings (font);
status = cairo_cff_font_set_ros_strings (font);
if (status)
return status;
status = cairo_cff_font_subset_charstrings (font);
if (status)
return status;
if (font->is_cid)
cairo_cff_font_subset_fontdict (font);
status = cairo_cff_font_subset_fontdict (font);
else
cairo_cff_font_create_cid_fontdict (font);
status = cairo_cff_font_create_cid_fontdict (font);
if (status)
return status;
status = cairo_cff_font_subset_strings (font);
if (status)
@ -1218,21 +1278,25 @@ cairo_cff_font_write_header (cairo_cff_font_t *font)
static cairo_status_t
cairo_cff_font_write_name (cairo_cff_font_t *font)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_array_t index;
cairo_status_t status;
cff_index_init (&index);
status = cff_index_append_copy (&index,
(unsigned char *) font->subset_font_name,
strlen(font->subset_font_name));
if (status)
return status;
goto FAIL;
status = cff_index_write (&index, &font->output);
if (status)
return status;
goto FAIL;
FAIL:
cff_index_fini (&index);
return CAIRO_STATUS_SUCCESS;
return status;
}
static cairo_status_t
@ -1435,6 +1499,7 @@ cairo_cff_font_write_private_dict (cairo_cff_font_t *font,
status = cff_dict_write (private_dict, &font->output);
if (status)
return status;
size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
/* private entry has two operands - size and offset */
buf_end = encode_integer_max (buf, size);
@ -1483,7 +1548,7 @@ static cairo_status_t
cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
{
unsigned int i;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_int_status_t status;
if (font->is_cid) {
for (i = 0; i < font->num_subset_fontdicts; i++) {
@ -1510,13 +1575,18 @@ cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
0,
font->fd_dict[0],
font->private_dict);
if (status)
return status;
status = cairo_cff_font_write_local_sub (font,
0,
font->private_dict,
&font->local_sub_index);
if (status)
return status;
}
return status;
return CAIRO_STATUS_SUCCESS;
}
typedef cairo_status_t
@ -1701,7 +1771,7 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->subset_font_name = strdup (subset_name);
if (font->subset_font_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
goto fail2;
}
font->x_min = (int16_t) be16_to_cpu (head.x_min);
font->y_min = (int16_t) be16_to_cpu (head.y_min);
@ -1737,7 +1807,7 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->font_name = malloc (30);
if (font->font_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
goto fail3;
}
snprintf(font->font_name, 30, "CairoFont-%u-%u",
scaled_font_subset->font_id,
@ -1754,25 +1824,35 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
if (font->widths == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail5;
goto fail4;
}
cairo_cff_font_create_set_widths (font);
status = cairo_cff_font_create_set_widths (font);
if (status)
goto fail5;
font->data_length = data_length;
font->data = malloc (data_length);
if (font->data == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail6;
goto fail5;
}
status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font,
TT_TAG_CFF, 0, font->data,
&font->data_length);
if (status)
goto fail7;
goto fail6;
font->data_end = font->data + font->data_length;
cff_dict_init (&font->top_dict);
cff_dict_init (&font->private_dict);
status = cff_dict_init (&font->top_dict);
if (status)
goto fail6;
status = cff_dict_init (&font->private_dict);
if (status)
goto fail7;
cff_index_init (&font->strings_index);
cff_index_init (&font->charstrings_index);
cff_index_init (&font->global_sub_index);
@ -1793,16 +1873,17 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
return CAIRO_STATUS_SUCCESS;
fail7:
free (font->data);
_cairo_hash_table_destroy (font->top_dict);
fail6:
free (font->widths);
free (font->data);
fail5:
free (font->font_name);
free (font->widths);
fail4:
free (font->subset_font_name);
free (font->font_name);
fail3:
_cairo_array_fini (&font->output);
free (font->subset_font_name);
fail2:
_cairo_array_fini (&font->output);
free (font);
fail1:
free (name);
@ -1886,12 +1967,16 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
goto fail1;
cff_subset->base_font = strdup (font->font_name);
if (cff_subset->base_font == NULL)
if (cff_subset->base_font == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
if (cff_subset->widths == NULL)
if (cff_subset->widths == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
cff_subset->widths[i] = font->widths[i];
@ -1903,8 +1988,10 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
cff_subset->descent = font->descent;
cff_subset->data = malloc (length);
if (cff_subset->data == NULL)
if (cff_subset->data == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
memcpy (cff_subset->data, data, length);
cff_subset->data_length = length;
@ -1954,13 +2041,13 @@ _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset
font->subset_font_name = strdup (subset_name);
if (font->subset_font_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
goto fail1;
}
font->font_name = strdup (subset_name);
if (font->subset_font_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
goto fail2;
}
font->x_min = 0;
@ -1973,15 +2060,21 @@ _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset
font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
if (font->widths == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
goto fail3;
}
font->data_length = 0;
font->data = NULL;
font->data_end = 0;
font->data_end = NULL;
status = cff_dict_init (&font->top_dict);
if (status)
goto fail4;
status = cff_dict_init (&font->private_dict);
if (status)
goto fail5;
cff_dict_init (&font->top_dict);
cff_dict_init (&font->private_dict);
cff_index_init (&font->strings_index);
cff_index_init (&font->charstrings_index);
cff_index_init (&font->global_sub_index);
@ -2000,13 +2093,16 @@ _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset
return CAIRO_STATUS_SUCCESS;
fail5:
_cairo_hash_table_destroy (font->top_dict);
fail4:
free (font->font_name);
free (font->widths);
fail3:
free (font->subset_font_name);
free (font->font_name);
fail2:
_cairo_array_fini (&font->output);
free (font->subset_font_name);
fail1:
_cairo_array_fini (&font->output);
free (font);
return _cairo_error (status);
}
@ -2037,16 +2133,40 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
end_buf = encode_integer (end_buf, type2_subset->y_min);
end_buf = encode_integer (end_buf, type2_subset->x_max);
end_buf = encode_integer (end_buf, type2_subset->y_max);
cff_dict_set_operands (font->top_dict, FONTBBOX_OP, buf, end_buf - buf);
status = cff_dict_set_operands (font->top_dict,
FONTBBOX_OP, buf, end_buf - buf);
if (status)
return status;
end_buf = encode_integer_max (buf, 0);
cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
cff_dict_set_operands (font->top_dict, FDSELECT_OP, buf, end_buf - buf);
cff_dict_set_operands (font->top_dict, FDARRAY_OP, buf, end_buf - buf);
cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
cairo_cff_font_set_ros_strings (font);
status = cff_dict_set_operands (font->top_dict,
CHARSTRINGS_OP, buf, end_buf - buf);
if (status)
return status;
status = cff_dict_set_operands (font->top_dict,
FDSELECT_OP, buf, end_buf - buf);
if (status)
return status;
status = cff_dict_set_operands (font->top_dict,
FDARRAY_OP, buf, end_buf - buf);
if (status)
return status;
status = cff_dict_set_operands (font->top_dict,
CHARSET_OP, buf, end_buf - buf);
if (status)
return status;
status = cairo_cff_font_set_ros_strings (font);
if (status)
return status;
/* Create CID FD dictionary */
cairo_cff_font_create_cid_fontdict (font);
status = cairo_cff_font_create_cid_fontdict (font);
if (status)
return status;
/* Create charstrings */
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
@ -2092,15 +2212,19 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
if (status)
goto fail1;
goto fail2;
cff_subset->base_font = strdup (font->font_name);
if (cff_subset->base_font == NULL)
goto fail1;
if (cff_subset->base_font == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
if (cff_subset->widths == NULL)
goto fail2;
if (cff_subset->widths == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
cff_subset->widths[i] = type2_subset.widths[i];
@ -2111,24 +2235,27 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
cff_subset->ascent = type2_subset.y_max;
cff_subset->descent = type2_subset.y_min;
_cairo_type2_charstrings_fini (&type2_subset);
cff_subset->data = malloc (length);
if (cff_subset->data == NULL)
goto fail3;
if (cff_subset->data == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
}
memcpy (cff_subset->data, data, length);
cff_subset->data_length = length;
cff_subset->data_length = length;
_cairo_type2_charstrings_fini (&type2_subset);
cairo_cff_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
fail3:
fail4:
free (cff_subset->widths);
fail2:
fail3:
free (cff_subset->base_font);
fail2:
_cairo_type2_charstrings_fini (&type2_subset);
fail1:
cairo_cff_font_destroy (font);