Coverage Report

Created: 2025-08-12 07:37

/src/imagemagick/MagickCore/registry.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%           RRRR    EEEEE    GGG   IIIII  SSSSS  TTTTT  RRRR   Y   Y          %
7
%           R   R   E       G        I    SS       T    R   R   Y Y           %
8
%           RRRR    EEE     G GGG    I     SSS     T    RRRR     Y            %
9
%           R R     E       G   G    I       SS    T    R R      Y            %
10
%           R  R    EEEEE    GGG   IIIII  SSSSS    T    R  R     Y            %
11
%                                                                             %
12
%                                                                             %
13
%                       MagickCore Registry Methods                           %
14
%                                                                             %
15
%                              Software Design                                %
16
%                                   Cristy                                    %
17
%                                 March 2000                                  %
18
%                                                                             %
19
%                                                                             %
20
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
21
%  dedicated to making software imaging solutions freely available.           %
22
%                                                                             %
23
%  You may not use this file except in compliance with the License.  You may  %
24
%  obtain a copy of the License at                                            %
25
%                                                                             %
26
%    https://imagemagick.org/script/license.php                               %
27
%                                                                             %
28
%  Unless required by applicable law or agreed to in writing, software        %
29
%  distributed under the License is distributed on an "AS IS" BASIS,          %
30
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31
%  See the License for the specific language governing permissions and        %
32
%  limitations under the License.                                             %
33
%                                                                             %
34
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
%
36
%
37
%
38
*/
39

40
/*
41
  Include declarations.
42
*/
43
#include "MagickCore/studio.h"
44
#include "MagickCore/exception.h"
45
#include "MagickCore/exception-private.h"
46
#include "MagickCore/image.h"
47
#include "MagickCore/list.h"
48
#include "MagickCore/memory_.h"
49
#include "MagickCore/memory-private.h"
50
#include "MagickCore/registry.h"
51
#include "MagickCore/registry-private.h"
52
#include "MagickCore/splay-tree.h"
53
#include "MagickCore/string_.h"
54
#include "MagickCore/string-private.h"
55
#include "MagickCore/timer-private.h"
56
#include "MagickCore/utility.h"
57

58
/*
59
  Typedef declarations.
60
*/
61
typedef struct _RegistryInfo
62
{
63
  RegistryType
64
    type;
65
66
  void
67
    *value;
68
69
  size_t
70
    signature;
71
} RegistryInfo;
72

73
/*
74
  Static declarations.
75
*/
76
static SplayTreeInfo
77
  *registry = (SplayTreeInfo *) NULL;
78
79
static SemaphoreInfo
80
  *registry_semaphore = (SemaphoreInfo *) NULL;
81

82
/*
83
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84
%                                                                             %
85
%                                                                             %
86
%                                                                             %
87
%   D e f i n e I m a g e R e g i s t r y                                     %
88
%                                                                             %
89
%                                                                             %
90
%                                                                             %
91
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
92
%
93
%  DefineImageRegistry() associates a key/value pair with the image registry.
94
%
95
%  The format of the DefineImageRegistry method is:
96
%
97
%      MagickBooleanType DefineImageRegistry(const RegistryType type,
98
%        const char *option,ExceptionInfo *exception)
99
%
100
%  A description of each parameter follows:
101
%
102
%    o type: the type.
103
%
104
%    o option: the option.
105
%
106
%    o exception: the exception.
107
%
108
*/
109
MagickExport MagickBooleanType DefineImageRegistry(const RegistryType type,
110
  const char *option,ExceptionInfo *exception)
111
0
{
112
0
  char
113
0
    key[MagickPathExtent],
114
0
    value[MagickPathExtent];
115
116
0
  char
117
0
    *p;
118
119
0
  assert(option != (const char *) NULL);
120
0
  (void) CopyMagickString(key,option,MagickPathExtent);
121
0
  for (p=key; *p != '\0'; p++)
122
0
    if (*p == '=')
123
0
      break;
124
0
  *value='\0';
125
0
  if (*p == '=')
126
0
    (void) CopyMagickString(value,p+1,MagickPathExtent);
127
0
  *p='\0';
128
0
  return(SetImageRegistry(type,key,value,exception));
129
0
}
130

131
/*
132
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133
%                                                                             %
134
%                                                                             %
135
%                                                                             %
136
%   D e l e t e I m a g e R e g i s t r y                                     %
137
%                                                                             %
138
%                                                                             %
139
%                                                                             %
140
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141
%
142
%  DeleteImageRegistry() deletes a key from the image registry.
143
%
144
%  The format of the DeleteImageRegistry method is:
145
%
146
%      MagickBooleanType DeleteImageRegistry(const char *key)
147
%
148
%  A description of each parameter follows:
149
%
150
%    o key: the registry.
151
%
152
*/
153
MagickExport MagickBooleanType DeleteImageRegistry(const char *key)
154
0
{
155
0
  assert(key != (const char *) NULL);
156
0
  if (IsEventLogging() != MagickFalse)
157
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
158
0
  if (registry == (void *) NULL)
159
0
    return(MagickFalse);
160
0
  return(DeleteNodeFromSplayTree(registry,key));
161
0
}
162

163
/*
164
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165
%                                                                             %
166
%                                                                             %
167
%                                                                             %
168
%   G e t I m a g e R e g i s t r y                                           %
169
%                                                                             %
170
%                                                                             %
171
%                                                                             %
172
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173
%
174
%  GetImageRegistry() returns a value associated with an image registry key.
175
%
176
%  The format of the GetImageRegistry method is:
177
%
178
%      void *GetImageRegistry(const RegistryType type,const char *key,
179
%        ExceptionInfo *exception)
180
%
181
%  A description of each parameter follows:
182
%
183
%    o type: the type.
184
%
185
%    o key: the key.
186
%
187
%    o exception: the exception.
188
%
189
*/
190
MagickExport void *GetImageRegistry(const RegistryType type,const char *key,
191
  ExceptionInfo *exception)
192
470k
{
193
470k
  void
194
470k
    *value;
195
196
470k
  RegistryInfo
197
470k
    *registry_info;
198
199
470k
  assert(key != (const char *) NULL);
200
470k
  if (IsEventLogging() != MagickFalse)
201
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
202
470k
  if (registry == (void *) NULL)
203
470k
    return((void *) NULL);
204
0
  registry_info=(RegistryInfo *) GetValueFromSplayTree(registry,key);
205
0
  if (registry_info == (void *) NULL)
206
0
    return((void *) NULL);
207
0
  value=(void *) NULL;
208
0
  switch (type)
209
0
  {
210
0
    case ImageRegistryType:
211
0
    {
212
0
      if (type == registry_info->type)
213
0
        value=(void *) CloneImageList((Image *) registry_info->value,exception);
214
0
      break;
215
0
    }
216
0
    case ImageInfoRegistryType:
217
0
    {
218
0
      if (type == registry_info->type)
219
0
        value=(void *) CloneImageInfo((ImageInfo *) registry_info->value);
220
0
      break;
221
0
    }
222
0
    case StringRegistryType:
223
0
    {
224
0
      switch (registry_info->type)
225
0
      {
226
0
        case ImageRegistryType:
227
0
        {
228
0
          value=(Image *) ConstantString(((Image *)
229
0
            registry_info->value)->filename);
230
0
          break;
231
0
        }
232
0
        case ImageInfoRegistryType:
233
0
        {
234
0
          value=(Image *) ConstantString(((ImageInfo *)
235
0
            registry_info->value)->filename);
236
0
          break;
237
0
        }
238
0
        case StringRegistryType:
239
0
        {
240
0
          value=(void *) ConstantString((char *) registry_info->value);
241
0
          break;
242
0
        }
243
0
        default:
244
0
          break;
245
0
      }
246
0
      break;
247
0
    }
248
0
    default:
249
0
      break;
250
0
  }
251
0
  return(value);
252
0
}
253

254
/*
255
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256
%                                                                             %
257
%                                                                             %
258
%                                                                             %
259
%   G e t N e x t I m a g e R e g i s t r y                                   %
260
%                                                                             %
261
%                                                                             %
262
%                                                                             %
263
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264
%
265
%  GetNextImageRegistry() gets the next image registry value.
266
%
267
%  The format of the GetNextImageRegistry method is:
268
%
269
%      char *GetNextImageRegistry(void)
270
%
271
*/
272
MagickExport char *GetNextImageRegistry(void)
273
0
{
274
0
  if (IsEventLogging() != MagickFalse)
275
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
276
0
  if (registry == (void *) NULL)
277
0
    return((char *) NULL);
278
0
  return((char *) GetNextKeyInSplayTree(registry));
279
0
}
280

281
/*
282
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
283
%                                                                             %
284
%                                                                             %
285
%                                                                             %
286
+   R e g i s t r y C o m p o n e n t G e n e s i s                           %
287
%                                                                             %
288
%                                                                             %
289
%                                                                             %
290
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291
%
292
%  RegistryComponentGenesis() instantiates the registry component.
293
%
294
%  The format of the RegistryComponentGenesis method is:
295
%
296
%      MagickBooleanType RegistryComponentGenesis(void)
297
%
298
*/
299
MagickPrivate MagickBooleanType RegistryComponentGenesis(void)
300
294
{
301
294
  if (registry_semaphore == (SemaphoreInfo *) NULL)
302
294
    registry_semaphore=AcquireSemaphoreInfo();
303
294
  return(MagickTrue);
304
294
}
305

306
/*
307
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308
%                                                                             %
309
%                                                                             %
310
%                                                                             %
311
%   R e g i s t r y C o m p o n e n t T e r m i n u s                         %
312
%                                                                             %
313
%                                                                             %
314
%                                                                             %
315
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316
%
317
%  RegistryComponentTerminus() destroys the registry component.
318
%
319
%  The format of the DestroyDefines method is:
320
%
321
%      void RegistryComponentTerminus(void)
322
%
323
*/
324
MagickPrivate void RegistryComponentTerminus(void)
325
0
{
326
0
  if (registry_semaphore == (SemaphoreInfo *) NULL)
327
0
    ActivateSemaphoreInfo(&registry_semaphore);
328
0
  LockSemaphoreInfo(registry_semaphore);
329
0
  if (IsEventLogging() != MagickFalse)
330
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
331
0
  if (registry != (void *) NULL)
332
0
    registry=DestroySplayTree(registry);
333
0
  UnlockSemaphoreInfo(registry_semaphore);
334
0
  RelinquishSemaphoreInfo(&registry_semaphore);
335
0
}
336

337
/*
338
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339
%                                                                             %
340
%                                                                             %
341
%                                                                             %
342
%   R e m o v e I m a g e R e g i s t r y                                     %
343
%                                                                             %
344
%                                                                             %
345
%                                                                             %
346
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347
%
348
%  RemoveImageRegistry() removes a key from the image registry and returns its
349
%  value.
350
%
351
%  The format of the RemoveImageRegistry method is:
352
%
353
%      void *RemoveImageRegistry(const char *key)
354
%
355
%  A description of each parameter follows:
356
%
357
%    o key: the registry.
358
%
359
*/
360
MagickExport void *RemoveImageRegistry(const char *key)
361
0
{
362
0
  assert(key != (const char *) NULL);
363
0
  if (IsEventLogging() != MagickFalse)
364
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
365
0
  if (registry == (void *) NULL)
366
0
    return((void *) NULL);
367
0
  return(RemoveNodeFromSplayTree(registry,key));
368
0
}
369

370
/*
371
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372
%                                                                             %
373
%                                                                             %
374
%                                                                             %
375
%   R e s e t I m a g e R e g i s t r y I t e r a t o r                       %
376
%                                                                             %
377
%                                                                             %
378
%                                                                             %
379
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
380
%
381
%  ResetImageRegistryIterator() resets the registry iterator.  Use it in
382
%  conjunction with GetNextImageRegistry() to iterate over all the values
383
%  in the image registry.
384
%
385
%  The format of the ResetImageRegistryIterator method is:
386
%
387
%      ResetImageRegistryIterator(void)
388
%
389
*/
390
MagickExport void ResetImageRegistryIterator(void)
391
0
{
392
0
  if (IsEventLogging() != MagickFalse)
393
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
394
0
  if (registry == (void *) NULL)
395
0
    return;
396
0
  ResetSplayTreeIterator(registry);
397
0
}
398

399
/*
400
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401
%                                                                             %
402
%                                                                             %
403
%                                                                             %
404
%   S e t I m a g e R e g i s t r y                                           %
405
%                                                                             %
406
%                                                                             %
407
%                                                                             %
408
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409
%
410
%  SetImageRegistry() associates a value with an image registry key.
411
%
412
%  The format of the SetImageRegistry method is:
413
%
414
%      MagickBooleanType SetImageRegistry(const RegistryType type,
415
%        const char *key,const void *value,ExceptionInfo *exception)
416
%
417
%  A description of each parameter follows:
418
%
419
%    o type: the type.
420
%
421
%    o key: the key.
422
%
423
%    o value: the value.
424
%
425
%    o exception: the exception.
426
%
427
*/
428
429
static void *DestroyRegistryNode(void *registry_info)
430
0
{
431
0
  RegistryInfo
432
0
    *p;
433
434
0
  p=(RegistryInfo *) registry_info;
435
0
  switch (p->type)
436
0
  {
437
0
    case StringRegistryType:
438
0
    default:
439
0
    {
440
0
      p->value=RelinquishMagickMemory(p->value);
441
0
      break;
442
0
    }
443
0
    case ImageRegistryType:
444
0
    {
445
0
      p->value=(void *) DestroyImageList((Image *) p->value);
446
0
      break;
447
0
    }
448
0
    case ImageInfoRegistryType:
449
0
    {
450
0
      p->value=(void *) DestroyImageInfo((ImageInfo *) p->value);
451
0
      break;
452
0
    }
453
0
  }
454
0
  return(RelinquishMagickMemory(p));
455
0
}
456
457
MagickExport MagickBooleanType SetImageRegistry(const RegistryType type,
458
  const char *key,const void *value,ExceptionInfo *exception)
459
0
{
460
0
  RegistryInfo
461
0
    *registry_info;
462
463
0
  void
464
0
    *clone_value;
465
466
0
  assert(key != (const char *) NULL);
467
0
  if (IsEventLogging() != MagickFalse)
468
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",key);
469
0
  if (value == (const void *) NULL)
470
0
    return(MagickFalse);
471
0
  clone_value=(void *) NULL;
472
0
  switch (type)
473
0
  {
474
0
    case StringRegistryType:
475
0
    default:
476
0
    {
477
0
      const char
478
0
        *string;
479
480
0
      string=(const char *) value;
481
0
      if (LocaleCompare(key,"date:precision") == 0)
482
0
        SetMagickDatePrecision((size_t) StringToInteger(string));
483
0
      clone_value=(void *) ConstantString(string);
484
0
      break;
485
0
    }
486
0
    case ImageRegistryType:
487
0
    {
488
0
      const Image
489
0
        *image;
490
491
0
      image=(const Image *) value;
492
0
      if ((image == (const Image *) NULL) ||
493
0
          (image->signature != MagickCoreSignature))
494
0
        {
495
0
          (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
496
0
            "UnableToSetRegistry","%s",key);
497
0
          return(MagickFalse);
498
0
        }
499
0
      clone_value=(void *) CloneImageList(image,exception);
500
0
      break;
501
0
    }
502
0
    case ImageInfoRegistryType:
503
0
    {
504
0
      const ImageInfo
505
0
        *image_info;
506
507
0
      image_info=(const ImageInfo *) value;
508
0
      if ((image_info == (const ImageInfo *) NULL) ||
509
0
          (image_info->signature != MagickCoreSignature))
510
0
        {
511
0
          (void) ThrowMagickException(exception,GetMagickModule(),RegistryError,
512
0
            "UnableToSetRegistry","%s",key);
513
0
          return(MagickFalse);
514
0
        }
515
0
      clone_value=(void *) CloneImageInfo(image_info);
516
0
      break;
517
0
    }
518
0
  }
519
0
  if (clone_value == (void *) NULL)
520
0
    return(MagickFalse);
521
0
  registry_info=(RegistryInfo *) AcquireCriticalMemory(sizeof(*registry_info));
522
0
  (void) memset(registry_info,0,sizeof(*registry_info));
523
0
  registry_info->type=type;
524
0
  registry_info->value=clone_value;
525
0
  registry_info->signature=MagickCoreSignature;
526
0
  if (registry == (SplayTreeInfo *) NULL)
527
0
    {
528
0
      if (registry_semaphore == (SemaphoreInfo *) NULL)
529
0
        ActivateSemaphoreInfo(&registry_semaphore);
530
0
      LockSemaphoreInfo(registry_semaphore);
531
0
      if (registry == (SplayTreeInfo *) NULL)
532
0
        registry=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory,
533
0
          DestroyRegistryNode);
534
0
      UnlockSemaphoreInfo(registry_semaphore);
535
0
    }
536
0
  return(AddValueToSplayTree(registry,ConstantString(key),registry_info));
537
0
}