~ubuntu-branches/ubuntu/trusty/pango1.0/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/00git_memory_leak.patch/pango/opentype/hb-blob.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2012-11-12 13:23:16 UTC
  • mfrom: (1.6.5) (63.3.31 sid)
  • Revision ID: package-import@ubuntu.com-20121112132316-1cffyagrjxx8tvmg
Tags: 1.30.1-1
* New upstream bug fix release.
* debian/libpango1.0-0.symbols: Add new symbol from this release.
* Grab a few fixes from upstream (via Ubuntu package, thanks Robert Ancell):
  - 00git_missing_prototype.patch: Add missing method prototype.
  - 00git_memory_leak.patch: Fix memory leak (LP: #837145)
  - 00git_thai_zero_width_spaces.patch: correctly handle zero width spaces
    in Thai (LP: #986008)
* Add debian/tests: Simple compile/link/run autopkg test. Thanks to Rafał
  Cieślak! (LP: #1073637)
* debian/control.in: Set Vcs-* to experimental branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2009  Red Hat, Inc.
 
3
 *
 
4
 *  This is part of HarfBuzz, an OpenType Layout engine 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
 * Red Hat Author(s): Behdad Esfahbod
 
25
 */
 
26
 
 
27
#include "hb-private.h"
 
28
 
 
29
#include "hb-blob.h"
 
30
 
 
31
#ifdef HAVE_SYS_MMAN_H
 
32
#ifdef HAVE_UNISTD_H
 
33
#include <unistd.h>
 
34
#endif /* HAVE_UNISTD_H */
 
35
#include <sys/mman.h>
 
36
#endif /* HAVE_SYS_MMAN_H */
 
37
 
 
38
#ifndef HB_DEBUG_BLOB
 
39
#define HB_DEBUG_BLOB HB_DEBUG
 
40
#endif
 
41
 
 
42
struct _hb_blob_t {
 
43
  hb_reference_count_t ref_count;
 
44
 
 
45
  unsigned int length;
 
46
 
 
47
  hb_mutex_t lock;
 
48
  /* the rest are protected by lock */
 
49
 
 
50
  unsigned int lock_count;
 
51
  hb_memory_mode_t mode;
 
52
 
 
53
  const char *data;
 
54
 
 
55
  hb_destroy_func_t destroy;
 
56
  void *user_data;
 
57
};
 
58
static hb_blob_t _hb_blob_nil = {
 
59
  HB_REFERENCE_COUNT_INVALID, /* ref_count */
 
60
 
 
61
  0, /* length */
 
62
 
 
63
  HB_MUTEX_INIT, /* lock */
 
64
 
 
65
  0, /* lock_count */
 
66
  HB_MEMORY_MODE_READONLY, /* mode */
 
67
 
 
68
  NULL, /* data */
 
69
 
 
70
  NULL, /* destroy */
 
71
  NULL /* user_data */
 
72
};
 
73
 
 
74
static void
 
75
_hb_blob_destroy_user_data (hb_blob_t *blob)
 
76
{
 
77
  if (blob->destroy) {
 
78
    blob->destroy (blob->user_data);
 
79
    blob->destroy = NULL;
 
80
    blob->user_data = NULL;
 
81
  }
 
82
}
 
83
 
 
84
static void
 
85
_hb_blob_unlock_and_destroy (hb_blob_t *blob)
 
86
{
 
87
  hb_blob_unlock (blob);
 
88
  hb_blob_destroy (blob);
 
89
}
 
90
 
 
91
hb_blob_t *
 
92
hb_blob_create (const char        *data,
 
93
                unsigned int       length,
 
94
                hb_memory_mode_t   mode,
 
95
                hb_destroy_func_t  destroy,
 
96
                void              *user_data)
 
97
{
 
98
  hb_blob_t *blob;
 
99
 
 
100
  if (!length || !HB_OBJECT_DO_CREATE (hb_blob_t, blob)) {
 
101
    if (destroy)
 
102
      destroy (user_data);
 
103
    return &_hb_blob_nil;
 
104
  }
 
105
 
 
106
  hb_mutex_init (blob->lock);
 
107
  blob->lock_count = 0;
 
108
 
 
109
  blob->data = data;
 
110
  blob->length = length;
 
111
  blob->mode = mode;
 
112
 
 
113
  blob->destroy = destroy;
 
114
  blob->user_data = user_data;
 
115
 
 
116
  if (blob->mode == HB_MEMORY_MODE_DUPLICATE) {
 
117
    blob->mode = HB_MEMORY_MODE_READONLY;
 
118
    if (!hb_blob_try_writable (blob)) {
 
119
      hb_blob_destroy (blob);
 
120
      return &_hb_blob_nil;
 
121
    }
 
122
  }
 
123
 
 
124
  return blob;
 
125
}
 
126
 
 
127
hb_blob_t *
 
128
hb_blob_create_sub_blob (hb_blob_t    *parent,
 
129
                         unsigned int  offset,
 
130
                         unsigned int  length)
 
131
{
 
132
  hb_blob_t *blob;
 
133
  const char *pdata;
 
134
 
 
135
  if (!length || offset >= parent->length || !HB_OBJECT_DO_CREATE (hb_blob_t, blob))
 
136
    return &_hb_blob_nil;
 
137
 
 
138
  pdata = hb_blob_lock (parent);
 
139
 
 
140
  blob->data = pdata + offset;
 
141
  blob->length = MIN (length, parent->length - offset);
 
142
 
 
143
  hb_mutex_lock (parent->lock);
 
144
  blob->mode = parent->mode;
 
145
  hb_mutex_unlock (parent->lock);
 
146
 
 
147
  blob->destroy = (hb_destroy_func_t) _hb_blob_unlock_and_destroy;
 
148
  blob->user_data = hb_blob_reference (parent);
 
149
 
 
150
  return blob;
 
151
}
 
152
 
 
153
hb_blob_t *
 
154
hb_blob_create_empty (void)
 
155
{
 
156
  return &_hb_blob_nil;
 
157
}
 
158
 
 
159
hb_blob_t *
 
160
hb_blob_reference (hb_blob_t *blob)
 
161
{
 
162
  HB_OBJECT_DO_REFERENCE (blob);
 
163
}
 
164
 
 
165
unsigned int
 
166
hb_blob_get_reference_count (hb_blob_t *blob)
 
167
{
 
168
  HB_OBJECT_DO_GET_REFERENCE_COUNT (blob);
 
169
}
 
170
 
 
171
void
 
172
hb_blob_destroy (hb_blob_t *blob)
 
173
{
 
174
  HB_OBJECT_DO_DESTROY (blob);
 
175
 
 
176
  _hb_blob_destroy_user_data (blob);
 
177
 
 
178
  free (blob);
 
179
}
 
180
 
 
181
unsigned int
 
182
hb_blob_get_length (hb_blob_t *blob)
 
183
{
 
184
  return blob->length;
 
185
}
 
186
 
 
187
const char *
 
188
hb_blob_lock (hb_blob_t *blob)
 
189
{
 
190
  if (HB_OBJECT_IS_INERT (blob))
 
191
    return NULL;
 
192
 
 
193
  hb_mutex_lock (blob->lock);
 
194
 
 
195
  blob->lock_count++;
 
196
#if HB_DEBUG_BLOB
 
197
  fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
 
198
           blob->lock_count, blob->data);
 
199
#endif
 
200
 
 
201
  hb_mutex_unlock (blob->lock);
 
202
 
 
203
  return blob->data;
 
204
}
 
205
 
 
206
void
 
207
hb_blob_unlock (hb_blob_t *blob)
 
208
{
 
209
  if (HB_OBJECT_IS_INERT (blob))
 
210
    return;
 
211
 
 
212
  hb_mutex_lock (blob->lock);
 
213
 
 
214
  assert (blob->lock_count > 0);
 
215
  blob->lock_count--;
 
216
#if HB_DEBUG_BLOB
 
217
  fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
 
218
           hb_atomic_int_get (blob->lock_count), blob->data);
 
219
#endif
 
220
 
 
221
  hb_mutex_unlock (blob->lock);
 
222
}
 
223
 
 
224
hb_bool_t
 
225
hb_blob_is_writable (hb_blob_t *blob)
 
226
{
 
227
  hb_memory_mode_t mode;
 
228
 
 
229
  if (HB_OBJECT_IS_INERT (blob))
 
230
    return FALSE;
 
231
 
 
232
  hb_mutex_lock (blob->lock);
 
233
 
 
234
  mode = blob->mode;
 
235
 
 
236
  hb_mutex_unlock (blob->lock);
 
237
 
 
238
  return mode == HB_MEMORY_MODE_WRITABLE;
 
239
}
 
240
 
 
241
 
 
242
static hb_bool_t
 
243
_try_make_writable_inplace_unix_locked (hb_blob_t *blob)
 
244
{
 
245
#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
 
246
  uintptr_t pagesize = -1, mask, length;
 
247
  const char *addr;
 
248
 
 
249
#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
 
250
  pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE);
 
251
#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
 
252
  pagesize = (uintptr_t) sysconf (_SC_PAGESIZE);
 
253
#elif defined(HAVE_GETPAGESIZE)
 
254
  pagesize = (uintptr_t) getpagesize ();
 
255
#endif
 
256
 
 
257
  if ((uintptr_t) -1L == pagesize) {
 
258
#if HB_DEBUG_BLOB
 
259
    fprintf (stderr, "%p %s: failed to get pagesize: %s\n", blob, __FUNCTION__, strerror (errno));
 
260
#endif
 
261
    return FALSE;
 
262
  }
 
263
#if HB_DEBUG_BLOB
 
264
  fprintf (stderr, "%p %s: pagesize is %u\n", blob, __FUNCTION__, pagesize);
 
265
#endif
 
266
 
 
267
  mask = ~(pagesize-1);
 
268
  addr = (const char *) (((uintptr_t) blob->data) & mask);
 
269
  length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask)  - addr;
 
270
#if HB_DEBUG_BLOB
 
271
  fprintf (stderr, "%p %s: calling mprotect on [%p..%p] (%d bytes)\n",
 
272
           blob, __FUNCTION__,
 
273
           addr, addr+length, length);
 
274
#endif
 
275
  if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) {
 
276
#if HB_DEBUG_BLOB
 
277
    fprintf (stderr, "%p %s: %s\n", blob, __FUNCTION__, strerror (errno));
 
278
#endif
 
279
    return FALSE;
 
280
  }
 
281
 
 
282
#if HB_DEBUG_BLOB
 
283
  fprintf (stderr, "%p %s: successfully made [%p..%p] (%d bytes) writable\n",
 
284
           blob, __FUNCTION__,
 
285
           addr, addr+length, length);
 
286
#endif
 
287
  return TRUE;
 
288
#else
 
289
  return FALSE;
 
290
#endif
 
291
}
 
292
 
 
293
static void
 
294
_try_writable_inplace_locked (hb_blob_t *blob)
 
295
{
 
296
#if HB_DEBUG_BLOB
 
297
  fprintf (stderr, "%p %s: making writable\n", blob, __FUNCTION__);
 
298
#endif
 
299
 
 
300
  if (_try_make_writable_inplace_unix_locked (blob)) {
 
301
#if HB_DEBUG_BLOB
 
302
    fprintf (stderr, "%p %s: making writable -> succeeded\n", blob, __FUNCTION__);
 
303
#endif
 
304
    blob->mode = HB_MEMORY_MODE_WRITABLE;
 
305
  } else {
 
306
#if HB_DEBUG_BLOB
 
307
    fprintf (stderr, "%p %s: making writable -> FAILED\n", blob, __FUNCTION__);
 
308
#endif
 
309
    /* Failed to make writable inplace, mark that */
 
310
    blob->mode = HB_MEMORY_MODE_READONLY;
 
311
  }
 
312
}
 
313
 
 
314
hb_bool_t
 
315
hb_blob_try_writable_inplace (hb_blob_t *blob)
 
316
{
 
317
  hb_memory_mode_t mode;
 
318
 
 
319
  if (HB_OBJECT_IS_INERT (blob))
 
320
    return FALSE;
 
321
 
 
322
  hb_mutex_lock (blob->lock);
 
323
 
 
324
  if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE)
 
325
    _try_writable_inplace_locked (blob);
 
326
 
 
327
  mode = blob->mode;
 
328
 
 
329
  hb_mutex_unlock (blob->lock);
 
330
 
 
331
  return mode == HB_MEMORY_MODE_WRITABLE;
 
332
}
 
333
 
 
334
hb_bool_t
 
335
hb_blob_try_writable (hb_blob_t *blob)
 
336
{
 
337
  hb_memory_mode_t mode;
 
338
 
 
339
  if (HB_OBJECT_IS_INERT (blob))
 
340
    return FALSE;
 
341
 
 
342
  hb_mutex_lock (blob->lock);
 
343
 
 
344
  if (blob->mode == HB_MEMORY_MODE_READONLY)
 
345
  {
 
346
    char *new_data;
 
347
 
 
348
#if HB_DEBUG_BLOB
 
349
    fprintf (stderr, "%p %s (%d) -> %p\n", blob, __FUNCTION__,
 
350
             blob->lock_count, blob->data);
 
351
#endif
 
352
 
 
353
    if (blob->lock_count)
 
354
      goto done;
 
355
 
 
356
    new_data = malloc (blob->length);
 
357
    if (new_data) {
 
358
#if HB_DEBUG_BLOB
 
359
      fprintf (stderr, "%p %s: dupped successfully -> %p\n", blob, __FUNCTION__, blob->data);
 
360
#endif
 
361
      memcpy (new_data, blob->data, blob->length);
 
362
      _hb_blob_destroy_user_data (blob);
 
363
      blob->mode = HB_MEMORY_MODE_WRITABLE;
 
364
      blob->data = new_data;
 
365
      blob->destroy = free;
 
366
      blob->user_data = new_data;
 
367
    }
 
368
  }
 
369
  else if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE)
 
370
    _try_writable_inplace_locked (blob);
 
371
 
 
372
done:
 
373
  mode = blob->mode;
 
374
 
 
375
  hb_mutex_unlock (blob->lock);
 
376
 
 
377
  return mode == HB_MEMORY_MODE_WRITABLE;
 
378
}