mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-10 22:10:16 +01:00
_cairo_malloc(0) always returns NULL, but has not been used consistently. This patch replaces many calls to malloc() with _cairo_malloc(). Fixes: fdo# 101547 CVE: CVE-2017-9814 Heap buffer overflow at cairo-truetype-subset.c:1299 Reviewed-by: Bryce Harrington <bryce@osg.samsung.com>
280 lines
7 KiB
C
280 lines
7 KiB
C
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
|
|
/* cairo - a vector graphics library with display and print output
|
|
*
|
|
* Copyright © 2016 Adrian Johnson
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it either under the terms of the GNU Lesser General Public
|
|
* License version 2.1 as published by the Free Software Foundation
|
|
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
|
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
|
* notice, a recipient may use your version of this file under either
|
|
* the MPL or the LGPL.
|
|
*
|
|
* You should have received a copy of the LGPL along with this library
|
|
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
|
* You should have received a copy of the MPL along with this library
|
|
* in the file COPYING-MPL-1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License
|
|
* Version 1.1 (the "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
|
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
|
* the specific language governing rights and limitations.
|
|
*
|
|
* The Original Code is the cairo graphics library.
|
|
*
|
|
* The Initial Developer of the Original Code is Adrian Johnson.
|
|
*
|
|
* Contributor(s):
|
|
* Adrian Johnson <ajohnson@redneon.com>
|
|
*/
|
|
|
|
#include "cairoint.h"
|
|
|
|
#include "cairo-tag-stack-private.h"
|
|
|
|
/* Tagged PDF must have one of these tags at the top level */
|
|
static const char * _cairo_tag_stack_tagged_pdf_top_level_element_list[] =
|
|
{
|
|
"Document",
|
|
"Part",
|
|
"Art",
|
|
"Sect",
|
|
"Div",
|
|
NULL
|
|
};
|
|
|
|
/* List of valid tag names. Table numbers reference PDF 32000 */
|
|
static const char * _cairo_tag_stack_struct_pdf_list[] =
|
|
{
|
|
/* Table 333 - Grouping Elements */
|
|
"Document",
|
|
"Part",
|
|
"Art",
|
|
"Sect",
|
|
"Div",
|
|
"BlockQuote",
|
|
"Caption",
|
|
"TOC",
|
|
"TOCI",
|
|
"Index",
|
|
"NonStruct",
|
|
"Private",
|
|
|
|
/* Table 335 - Standard structure types for paragraphlike elements */
|
|
"P", "H",
|
|
"H1", "H2", "H3", "H4", "H5", "H6",
|
|
|
|
/* Table 336 - Standard structure types for list elements */
|
|
"L", "LI", "Lbl", "LBody",
|
|
|
|
/* Table 337 - Standard structure types for table elements */
|
|
"Table",
|
|
"TR", "TH", "TD",
|
|
"THead", "TBody", "TFoot",
|
|
|
|
/* Table 338 - Standard structure types for inline-level structure elements */
|
|
"Span",
|
|
"Quote",
|
|
"Note",
|
|
"Reference",
|
|
"BibEntry",
|
|
"Code",
|
|
"Link", /* CAIRO_TAG_LINK */
|
|
"Annot",
|
|
"Ruby",
|
|
"Warichu",
|
|
|
|
/* Table 339 - Standard structure types for Ruby and Warichu elements */
|
|
"RB", "RT", "RP",
|
|
"WT", "WP",
|
|
|
|
/* Table 340 - Standard structure types for illustration elements */
|
|
"Figure",
|
|
"Formula",
|
|
"Form",
|
|
|
|
NULL
|
|
};
|
|
|
|
/* List of cairo specific tag names */
|
|
static const char * _cairo_tag_stack_cairo_tag_list[] =
|
|
{
|
|
CAIRO_TAG_DEST,
|
|
NULL
|
|
};
|
|
|
|
void
|
|
_cairo_tag_stack_init (cairo_tag_stack_t *stack)
|
|
{
|
|
cairo_list_init (&stack->list);
|
|
stack->type = TAG_TREE_TYPE_NO_TAGS;
|
|
stack->size = 0;
|
|
}
|
|
|
|
void
|
|
_cairo_tag_stack_fini (cairo_tag_stack_t *stack)
|
|
{
|
|
while (! cairo_list_is_empty (&stack->list)) {
|
|
cairo_tag_stack_elem_t *elem;
|
|
|
|
elem = cairo_list_first_entry (&stack->list, cairo_tag_stack_elem_t, link);
|
|
cairo_list_del (&elem->link);
|
|
free (elem->name);
|
|
free (elem->attributes);
|
|
free (elem);
|
|
}
|
|
}
|
|
|
|
cairo_tag_stack_structure_type_t
|
|
_cairo_tag_stack_get_structure_type (cairo_tag_stack_t *stack)
|
|
{
|
|
return stack->type;
|
|
}
|
|
|
|
static cairo_bool_t
|
|
name_in_list (const char *name, const char **list)
|
|
{
|
|
if (! name)
|
|
return FALSE;
|
|
|
|
while (*list) {
|
|
if (strcmp (name, *list) == 0)
|
|
return TRUE;
|
|
list++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
cairo_int_status_t
|
|
_cairo_tag_stack_push (cairo_tag_stack_t *stack,
|
|
const char *name,
|
|
const char *attributes)
|
|
{
|
|
cairo_tag_stack_elem_t *elem;
|
|
|
|
if (! name_in_list (name, _cairo_tag_stack_struct_pdf_list) &&
|
|
! name_in_list (name, _cairo_tag_stack_cairo_tag_list))
|
|
{
|
|
stack->type = TAG_TYPE_INVALID;
|
|
return _cairo_error (CAIRO_STATUS_TAG_ERROR);
|
|
}
|
|
|
|
if (stack->type == TAG_TREE_TYPE_NO_TAGS) {
|
|
if (name_in_list (name, _cairo_tag_stack_tagged_pdf_top_level_element_list))
|
|
stack->type = TAG_TREE_TYPE_TAGGED;
|
|
else if (strcmp (name, "Link") == 0)
|
|
stack->type = TAG_TREE_TYPE_LINK_ONLY;
|
|
else if (name_in_list (name, _cairo_tag_stack_struct_pdf_list))
|
|
stack->type = TAG_TREE_TYPE_STRUCTURE;
|
|
} else {
|
|
if (stack->type == TAG_TREE_TYPE_LINK_ONLY &&
|
|
(strcmp (name, "Link") != 0) &&
|
|
name_in_list (name, _cairo_tag_stack_struct_pdf_list))
|
|
{
|
|
stack->type = TAG_TREE_TYPE_STRUCTURE;
|
|
}
|
|
}
|
|
|
|
elem = _cairo_malloc (sizeof(cairo_tag_stack_elem_t));
|
|
if (unlikely (elem == NULL))
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
elem->name = strdup (name);
|
|
if (unlikely (elem->name == NULL))
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
if (attributes) {
|
|
elem->attributes = strdup (attributes);
|
|
if (unlikely (elem->attributes == NULL))
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
} else {
|
|
elem->attributes = NULL;
|
|
}
|
|
|
|
elem->data = NULL;
|
|
|
|
cairo_list_add_tail (&elem->link, &stack->list);
|
|
stack->size++;
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
}
|
|
|
|
cairo_private void
|
|
_cairo_tag_stack_set_top_data (cairo_tag_stack_t *stack,
|
|
void *data)
|
|
{
|
|
cairo_tag_stack_elem_t *top;
|
|
|
|
top = _cairo_tag_stack_top_elem (stack);
|
|
if (top)
|
|
top->data = data;
|
|
}
|
|
|
|
cairo_int_status_t
|
|
_cairo_tag_stack_pop (cairo_tag_stack_t *stack,
|
|
const char *name,
|
|
cairo_tag_stack_elem_t **elem)
|
|
{
|
|
cairo_tag_stack_elem_t *top;
|
|
|
|
top = _cairo_tag_stack_top_elem (stack);
|
|
if (!top) {
|
|
stack->type = TAG_TYPE_INVALID;
|
|
return _cairo_error (CAIRO_STATUS_TAG_ERROR);
|
|
}
|
|
|
|
cairo_list_del (&top->link);
|
|
stack->size--;
|
|
if (strcmp (top->name, name) != 0) {
|
|
stack->type = TAG_TYPE_INVALID;
|
|
_cairo_tag_stack_free_elem (top);
|
|
return _cairo_error (CAIRO_STATUS_TAG_ERROR);
|
|
}
|
|
|
|
if (elem)
|
|
*elem = top;
|
|
else
|
|
_cairo_tag_stack_free_elem (top);
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
}
|
|
|
|
cairo_tag_stack_elem_t *
|
|
_cairo_tag_stack_top_elem (cairo_tag_stack_t *stack)
|
|
{
|
|
if (cairo_list_is_empty (&stack->list))
|
|
return NULL;
|
|
|
|
return cairo_list_last_entry (&stack->list, cairo_tag_stack_elem_t, link);
|
|
}
|
|
|
|
void
|
|
_cairo_tag_stack_free_elem (cairo_tag_stack_elem_t *elem)
|
|
{
|
|
free (elem->name);
|
|
free (elem->attributes);
|
|
free (elem);
|
|
}
|
|
|
|
cairo_tag_type_t
|
|
_cairo_tag_get_type (const char *name)
|
|
{
|
|
if (! name_in_list (name, _cairo_tag_stack_struct_pdf_list) &&
|
|
! name_in_list (name, _cairo_tag_stack_cairo_tag_list))
|
|
return TAG_TYPE_INVALID;
|
|
|
|
if (strcmp(name, "Link") == 0)
|
|
return (TAG_TYPE_LINK | TAG_TYPE_STRUCTURE);
|
|
|
|
if (strcmp(name, "cairo.dest") == 0)
|
|
return TAG_TYPE_DEST;
|
|
|
|
return TAG_TYPE_STRUCTURE;
|
|
}
|