Coverage Report

Created: 2026-11-12 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/source/pdf/pdf-store.c
Line
Count
Source
1
// Copyright (C) 2004-2021 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
#include "mupdf/pdf.h"
25
26
#include <assert.h>
27
28
static int
29
pdf_make_hash_key(fz_context *ctx, fz_store_hash *hash, void *key_)
30
79.8k
{
31
79.8k
  pdf_obj *key = (pdf_obj *)key_;
32
33
79.8k
  if (!pdf_is_indirect(ctx, key))
34
12
    return 0;
35
79.8k
  hash->u.pi.i = pdf_to_num(ctx, key);
36
79.8k
  hash->u.pi.ptr = pdf_get_indirect_document(ctx, key);
37
79.8k
  return 1;
38
79.8k
}
39
40
static void *
41
pdf_keep_key(fz_context *ctx, void *key)
42
7.12k
{
43
7.12k
  return (void *)pdf_keep_obj(ctx, (pdf_obj *)key);
44
7.12k
}
45
46
static void
47
pdf_drop_key(fz_context *ctx, void *key)
48
7.12k
{
49
7.12k
  pdf_drop_obj(ctx, (pdf_obj *)key);
50
7.12k
}
51
52
static int
53
pdf_cmp_key(fz_context *ctx, void *k0, void *k1)
54
0
{
55
0
  pdf_obj *a = (pdf_obj *)k0;
56
0
  pdf_obj *b = (pdf_obj *)k1;
57
0
  pdf_document *adoc = pdf_get_bound_document(ctx, a);
58
0
  pdf_document *bdoc = pdf_get_bound_document(ctx, b);
59
60
  /* Avoid sharing complex objects across documents. */
61
0
  if (adoc && bdoc && adoc != bdoc)
62
0
    return 1;
63
64
0
  return pdf_objcmp(ctx, a, b);
65
0
}
66
67
static void
68
pdf_format_key(fz_context *ctx, char *s, size_t n, void *key_)
69
0
{
70
0
  pdf_obj *key = (pdf_obj *)key_;
71
0
  if (pdf_is_indirect(ctx, key))
72
0
    fz_snprintf(s, n, "(%d 0 R)", pdf_to_num(ctx, key));
73
0
  else
74
0
  {
75
0
    size_t t;
76
0
    char *p = pdf_sprint_obj(ctx, s, n, &t, key, 1, 0);
77
0
    if (p != s) {
78
0
      fz_strlcpy(s, p, n);
79
0
      fz_free(ctx, p);
80
0
    }
81
0
  }
82
0
}
83
84
static const fz_store_type pdf_obj_store_type =
85
{
86
  "pdf_obj",
87
  pdf_make_hash_key,
88
  pdf_keep_key,
89
  pdf_drop_key,
90
  pdf_cmp_key,
91
  pdf_format_key,
92
  NULL
93
};
94
95
void
96
pdf_store_item(fz_context *ctx, pdf_obj *key, void *val, size_t itemsize)
97
7.12k
{
98
7.12k
  void *existing;
99
100
7.12k
  assert(pdf_is_name(ctx, key) || pdf_is_array(ctx, key) || pdf_is_dict(ctx, key) || pdf_is_indirect(ctx, key));
101
7.12k
  existing = fz_store_item(ctx, key, val, itemsize, &pdf_obj_store_type);
102
7.12k
  if (existing)
103
0
    fz_warn(ctx, "unexpectedly replacing entry in PDF store");
104
7.12k
}
105
106
void *
107
pdf_find_item(fz_context *ctx, fz_store_drop_fn *drop, pdf_obj *key)
108
65.6k
{
109
65.6k
  return fz_find_item(ctx, drop, key, &pdf_obj_store_type);
110
65.6k
}
111
112
void
113
pdf_remove_item(fz_context *ctx, fz_store_drop_fn *drop, pdf_obj *key)
114
0
{
115
0
  fz_remove_item(ctx, drop, key, &pdf_obj_store_type);
116
0
}
117
118
static int
119
pdf_filter_store(fz_context *ctx, void *doc_, void *key)
120
7.12k
{
121
7.12k
  pdf_document *doc = (pdf_document *)doc_;
122
7.12k
  pdf_obj *obj = (pdf_obj *)key;
123
7.12k
  pdf_document *key_doc = pdf_get_bound_document(ctx, obj);
124
125
7.12k
  return (doc == key_doc);
126
7.12k
}
127
128
void
129
pdf_empty_store(fz_context *ctx, pdf_document *doc)
130
86
{
131
86
  fz_filter_store(ctx, pdf_filter_store, doc, &pdf_obj_store_type);
132
86
  fz_drop_drawn_tiles_for_document(ctx, (fz_document *)doc);
133
86
}
134
135
static int
136
pdf_filter_locals(fz_context *ctx, void *doc_, void *key)
137
0
{
138
0
  pdf_document *doc = (pdf_document *)doc_;
139
0
  pdf_obj *obj = (pdf_obj *)key;
140
0
  pdf_document *key_doc = pdf_get_bound_document(ctx, obj);
141
142
0
  return (doc == key_doc && pdf_is_local_object(ctx, doc, obj));
143
0
}
144
145
void pdf_purge_locals_from_store(fz_context *ctx, pdf_document *doc)
146
68
{
147
68
  fz_filter_store(ctx, pdf_filter_locals, doc, &pdf_obj_store_type);
148
68
}
149
150
struct doc_num_info {
151
  pdf_document *doc;
152
  int num;
153
};
154
155
static int
156
pdf_filter_object_number(fz_context *ctx, void *ref_, void *key_)
157
0
{
158
0
  struct doc_num_info *ref = ref_;
159
0
  pdf_obj *key_obj = (pdf_obj *)key_;
160
0
  pdf_document *key_doc = pdf_get_bound_document(ctx, key_obj);
161
0
  return (ref->doc == key_doc && ref->num == pdf_to_num(ctx, key_obj));
162
0
}
163
164
void pdf_purge_object_from_store(fz_context *ctx, pdf_document *doc, int num)
165
0
{
166
0
  struct doc_num_info ref = { doc, num };
167
0
  fz_filter_store(ctx, pdf_filter_object_number, &ref, &pdf_obj_store_type);
168
0
}