Bug Summary

File:jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh
Warning:line 510, column 12
Potential leak of memory pointed to by 'p'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hb-subset.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -D GETPAGESIZE -D HAVE_MPROTECT -D HAVE_PTHREAD -D HAVE_SYSCONF -D HAVE_SYS_MMAN_H -D HAVE_UNISTD_H -D HB_NO_PRAGMA_GCC_DIAGNOSTIC -D HAVE_INTEL_ATOMIC_PRIMITIVES -I /usr/include/freetype2 -D LE_STANDALONE -D HEADLESS -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/libfontmanager -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libfontmanager -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.desktop -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/common/awt -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/awt -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/common/font -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/common/font -I /home/daniel/Projects/java/jdk/src/java.desktop/unix/native/libawt/java2d -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d/pipe -I /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libawt/java2d/loops -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-unused -Wno-type-limits -Wno-missing-field-initializers -Wno-strict-aliasing -Wno-reorder -Wno-delete-non-virtual-dtor -Wno-strict-overflow -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-unused-result -Wno-extra -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-subset.cc

/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-subset.cc

1/*
2 * Copyright © 2018 Google, Inc.
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
25 */
26
27#include "hb.hh"
28#include "hb-open-type.hh"
29
30#include "hb-subset.hh"
31
32#include "hb-open-file.hh"
33#include "hb-ot-cmap-table.hh"
34#include "hb-ot-glyf-table.hh"
35#include "hb-ot-hdmx-table.hh"
36#include "hb-ot-head-table.hh"
37#include "hb-ot-hhea-table.hh"
38#include "hb-ot-hmtx-table.hh"
39#include "hb-ot-maxp-table.hh"
40#include "hb-ot-color-sbix-table.hh"
41#include "hb-ot-color-colr-table.hh"
42#include "hb-ot-os2-table.hh"
43#include "hb-ot-post-table.hh"
44#include "hb-ot-cff1-table.hh"
45#include "hb-ot-cff2-table.hh"
46#include "hb-ot-vorg-table.hh"
47#include "hb-ot-name-table.hh"
48#include "hb-ot-color-cbdt-table.hh"
49#include "hb-ot-layout-gsub-table.hh"
50#include "hb-ot-layout-gpos-table.hh"
51#include "hb-ot-var-gvar-table.hh"
52#include "hb-ot-var-hvar-table.hh"
53
54
55static unsigned
56_plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len)
57{
58 unsigned src_glyphs = plan->source->get_num_glyphs ();
59 unsigned dst_glyphs = plan->glyphset ()->get_population ();
60
61 if (unlikely (!src_glyphs)(__builtin_expect (!!(!src_glyphs), 0)))
62 return 512 + table_len;
63
64 return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
65}
66
67template<typename TableType>
68static bool
69_subset (hb_subset_plan_t *plan)
70{
71 bool result = false;
72 hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
73 const TableType *table = source_blob->as<TableType> ();
74
75 hb_tag_t tag = TableType::tableTag;
76 if (source_blob->data)
1
Assuming field 'data' is non-null
2
Taking true branch
77 {
78 hb_vector_t<char> buf;
79 /* TODO Not all tables are glyph-related. 'name' table size for example should not be
80 * affected by number of glyphs. Accommodate that. */
81 unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
82 DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size)_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "OT::%c%c%c%c initial estimated table size: %u bytes."
, (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>
16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t
)((tag)&0xFF), buf_size)
;
83 if (unlikely (!buf.alloc (buf_size))(__builtin_expect (!!(!buf.alloc (buf_size)), 0)))
3
Assuming the condition is false
4
Taking false branch
84 {
85 DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size)_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "OT::%c%c%c%c failed to allocate %u bytes.", (uint8_t
)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&
0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&
0xFF), buf_size)
;
86 hb_blob_destroy (source_blob);
87 return false;
88 }
89 retry:
90 hb_serialize_context_t serializer ((void *) buf, buf_size);
91 serializer.start_serialize<TableType> ();
92 hb_subset_context_t c (source_blob, plan, &serializer, tag);
93 bool needed = table->subset (&c);
94 if (serializer.ran_out_of_room)
5
Assuming field 'ran_out_of_room' is false
6
Taking false branch
95 {
96 buf_size += (buf_size >> 1) + 32;
97 DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size)_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "OT::%c%c%c%c ran out of room; reallocating to %u bytes."
, (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>
16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t
)((tag)&0xFF), buf_size)
;
98 if (unlikely (!buf.alloc (buf_size))(__builtin_expect (!!(!buf.alloc (buf_size)), 0)))
99 {
100 DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size)_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "OT::%c%c%c%c failed to reallocate %u bytes.", (uint8_t
)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&
0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&
0xFF), buf_size)
;
101 hb_blob_destroy (source_blob);
102 return false;
103 }
104 goto retry;
105 }
106 serializer.end_serialize ();
107
108 result = !serializer.in_error ();
109
110 if (result
6.1
'result' is true
6.1
'result' is true
)
7
Taking true branch
111 {
112 if (needed
7.1
'needed' is true
7.1
'needed' is true
)
8
Taking true branch
113 {
114 hb_blob_t *dest_blob = serializer.copy_blob ();
9
Calling 'hb_serialize_context_t::copy_blob'
115 DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length)_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "OT::%c%c%c%c final subset table size: %u bytes.", (uint8_t
)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&
0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&
0xFF), dest_blob->length)
;
116 result = c.plan->add_table (tag, dest_blob);
117 hb_blob_destroy (dest_blob);
118 }
119 else
120 {
121 DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag))_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "OT::%c%c%c%c::subset table subsetted to empty.", (uint8_t
)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&
0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&
0xFF))
;
122 }
123 }
124 }
125 else
126 DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag))_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "OT::%c%c%c%c::subset sanitize failed on source table."
, (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>
16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t
)((tag)&0xFF))
;
127
128 hb_blob_destroy (source_blob);
129 DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!")_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "OT::%c%c%c%c::subset %s", (uint8_t)(((tag)>>24
)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)
(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF), result
? "success" : "FAILED!")
;
130 return result;
131}
132
133static bool
134_is_table_present (hb_face_t *source, hb_tag_t tag)
135{
136 hb_tag_t table_tags[32];
137 unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
138 while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
139 {
140 for (unsigned i = 0; i < num_tables; ++i)
141 if (table_tags[i] == tag)
142 return true;
143 offset += num_tables;
144 }
145 return false;
146}
147
148static bool
149_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
150{
151 if (plan->drop_tables->has (tag))
152 return true;
153
154 switch (tag)
155 {
156 case HB_TAG ('c','v','a','r')((hb_tag_t)((((uint32_t)('c')&0xFF)<<24)|(((uint32_t
)('v')&0xFF)<<16)|(((uint32_t)('a')&0xFF)<<
8)|((uint32_t)('r')&0xFF)))
: /* hint table, fallthrough */
157 case HB_TAG ('c','v','t',' ')((hb_tag_t)((((uint32_t)('c')&0xFF)<<24)|(((uint32_t
)('v')&0xFF)<<16)|(((uint32_t)('t')&0xFF)<<
8)|((uint32_t)(' ')&0xFF)))
: /* hint table, fallthrough */
158 case HB_TAG ('f','p','g','m')((hb_tag_t)((((uint32_t)('f')&0xFF)<<24)|(((uint32_t
)('p')&0xFF)<<16)|(((uint32_t)('g')&0xFF)<<
8)|((uint32_t)('m')&0xFF)))
: /* hint table, fallthrough */
159 case HB_TAG ('p','r','e','p')((hb_tag_t)((((uint32_t)('p')&0xFF)<<24)|(((uint32_t
)('r')&0xFF)<<16)|(((uint32_t)('e')&0xFF)<<
8)|((uint32_t)('p')&0xFF)))
: /* hint table, fallthrough */
160 case HB_TAG ('h','d','m','x')((hb_tag_t)((((uint32_t)('h')&0xFF)<<24)|(((uint32_t
)('d')&0xFF)<<16)|(((uint32_t)('m')&0xFF)<<
8)|((uint32_t)('x')&0xFF)))
: /* hint table, fallthrough */
161 case HB_TAG ('V','D','M','X')((hb_tag_t)((((uint32_t)('V')&0xFF)<<24)|(((uint32_t
)('D')&0xFF)<<16)|(((uint32_t)('M')&0xFF)<<
8)|((uint32_t)('X')&0xFF)))
: /* hint table, fallthrough */
162 return plan->drop_hints;
163
164#ifdef HB_NO_SUBSET_LAYOUT
165 // Drop Layout Tables if requested.
166 case HB_OT_TAG_GDEF((hb_tag_t)((((uint32_t)('G')&0xFF)<<24)|(((uint32_t
)('D')&0xFF)<<16)|(((uint32_t)('E')&0xFF)<<
8)|((uint32_t)('F')&0xFF)))
:
167 case HB_OT_TAG_GPOS((hb_tag_t)((((uint32_t)('G')&0xFF)<<24)|(((uint32_t
)('P')&0xFF)<<16)|(((uint32_t)('O')&0xFF)<<
8)|((uint32_t)('S')&0xFF)))
:
168 case HB_OT_TAG_GSUB((hb_tag_t)((((uint32_t)('G')&0xFF)<<24)|(((uint32_t
)('S')&0xFF)<<16)|(((uint32_t)('U')&0xFF)<<
8)|((uint32_t)('B')&0xFF)))
:
169 case HB_TAG ('m','o','r','x')((hb_tag_t)((((uint32_t)('m')&0xFF)<<24)|(((uint32_t
)('o')&0xFF)<<16)|(((uint32_t)('r')&0xFF)<<
8)|((uint32_t)('x')&0xFF)))
:
170 case HB_TAG ('m','o','r','t')((hb_tag_t)((((uint32_t)('m')&0xFF)<<24)|(((uint32_t
)('o')&0xFF)<<16)|(((uint32_t)('r')&0xFF)<<
8)|((uint32_t)('t')&0xFF)))
:
171 case HB_TAG ('k','e','r','x')((hb_tag_t)((((uint32_t)('k')&0xFF)<<24)|(((uint32_t
)('e')&0xFF)<<16)|(((uint32_t)('r')&0xFF)<<
8)|((uint32_t)('x')&0xFF)))
:
172 case HB_TAG ('k','e','r','n')((hb_tag_t)((((uint32_t)('k')&0xFF)<<24)|(((uint32_t
)('e')&0xFF)<<16)|(((uint32_t)('r')&0xFF)<<
8)|((uint32_t)('n')&0xFF)))
:
173 return true;
174#endif
175
176 default:
177 return false;
178 }
179}
180
181static bool
182_subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
183{
184 DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag))_hb_debug_msg<(0 +0)> ("SUBSET", (nullptr), nullptr, false
, 0, 0, "subset %c%c%c%c", (uint8_t)(((tag)>>24)&0xFF
), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>
8)&0xFF), (uint8_t)((tag)&0xFF))
;
185 switch (tag)
186 {
187 case HB_OT_TAG_glyf((hb_tag_t)((((uint32_t)('g')&0xFF)<<24)|(((uint32_t
)('l')&0xFF)<<16)|(((uint32_t)('y')&0xFF)<<
8)|((uint32_t)('f')&0xFF)))
: return _subset<const OT::glyf> (plan);
188 case HB_OT_TAG_hdmx((hb_tag_t)((((uint32_t)('h')&0xFF)<<24)|(((uint32_t
)('d')&0xFF)<<16)|(((uint32_t)('m')&0xFF)<<
8)|((uint32_t)('x')&0xFF)))
: return _subset<const OT::hdmx> (plan);
189 case HB_OT_TAG_name((hb_tag_t)((((uint32_t)('n')&0xFF)<<24)|(((uint32_t
)('a')&0xFF)<<16)|(((uint32_t)('m')&0xFF)<<
8)|((uint32_t)('e')&0xFF)))
: return _subset<const OT::name> (plan);
190 case HB_OT_TAG_head((hb_tag_t)((((uint32_t)('h')&0xFF)<<24)|(((uint32_t
)('e')&0xFF)<<16)|(((uint32_t)('a')&0xFF)<<
8)|((uint32_t)('d')&0xFF)))
:
191 if (_is_table_present (plan->source, HB_OT_TAG_glyf((hb_tag_t)((((uint32_t)('g')&0xFF)<<24)|(((uint32_t
)('l')&0xFF)<<16)|(((uint32_t)('y')&0xFF)<<
8)|((uint32_t)('f')&0xFF)))
) && !_should_drop_table (plan, HB_OT_TAG_glyf((hb_tag_t)((((uint32_t)('g')&0xFF)<<24)|(((uint32_t
)('l')&0xFF)<<16)|(((uint32_t)('y')&0xFF)<<
8)|((uint32_t)('f')&0xFF)))
))
192 return true; /* skip head, handled by glyf */
193 return _subset<const OT::head> (plan);
194 case HB_OT_TAG_hhea((hb_tag_t)((((uint32_t)('h')&0xFF)<<24)|(((uint32_t
)('h')&0xFF)<<16)|(((uint32_t)('e')&0xFF)<<
8)|((uint32_t)('a')&0xFF)))
: return true; /* skip hhea, handled by hmtx */
195 case HB_OT_TAG_hmtx((hb_tag_t)((((uint32_t)('h')&0xFF)<<24)|(((uint32_t
)('m')&0xFF)<<16)|(((uint32_t)('t')&0xFF)<<
8)|((uint32_t)('x')&0xFF)))
: return _subset<const OT::hmtx> (plan);
196 case HB_OT_TAG_vhea((hb_tag_t)((((uint32_t)('v')&0xFF)<<24)|(((uint32_t
)('h')&0xFF)<<16)|(((uint32_t)('e')&0xFF)<<
8)|((uint32_t)('a')&0xFF)))
: return true; /* skip vhea, handled by vmtx */
197 case HB_OT_TAG_vmtx((hb_tag_t)((((uint32_t)('v')&0xFF)<<24)|(((uint32_t
)('m')&0xFF)<<16)|(((uint32_t)('t')&0xFF)<<
8)|((uint32_t)('x')&0xFF)))
: return _subset<const OT::vmtx> (plan);
198 case HB_OT_TAG_maxp((hb_tag_t)((((uint32_t)('m')&0xFF)<<24)|(((uint32_t
)('a')&0xFF)<<16)|(((uint32_t)('x')&0xFF)<<
8)|((uint32_t)('p')&0xFF)))
: return _subset<const OT::maxp> (plan);
199 case HB_OT_TAG_sbix((hb_tag_t)((((uint32_t)('s')&0xFF)<<24)|(((uint32_t
)('b')&0xFF)<<16)|(((uint32_t)('i')&0xFF)<<
8)|((uint32_t)('x')&0xFF)))
: return _subset<const OT::sbix> (plan);
200 case HB_OT_TAG_loca((hb_tag_t)((((uint32_t)('l')&0xFF)<<24)|(((uint32_t
)('o')&0xFF)<<16)|(((uint32_t)('c')&0xFF)<<
8)|((uint32_t)('a')&0xFF)))
: return true; /* skip loca, handled by glyf */
201 case HB_OT_TAG_cmap((hb_tag_t)((((uint32_t)('c')&0xFF)<<24)|(((uint32_t
)('m')&0xFF)<<16)|(((uint32_t)('a')&0xFF)<<
8)|((uint32_t)('p')&0xFF)))
: return _subset<const OT::cmap> (plan);
202 case HB_OT_TAG_OS2((hb_tag_t)((((uint32_t)('O')&0xFF)<<24)|(((uint32_t
)('S')&0xFF)<<16)|(((uint32_t)('/')&0xFF)<<
8)|((uint32_t)('2')&0xFF)))
: return _subset<const OT::OS2 > (plan);
203 case HB_OT_TAG_post((hb_tag_t)((((uint32_t)('p')&0xFF)<<24)|(((uint32_t
)('o')&0xFF)<<16)|(((uint32_t)('s')&0xFF)<<
8)|((uint32_t)('t')&0xFF)))
: return _subset<const OT::post> (plan);
204 case HB_OT_TAG_COLR((hb_tag_t)((((uint32_t)('C')&0xFF)<<24)|(((uint32_t
)('O')&0xFF)<<16)|(((uint32_t)('L')&0xFF)<<
8)|((uint32_t)('R')&0xFF)))
: return _subset<const OT::COLR> (plan);
205 case HB_OT_TAG_CBLC((hb_tag_t)((((uint32_t)('C')&0xFF)<<24)|(((uint32_t
)('B')&0xFF)<<16)|(((uint32_t)('L')&0xFF)<<
8)|((uint32_t)('C')&0xFF)))
: return _subset<const OT::CBLC> (plan);
206 case HB_OT_TAG_CBDT((hb_tag_t)((((uint32_t)('C')&0xFF)<<24)|(((uint32_t
)('B')&0xFF)<<16)|(((uint32_t)('D')&0xFF)<<
8)|((uint32_t)('T')&0xFF)))
: return true; /* skip CBDT, handled by CBLC */
207
208#ifndef HB_NO_SUBSET_CFF
209 case HB_OT_TAG_cff1((hb_tag_t)((((uint32_t)('C')&0xFF)<<24)|(((uint32_t
)('F')&0xFF)<<16)|(((uint32_t)('F')&0xFF)<<
8)|((uint32_t)(' ')&0xFF)))
: return _subset<const OT::cff1> (plan);
210 case HB_OT_TAG_cff2((hb_tag_t)((((uint32_t)('C')&0xFF)<<24)|(((uint32_t
)('F')&0xFF)<<16)|(((uint32_t)('F')&0xFF)<<
8)|((uint32_t)('2')&0xFF)))
: return _subset<const OT::cff2> (plan);
211 case HB_OT_TAG_VORG((hb_tag_t)((((uint32_t)('V')&0xFF)<<24)|(((uint32_t
)('O')&0xFF)<<16)|(((uint32_t)('R')&0xFF)<<
8)|((uint32_t)('G')&0xFF)))
: return _subset<const OT::VORG> (plan);
212#endif
213
214#ifndef HB_NO_SUBSET_LAYOUT
215 case HB_OT_TAG_GDEF((hb_tag_t)((((uint32_t)('G')&0xFF)<<24)|(((uint32_t
)('D')&0xFF)<<16)|(((uint32_t)('E')&0xFF)<<
8)|((uint32_t)('F')&0xFF)))
: return _subset<const OT::GDEF> (plan);
216 case HB_OT_TAG_GSUB((hb_tag_t)((((uint32_t)('G')&0xFF)<<24)|(((uint32_t
)('S')&0xFF)<<16)|(((uint32_t)('U')&0xFF)<<
8)|((uint32_t)('B')&0xFF)))
: return _subset<const OT::GSUB> (plan);
217 case HB_OT_TAG_GPOS((hb_tag_t)((((uint32_t)('G')&0xFF)<<24)|(((uint32_t
)('P')&0xFF)<<16)|(((uint32_t)('O')&0xFF)<<
8)|((uint32_t)('S')&0xFF)))
: return _subset<const OT::GPOS> (plan);
218 case HB_OT_TAG_gvar((hb_tag_t)((((uint32_t)('g')&0xFF)<<24)|(((uint32_t
)('v')&0xFF)<<16)|(((uint32_t)('a')&0xFF)<<
8)|((uint32_t)('r')&0xFF)))
: return _subset<const OT::gvar> (plan);
219 case HB_OT_TAG_HVAR((hb_tag_t)((((uint32_t)('H')&0xFF)<<24)|(((uint32_t
)('V')&0xFF)<<16)|(((uint32_t)('A')&0xFF)<<
8)|((uint32_t)('R')&0xFF)))
: return _subset<const OT::HVAR> (plan);
220 case HB_OT_TAG_VVAR((hb_tag_t)((((uint32_t)('V')&0xFF)<<24)|(((uint32_t
)('V')&0xFF)<<16)|(((uint32_t)('A')&0xFF)<<
8)|((uint32_t)('R')&0xFF)))
: return _subset<const OT::VVAR> (plan);
221#endif
222
223 default:
224 hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
225 bool result = plan->add_table (tag, source_table);
226 hb_blob_destroy (source_table);
227 return result;
228 }
229}
230
231/**
232 * hb_subset:
233 * @source: font face data to be subset.
234 * @input: input to use for the subsetting.
235 *
236 * Subsets a font according to provided input.
237 **/
238hb_face_t *
239hb_subset (hb_face_t *source, hb_subset_input_t *input)
240{
241 if (unlikely (!input || !source)(__builtin_expect (!!(!input || !source), 0))) return hb_face_get_empty ();
242
243 hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
244 if (unlikely (plan->in_error ())(__builtin_expect (!!(plan->in_error ()), 0)))
245 return hb_face_get_empty ();
246
247 hb_set_t tags_set;
248 bool success = true;
249 hb_tag_t table_tags[32];
250 unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
251 while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
252 {
253 for (unsigned i = 0; i < num_tables; ++i)
254 {
255 hb_tag_t tag = table_tags[i];
256 if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue;
257 tags_set.add (tag);
258 success = _subset_table (plan, tag);
259 if (unlikely (!success)(__builtin_expect (!!(!success), 0))) goto end;
260 }
261 offset += num_tables;
262 }
263end:
264
265 hb_face_t *result = success ? hb_face_reference (plan->dest) : hb_face_get_empty ();
266
267 hb_subset_plan_destroy (plan);
268 return result;
269}

/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh

1/*
2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
3 * Copyright © 2012,2018 Google, Inc.
4 * Copyright © 2019 Facebook, Inc.
5 *
6 * This is part of HarfBuzz, a text shaping library.
7 *
8 * Permission is hereby granted, without written agreement and without
9 * license or royalty fees, to use, copy, modify, and distribute this
10 * software and its documentation for any purpose, provided that the
11 * above copyright notice and the following two paragraphs appear in
12 * all copies of this software.
13 *
14 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * DAMAGE.
19 *
20 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 *
26 * Red Hat Author(s): Behdad Esfahbod
27 * Google Author(s): Behdad Esfahbod
28 * Facebook Author(s): Behdad Esfahbod
29 */
30
31#ifndef HB_SERIALIZE_HH
32#define HB_SERIALIZE_HH
33
34#include "hb.hh"
35#include "hb-blob.hh"
36#include "hb-map.hh"
37#include "hb-pool.hh"
38
39
40/*
41 * Serialize
42 */
43
44struct hb_serialize_context_t
45{
46 typedef unsigned objidx_t;
47
48 enum whence_t {
49 Head, /* Relative to the current object head (default). */
50 Tail, /* Relative to the current object tail after packed. */
51 Absolute /* Absolute: from the start of the serialize buffer. */
52 };
53
54 struct object_t
55 {
56 void fini () { links.fini (); }
57
58 bool operator == (const object_t &o) const
59 {
60 return (tail - head == o.tail - o.head)
61 && (links.length == o.links.length)
62 && 0 == hb_memcmp (head, o.head, tail - head)
63 && links.as_bytes () == o.links.as_bytes ();
64 }
65 uint32_t hash () const
66 {
67 return hb_bytes_t (head, tail - head).hash () ^
68 links.as_bytes ().hash ();
69 }
70
71 struct link_t
72 {
73 bool is_wide: 1;
74 bool is_signed: 1;
75 unsigned whence: 2;
76 unsigned position: 28;
77 unsigned bias;
78 objidx_t objidx;
79 };
80
81 char *head;
82 char *tail;
83 hb_vector_t<link_t> links;
84 object_t *next;
85 };
86
87 struct snapshot_t
88 {
89 char *head;
90 char *tail;
91 object_t *current; // Just for sanity check
92 unsigned num_links;
93 };
94
95 snapshot_t snapshot ()
96 { return snapshot_t { head, tail, current, current->links.length }; }
97
98 hb_serialize_context_t (void *start_, unsigned int size) :
99 start ((char *) start_),
100 end (start + size),
101 current (nullptr)
102 { reset (); }
103 ~hb_serialize_context_t () { fini (); }
104
105 void fini ()
106 {
107 for (object_t *_ : ++hb_iter (packed)) _->fini ();
108 packed.fini ();
109 this->packed_map.fini ();
110
111 while (current)
112 {
113 auto *_ = current;
114 current = current->next;
115 _->fini ();
116 }
117 object_pool.fini ();
118 }
119
120 bool in_error () const { return !this->successful; }
121
122 void reset ()
123 {
124 this->successful = true;
125 this->ran_out_of_room = false;
126 this->head = this->start;
127 this->tail = this->end;
128 this->debug_depth = 0;
129
130 fini ();
131 this->packed.push (nullptr);
132 }
133
134 bool check_success (bool success)
135 { return this->successful && (success || (err_other_error (), false)); }
136
137 template <typename T1, typename T2>
138 bool check_equal (T1 &&v1, T2 &&v2)
139 { return check_success ((long long) v1 == (long long) v2); }
140
141 template <typename T1, typename T2>
142 bool check_assign (T1 &v1, T2 &&v2)
143 { return check_equal (v1 = v2, v2); }
144
145 template <typename T> bool propagate_error (T &&obj)
146 { return check_success (!hb_deref (obj).in_error ()); }
147
148 template <typename T1, typename... Ts> bool propagate_error (T1 &&o1, Ts&&... os)
149 { return propagate_error (hb_forward<T1> (o1)) &&
150 propagate_error (hb_forward<Ts> (os)...); }
151
152 /* To be called around main operation. */
153 template <typename Type>
154 Type *start_serialize ()
155 {
156 DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (+1), "start [%p..%p] (%lu bytes)", this->start
, this->end, (unsigned long) (this->end - this->start
))
157 "start [%p..%p] (%lu bytes)",_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (+1), "start [%p..%p] (%lu bytes)", this->start
, this->end, (unsigned long) (this->end - this->start
))
158 this->start, this->end,_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (+1), "start [%p..%p] (%lu bytes)", this->start
, this->end, (unsigned long) (this->end - this->start
))
159 (unsigned long) (this->end - this->start))_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (+1), "start [%p..%p] (%lu bytes)", this->start
, this->end, (unsigned long) (this->end - this->start
))
;
160
161 assert (!current)(static_cast <bool> (!current) ? void (0) : __assert_fail
("!current", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 161, __extension__ __PRETTY_FUNCTION__))
;
162 return push<Type> ();
163 }
164 void end_serialize ()
165 {
166 DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (-1), "end [%p..%p] serialized %u bytes; %s", this
->start, this->end, (unsigned) (this->head - this->
start), this->successful ? "successful" : "UNSUCCESSFUL")
167 "end [%p..%p] serialized %u bytes; %s",_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (-1), "end [%p..%p] serialized %u bytes; %s", this
->start, this->end, (unsigned) (this->head - this->
start), this->successful ? "successful" : "UNSUCCESSFUL")
168 this->start, this->end,_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (-1), "end [%p..%p] serialized %u bytes; %s", this
->start, this->end, (unsigned) (this->head - this->
start), this->successful ? "successful" : "UNSUCCESSFUL")
169 (unsigned) (this->head - this->start),_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (-1), "end [%p..%p] serialized %u bytes; %s", this
->start, this->end, (unsigned) (this->head - this->
start), this->successful ? "successful" : "UNSUCCESSFUL")
170 this->successful ? "successful" : "UNSUCCESSFUL")_hb_debug_msg<(0 +0)> ("SERIALIZE", (this->start), nullptr
, true, (0), (-1), "end [%p..%p] serialized %u bytes; %s", this
->start, this->end, (unsigned) (this->head - this->
start), this->successful ? "successful" : "UNSUCCESSFUL")
;
171
172 propagate_error (packed, packed_map);
173
174 if (unlikely (!current)(__builtin_expect (!!(!current), 0))) return;
175 if (unlikely (in_error())(__builtin_expect (!!(in_error()), 0))) return;
176
177 assert (!current->next)(static_cast <bool> (!current->next) ? void (0) : __assert_fail
("!current->next", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 177, __extension__ __PRETTY_FUNCTION__))
;
178
179 /* Only "pack" if there exist other objects... Otherwise, don't bother.
180 * Saves a move. */
181 if (packed.length <= 1)
182 return;
183
184 pop_pack (false);
185
186 resolve_links ();
187 }
188
189 template <typename Type = void>
190 Type *push ()
191 {
192 if (unlikely (in_error ())(__builtin_expect (!!(in_error ()), 0))) return start_embed<Type> ();
193
194 object_t *obj = object_pool.alloc ();
195 if (unlikely (!obj)(__builtin_expect (!!(!obj), 0)))
196 check_success (false);
197 else
198 {
199 obj->head = head;
200 obj->tail = tail;
201 obj->next = current;
202 current = obj;
203 }
204 return start_embed<Type> ();
205 }
206 void pop_discard ()
207 {
208 object_t *obj = current;
209 if (unlikely (!obj)(__builtin_expect (!!(!obj), 0))) return;
210 if (unlikely (in_error())(__builtin_expect (!!(in_error()), 0))) return;
211
212 current = current->next;
213 revert (obj->head, obj->tail);
214 obj->fini ();
215 object_pool.free (obj);
216 }
217
218 /* Set share to false when an object is unlikely sharable with others
219 * so not worth an attempt, or a contiguous table is serialized as
220 * multiple consecutive objects in the reverse order so can't be shared.
221 */
222 objidx_t pop_pack (bool share=true)
223 {
224 object_t *obj = current;
225 if (unlikely (!obj)(__builtin_expect (!!(!obj), 0))) return 0;
226 if (unlikely (in_error())(__builtin_expect (!!(in_error()), 0))) return 0;
227
228 current = current->next;
229 obj->tail = head;
230 obj->next = nullptr;
231 unsigned len = obj->tail - obj->head;
232 head = obj->head; /* Rewind head. */
233
234 if (!len)
235 {
236 assert (!obj->links.length)(static_cast <bool> (!obj->links.length) ? void (0) :
__assert_fail ("!obj->links.length", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 236, __extension__ __PRETTY_FUNCTION__))
;
237 return 0;
238 }
239
240 objidx_t objidx;
241 if (share)
242 {
243 objidx = packed_map.get (obj);
244 if (objidx)
245 {
246 obj->fini ();
247 return objidx;
248 }
249 }
250
251 tail -= len;
252 memmove (tail, obj->head, len);
253
254 obj->head = tail;
255 obj->tail = tail + len;
256
257 packed.push (obj);
258
259 if (unlikely (!propagate_error (packed))(__builtin_expect (!!(!propagate_error (packed)), 0)))
260 {
261 /* Obj wasn't successfully added to packed, so clean it up otherwise its
262 * links will be leaked. When we use constructor/destructors properly, we
263 * can remove these. */
264 obj->fini ();
265 return 0;
266 }
267
268 objidx = packed.length - 1;
269
270 if (share) packed_map.set (obj, objidx);
271 propagate_error (packed_map);
272
273 return objidx;
274 }
275
276 void revert (snapshot_t snap)
277 {
278 if (unlikely (in_error ())(__builtin_expect (!!(in_error ()), 0))) return;
279 assert (snap.current == current)(static_cast <bool> (snap.current == current) ? void (0
) : __assert_fail ("snap.current == current", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 279, __extension__ __PRETTY_FUNCTION__))
;
280 current->links.shrink (snap.num_links);
281 revert (snap.head, snap.tail);
282 }
283
284 void revert (char *snap_head,
285 char *snap_tail)
286 {
287 if (unlikely (in_error ())(__builtin_expect (!!(in_error ()), 0))) return;
288 assert (snap_head <= head)(static_cast <bool> (snap_head <= head) ? void (0) :
__assert_fail ("snap_head <= head", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 288, __extension__ __PRETTY_FUNCTION__))
;
289 assert (tail <= snap_tail)(static_cast <bool> (tail <= snap_tail) ? void (0) :
__assert_fail ("tail <= snap_tail", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 289, __extension__ __PRETTY_FUNCTION__))
;
290 head = snap_head;
291 tail = snap_tail;
292 discard_stale_objects ();
293 }
294
295 void discard_stale_objects ()
296 {
297 if (unlikely (in_error ())(__builtin_expect (!!(in_error ()), 0))) return;
298 while (packed.length > 1 &&
299 packed.tail ()->head < tail)
300 {
301 packed_map.del (packed.tail ());
302 assert (!packed.tail ()->next)(static_cast <bool> (!packed.tail ()->next) ? void (
0) : __assert_fail ("!packed.tail ()->next", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 302, __extension__ __PRETTY_FUNCTION__))
;
303 packed.tail ()->fini ();
304 packed.pop ();
305 }
306 if (packed.length > 1)
307 assert (packed.tail ()->head == tail)(static_cast <bool> (packed.tail ()->head == tail) ?
void (0) : __assert_fail ("packed.tail ()->head == tail",
"/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 307, __extension__ __PRETTY_FUNCTION__))
;
308 }
309
310 template <typename T>
311 void add_link (T &ofs, objidx_t objidx,
312 whence_t whence = Head,
313 unsigned bias = 0)
314 {
315 static_assert (sizeof (T) == 2 || sizeof (T) == 4, "");
316 if (unlikely (in_error ())(__builtin_expect (!!(in_error ()), 0))) return;
317
318 if (!objidx)
319 return;
320
321 assert (current)(static_cast <bool> (current) ? void (0) : __assert_fail
("current", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 321, __extension__ __PRETTY_FUNCTION__))
;
322 assert (current->head <= (const char *) &ofs)(static_cast <bool> (current->head <= (const char
*) &ofs) ? void (0) : __assert_fail ("current->head <= (const char *) &ofs"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 322, __extension__ __PRETTY_FUNCTION__))
;
323
324 auto& link = *current->links.push ();
325
326 link.is_wide = sizeof (T) == 4;
327 link.is_signed = hb_is_signed (hb_unwrap_type (T))hb_is_signed<typename hb_unwrap_type<T>::type>::value;
328 link.whence = (unsigned) whence;
329 link.position = (const char *) &ofs - current->head;
330 link.bias = bias;
331 link.objidx = objidx;
332 }
333
334 unsigned to_bias (const void *base) const
335 {
336 if (unlikely (in_error ())(__builtin_expect (!!(in_error ()), 0))) return 0;
337 if (!base) return 0;
338 assert (current)(static_cast <bool> (current) ? void (0) : __assert_fail
("current", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 338, __extension__ __PRETTY_FUNCTION__))
;
339 assert (current->head <= (const char *) base)(static_cast <bool> (current->head <= (const char
*) base) ? void (0) : __assert_fail ("current->head <= (const char *) base"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 339, __extension__ __PRETTY_FUNCTION__))
;
340 return (const char *) base - current->head;
341 }
342
343 void resolve_links ()
344 {
345 if (unlikely (in_error ())(__builtin_expect (!!(in_error ()), 0))) return;
346
347 assert (!current)(static_cast <bool> (!current) ? void (0) : __assert_fail
("!current", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 347, __extension__ __PRETTY_FUNCTION__))
;
348 assert (packed.length > 1)(static_cast <bool> (packed.length > 1) ? void (0) :
__assert_fail ("packed.length > 1", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 348, __extension__ __PRETTY_FUNCTION__))
;
349
350 for (const object_t* parent : ++hb_iter (packed))
351 for (const object_t::link_t &link : parent->links)
352 {
353 const object_t* child = packed[link.objidx];
354 if (unlikely (!child)(__builtin_expect (!!(!child), 0))) { err_other_error(); return; }
355 unsigned offset = 0;
356 switch ((whence_t) link.whence) {
357 case Head: offset = child->head - parent->head; break;
358 case Tail: offset = child->head - parent->tail; break;
359 case Absolute: offset = (head - start) + (child->head - tail); break;
360 }
361
362 assert (offset >= link.bias)(static_cast <bool> (offset >= link.bias) ? void (0)
: __assert_fail ("offset >= link.bias", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 362, __extension__ __PRETTY_FUNCTION__))
;
363 offset -= link.bias;
364 if (link.is_signed)
365 {
366 if (link.is_wide)
367 assign_offset<int32_t> (parent, link, offset);
368 else
369 assign_offset<int16_t> (parent, link, offset);
370 }
371 else
372 {
373 if (link.is_wide)
374 assign_offset<uint32_t> (parent, link, offset);
375 else
376 assign_offset<uint16_t> (parent, link, offset);
377 }
378 }
379 }
380
381 unsigned int length () const
382 {
383 if (unlikely (!current)(__builtin_expect (!!(!current), 0))) return 0;
384 return this->head - current->head;
385 }
386
387 void align (unsigned int alignment)
388 {
389 unsigned int l = length () % alignment;
390 if (l)
391 allocate_size<void> (alignment - l);
392 }
393
394 template <typename Type = void>
395 Type *start_embed (const Type *obj HB_UNUSED__attribute__((unused)) = nullptr) const
396 { return reinterpret_cast<Type *> (this->head); }
397 template <typename Type>
398 Type *start_embed (const Type &obj) const
399 { return start_embed (hb_addressof (obj)); }
400
401 /* Following two functions exist to allow setting breakpoint on. */
402 void err_ran_out_of_room () { this->ran_out_of_room = true; }
403 void err_other_error () { this->successful = false; }
404
405 template <typename Type>
406 Type *allocate_size (unsigned int size)
407 {
408 if (unlikely (!this->successful)(__builtin_expect (!!(!this->successful), 0))) return nullptr;
409
410 if (this->tail - this->head < ptrdiff_t (size))
411 {
412 err_ran_out_of_room ();
413 this->successful = false;
414 return nullptr;
415 }
416 memset (this->head, 0, size);
417 char *ret = this->head;
418 this->head += size;
419 return reinterpret_cast<Type *> (ret);
420 }
421
422 template <typename Type>
423 Type *allocate_min ()
424 { return this->allocate_size<Type> (Type::min_size); }
425
426 template <typename Type>
427 Type *embed (const Type *obj)
428 {
429 unsigned int size = obj->get_size ();
430 Type *ret = this->allocate_size<Type> (size);
431 if (unlikely (!ret)(__builtin_expect (!!(!ret), 0))) return nullptr;
432 memcpy (ret, obj, size);
433 return ret;
434 }
435 template <typename Type>
436 Type *embed (const Type &obj)
437 { return embed (hb_addressof (obj)); }
438
439 template <typename Type, typename ...Ts> auto
440 _copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN-> hb_head_t<Type *, decltype ((src.copy (this, hb_forward
<Ts> (ds)...)))> { return (src.copy (this, hb_forward
<Ts> (ds)...)); }
441 (Type *, src.copy (this, hb_forward<Ts> (ds)...))-> hb_head_t<Type *, decltype ((src.copy (this, hb_forward
<Ts> (ds)...)))> { return (src.copy (this, hb_forward
<Ts> (ds)...)); }
442
443 template <typename Type> auto
444 _copy (const Type &src, hb_priority<0>) -> decltype (&(hb_declval<Type> () = src))
445 {
446 Type *ret = this->allocate_size<Type> (sizeof (Type));
447 if (unlikely (!ret)(__builtin_expect (!!(!ret), 0))) return nullptr;
448 *ret = src;
449 return ret;
450 }
451
452 /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
453 * instead of memcpy(). */
454 template <typename Type, typename ...Ts>
455 Type *copy (const Type &src, Ts&&... ds)
456 { return _copy (src, hb_prioritizehb_priority<16> (), hb_forward<Ts> (ds)...); }
457 template <typename Type, typename ...Ts>
458 Type *copy (const Type *src, Ts&&... ds)
459 { return copy (*src, hb_forward<Ts> (ds)...); }
460
461 template<typename Iterator,
462 hb_requires (hb_is_iterator (Iterator))typename hb_enable_if<((hb_is_iterator_of<Iterator, typename
Iterator::item_t>::value))>::type* = nullptr
,
463 typename ...Ts>
464 void copy_all (Iterator it, Ts&&... ds)
465 { for (decltype (*it) _ : it) copy (_, hb_forward<Ts> (ds)...); }
466
467 template <typename Type>
468 hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }
469
470 template <typename Type>
471 Type *extend_size (Type *obj, unsigned int size)
472 {
473 if (unlikely (in_error ())(__builtin_expect (!!(in_error ()), 0))) return nullptr;
474
475 assert (this->start <= (char *) obj)(static_cast <bool> (this->start <= (char *) obj)
? void (0) : __assert_fail ("this->start <= (char *) obj"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 475, __extension__ __PRETTY_FUNCTION__))
;
476 assert ((char *) obj <= this->head)(static_cast <bool> ((char *) obj <= this->head) ?
void (0) : __assert_fail ("(char *) obj <= this->head"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 476, __extension__ __PRETTY_FUNCTION__))
;
477 assert ((char *) obj + size >= this->head)(static_cast <bool> ((char *) obj + size >= this->
head) ? void (0) : __assert_fail ("(char *) obj + size >= this->head"
, "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 477, __extension__ __PRETTY_FUNCTION__))
;
478 if (unlikely (!this->allocate_size<Type> (((char *) obj) + size - this->head))(__builtin_expect (!!(!this->allocate_size<Type> (((
char *) obj) + size - this->head)), 0))
) return nullptr;
479 return reinterpret_cast<Type *> (obj);
480 }
481 template <typename Type>
482 Type *extend_size (Type &obj, unsigned int size)
483 { return extend_size (hb_addressof (obj), size); }
484
485 template <typename Type>
486 Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); }
487 template <typename Type>
488 Type *extend_min (Type &obj) { return extend_min (hb_addressof (obj)); }
489
490 template <typename Type, typename ...Ts>
491 Type *extend (Type *obj, Ts&&... ds)
492 { return extend_size (obj, obj->get_size (hb_forward<Ts> (ds)...)); }
493 template <typename Type, typename ...Ts>
494 Type *extend (Type &obj, Ts&&... ds)
495 { return extend (hb_addressof (obj), hb_forward<Ts> (ds)...); }
496
497 /* Output routines. */
498 hb_bytes_t copy_bytes () const
499 {
500 assert (this->successful)(static_cast <bool> (this->successful) ? void (0) : __assert_fail
("this->successful", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 500, __extension__ __PRETTY_FUNCTION__))
;
11
'?' condition is true
501 /* Copy both items from head side and tail side... */
502 unsigned int len = (this->head - this->start)
503 + (this->end - this->tail);
504
505 char *p = (char *) malloc (len);
12
Memory is allocated
506 if (unlikely (!p)(__builtin_expect (!!(!p), 0))) return hb_bytes_t ();
13
Assuming 'p' is non-null
14
Taking false branch
507
508 memcpy (p, this->start, this->head - this->start);
509 memcpy (p + (this->head - this->start), this->tail, this->end - this->tail);
510 return hb_bytes_t (p, len);
15
Potential leak of memory pointed to by 'p'
511 }
512 template <typename Type>
513 Type *copy () const
514 { return reinterpret_cast<Type *> ((char *) copy_bytes ().arrayZ); }
515 hb_blob_t *copy_blob () const
516 {
517 hb_bytes_t b = copy_bytes ();
10
Calling 'hb_serialize_context_t::copy_bytes'
518 return hb_blob_create (b.arrayZ, b.length,
519 HB_MEMORY_MODE_WRITABLE,
520 (char *) b.arrayZ, free);
521 }
522
523 private:
524 template <typename T>
525 void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
526 {
527 auto &off = * ((BEInt<T> *) (parent->head + link.position));
528 assert (0 == off)(static_cast <bool> (0 == off) ? void (0) : __assert_fail
("0 == off", "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-serialize.hh"
, 528, __extension__ __PRETTY_FUNCTION__))
;
529 check_assign (off, offset);
530 }
531
532 public: /* TODO Make private. */
533 char *start, *head, *tail, *end;
534 unsigned int debug_depth;
535 bool successful;
536 bool ran_out_of_room;
537
538 private:
539
540 /* Object memory pool. */
541 hb_pool_t<object_t> object_pool;
542
543 /* Stack of currently under construction objects. */
544 object_t *current;
545
546 /* Stack of packed objects. Object 0 is always nil object. */
547 hb_vector_t<object_t *> packed;
548
549 /* Map view of packed objects. */
550 hb_hashmap_t<const object_t *, objidx_t, nullptr, 0> packed_map;
551};
552
553
554#endif /* HB_SERIALIZE_HH */