Coverage Report

Created: 2026-09-28 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/inline.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                  IIIII  N   N  L      IIIII  N   N  EEEEE                   %
7
%                    I    NN  N  L        I    NN  N  E                       %
8
%                    I    N N N  L        I    N N N  EEE                     %
9
%                    I    N  NN  L        I    N  NN  E                       %
10
%                  IIIII  N   N  LLLLL  IIIII  N   N  EEEEE                   %
11
%                                                                             %
12
%                                                                             %
13
%                            Read Inline Images                               %
14
%                                                                             %
15
%                              Software Design                                %
16
%                                   Cristy                                    %
17
%                                 July 1992                                   %
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/license/                                         %
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
  Include declarations.
41
*/
42
#include "MagickCore/studio.h"
43
#include "MagickCore/blob.h"
44
#include "MagickCore/blob-private.h"
45
#include "MagickCore/client.h"
46
#include "MagickCore/constitute.h"
47
#include "MagickCore/display.h"
48
#include "MagickCore/exception.h"
49
#include "MagickCore/exception-private.h"
50
#include "MagickCore/image.h"
51
#include "MagickCore/image-private.h"
52
#include "MagickCore/list.h"
53
#include "MagickCore/magick.h"
54
#include "MagickCore/memory_.h"
55
#include "MagickCore/option.h"
56
#include "MagickCore/quantum-private.h"
57
#include "MagickCore/static.h"
58
#include "MagickCore/string_.h"
59
#include "MagickCore/module.h"
60
#include "MagickCore/utility.h"
61
#include "MagickCore/xwindow.h"
62
#include "MagickCore/xwindow-private.h"
63

64
/*
65
  Forward declarations.
66
*/
67
static MagickBooleanType
68
  WriteINLINEImage(const ImageInfo *,Image *,ExceptionInfo *);
69

70
/*
71
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72
%                                                                             %
73
%                                                                             %
74
%                                                                             %
75
%   R e a d I N L I N E I m a g e                                             %
76
%                                                                             %
77
%                                                                             %
78
%                                                                             %
79
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80
%
81
%  ReadINLINEImage() reads base64-encoded inlines images.
82
%
83
%  The format of the ReadINLINEImage method is:
84
%
85
%      Image *ReadINLINEImage(const ImageInfo *image_info,
86
%        ExceptionInfo *exception)
87
%
88
%  A description of each parameter follows:
89
%
90
%    o image_info: the image info.
91
%
92
%    o exception: return any errors or warnings in this structure.
93
%
94
*/
95
static Image *ReadINLINEImage(const ImageInfo *image_info,
96
  ExceptionInfo *exception)
97
9.89k
{
98
9.89k
  Image
99
9.89k
    *image;
100
101
9.89k
  MagickBooleanType
102
9.89k
    status;
103
104
9.89k
  size_t
105
9.89k
    quantum;
106
107
9.89k
  ssize_t
108
9.89k
    count,
109
9.89k
    i;
110
111
9.89k
  unsigned char
112
9.89k
    *inline_image;
113
114
  /*
115
    Open image file.
116
  */
117
9.89k
  assert(image_info != (const ImageInfo *) NULL);
118
9.89k
  assert(image_info->signature == MagickCoreSignature);
119
9.89k
  assert(exception != (ExceptionInfo *) NULL);
120
9.89k
  assert(exception->signature == MagickCoreSignature);
121
9.89k
  if (IsEventLogging() != MagickFalse)
122
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
123
0
      image_info->filename);
124
9.89k
  if (LocaleNCompare(image_info->filename,"data:",5) == 0)
125
0
    {
126
0
      char
127
0
        *filename;
128
129
0
      Image
130
0
        *data_image;
131
132
0
      filename=AcquireString("data:");
133
0
      (void) ConcatenateMagickString(filename,image_info->filename,
134
0
        MagickPathExtent);
135
0
      data_image=ReadInlineImage(image_info,filename,exception);
136
0
      filename=DestroyString(filename);
137
0
      return(data_image);
138
0
    }
139
9.89k
  image=AcquireImage(image_info,exception);
140
9.89k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
141
9.89k
  if (status == MagickFalse)
142
608
    {
143
608
      image=DestroyImageList(image);
144
608
      return((Image *) NULL);
145
608
    }
146
9.29k
  quantum=MagickMin((size_t) GetBlobSize(image),MagickMaxBufferExtent);
147
9.29k
  if (quantum == 0)
148
608
    quantum=MagickMaxBufferExtent;
149
9.29k
  inline_image=(unsigned char *) AcquireQuantumMemory(quantum,
150
9.29k
    sizeof(*inline_image));
151
9.29k
  count=0;
152
17.9k
  for (i=0; inline_image != (unsigned char *) NULL; i+=count)
153
17.9k
  {
154
17.9k
    count=(ssize_t) ReadBlob(image,quantum,inline_image+i);
155
17.9k
    if (count <= 0)
156
9.29k
      {
157
9.29k
        count=0;
158
9.29k
        if (errno != EINTR)
159
9.29k
          break;
160
9.29k
      }
161
8.68k
    if (~((size_t) i) < (quantum+1))
162
0
      {
163
0
        inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
164
0
        break;
165
0
      }
166
8.68k
    inline_image=(unsigned char *) ResizeQuantumMemory(inline_image,(size_t)
167
8.68k
      (i+count+(ssize_t) quantum+1),sizeof(*inline_image));
168
8.68k
  }
169
9.29k
  if (inline_image == (unsigned char *) NULL)
170
0
    {
171
0
      (void) ThrowMagickException(exception,GetMagickModule(),
172
0
        ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename);
173
0
      return((Image *) NULL);
174
0
    }
175
9.29k
  inline_image[i+count]='\0';
176
9.29k
  image=DestroyImageList(image);
177
9.29k
  image=ReadInlineImage(image_info,(char *) inline_image,exception);
178
9.29k
  inline_image=(unsigned char *) RelinquishMagickMemory(inline_image);
179
9.29k
  return(image);
180
9.29k
}
181

182
/*
183
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
184
%                                                                             %
185
%                                                                             %
186
%                                                                             %
187
%   R e g i s t e r I N L I N E I m a g e                                     %
188
%                                                                             %
189
%                                                                             %
190
%                                                                             %
191
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192
%
193
%  RegisterINLINEImage() adds attributes for the INLINE image format to
194
%  the list of supported formats.  The attributes include the image format
195
%  tag, a method to read and/or write the format, whether the format
196
%  supports the saving of more than one frame to the same file or blob,
197
%  whether the format supports native in-memory I/O, and a brief
198
%  description of the format.
199
%
200
%  The format of the RegisterINLINEImage method is:
201
%
202
%      size_t RegisterINLINEImage(void)
203
%
204
*/
205
ModuleExport size_t RegisterINLINEImage(void)
206
8
{
207
8
  MagickInfo
208
8
    *entry;
209
210
8
  entry=AcquireMagickInfo("INLINE","DATA","Base64-encoded inline images");
211
8
  entry->decoder=(DecodeImageHandler *) ReadINLINEImage;
212
8
  entry->encoder=(EncodeImageHandler *) WriteINLINEImage;
213
8
  entry->format_type=ImplicitFormatType;
214
8
  entry->flags|=CoderExplicitAllowedFlag;
215
8
  (void) RegisterMagickInfo(entry);
216
8
  entry=AcquireMagickInfo("INLINE","INLINE","Base64-encoded inline images");
217
8
  entry->decoder=(DecodeImageHandler *) ReadINLINEImage;
218
8
  entry->encoder=(EncodeImageHandler *) WriteINLINEImage;
219
8
  entry->format_type=ImplicitFormatType;
220
8
  entry->flags|=CoderExplicitAllowedFlag;
221
8
  (void) RegisterMagickInfo(entry);
222
8
  return(MagickImageCoderSignature);
223
8
}
224

225
/*
226
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227
%                                                                             %
228
%                                                                             %
229
%                                                                             %
230
%   U n r e g i s t e r I N L I N E I m a g e                                 %
231
%                                                                             %
232
%                                                                             %
233
%                                                                             %
234
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235
%
236
%  UnregisterINLINEImage() removes format registrations made by the
237
%  INLINE module from the list of supported formats.
238
%
239
%  The format of the UnregisterINLINEImage method is:
240
%
241
%      UnregisterINLINEImage(void)
242
%
243
*/
244
ModuleExport void UnregisterINLINEImage(void)
245
0
{
246
0
  (void) UnregisterMagickInfo("INLINE");
247
0
  (void) UnregisterMagickInfo("DATA");
248
0
}
249

250
/*
251
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252
%                                                                             %
253
%                                                                             %
254
%                                                                             %
255
%   W r i t e I N L I N E I m a g e                                           %
256
%                                                                             %
257
%                                                                             %
258
%                                                                             %
259
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260
%
261
%  WriteINLINEImage() writes an image to a file in INLINE format (Base64).
262
%
263
%  The format of the WriteINLINEImage method is:
264
%
265
%      MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
266
%        Image *image,ExceptionInfo *exception)
267
%
268
%  A description of each parameter follows.
269
%
270
%    o image_info: the image info.
271
%
272
%    o image:  The image.
273
%
274
%    o exception: return any errors or warnings in this structure.
275
%
276
*/
277
static MagickBooleanType WriteINLINEImage(const ImageInfo *image_info,
278
  Image *image,ExceptionInfo *exception)
279
583
{
280
583
  char
281
583
    *base64,
282
583
    message[MagickPathExtent];
283
284
583
  const MagickInfo
285
583
    *magick_info;
286
287
583
  Image
288
583
    *write_image;
289
290
583
  ImageInfo
291
583
    *write_info;
292
293
583
  MagickBooleanType
294
583
    status;
295
296
583
  size_t
297
583
    blob_length,
298
583
    encode_length;
299
300
583
  unsigned char
301
583
    *blob;
302
303
  /*
304
    Convert image to base64-encoding.
305
  */
306
583
  assert(image_info != (const ImageInfo *) NULL);
307
583
  assert(image_info->signature == MagickCoreSignature);
308
583
  assert(image != (Image *) NULL);
309
583
  assert(image->signature == MagickCoreSignature);
310
583
  if (IsEventLogging() != MagickFalse)
311
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
312
583
  write_info=CloneImageInfo(image_info);
313
583
  (void) SetImageInfo(write_info,1,exception);
314
583
  if (LocaleCompare(write_info->magick,"INLINE") == 0)
315
583
    (void) CopyMagickString(write_info->magick,image->magick,MagickPathExtent);
316
583
  magick_info=GetMagickInfo(write_info->magick,exception);
317
583
  if ((magick_info == (const MagickInfo *) NULL) ||
318
583
      (GetMagickMimeType(magick_info) == (const char *) NULL))
319
583
    {
320
583
      write_info=DestroyImageInfo(write_info);
321
583
      ThrowWriterException(ImageError,"ImageTypeNotSupported");
322
0
    }
323
0
  (void) CopyMagickString(image->filename,write_info->filename,
324
0
    MagickPathExtent);
325
0
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
326
0
  if (status == MagickFalse)
327
0
    {
328
0
      write_info=DestroyImageInfo(write_info);
329
0
      return(status);
330
0
    }
331
0
  blob_length=2048;
332
0
  write_image=CloneImage(image,0,0,MagickTrue,exception);
333
0
  if (write_image == (Image *) NULL)
334
0
    {
335
0
      write_info=DestroyImageInfo(write_info);
336
0
      (void) CloseBlob(image);
337
0
      return(MagickTrue);
338
0
    }
339
0
  blob=(unsigned char *) ImageToBlob(write_info,write_image,&blob_length,
340
0
    exception);
341
0
  write_image=DestroyImage(write_image);
342
0
  write_info=DestroyImageInfo(write_info);
343
0
  if (blob == (unsigned char *) NULL)
344
0
    return(MagickFalse);
345
0
  encode_length=0;
346
0
  base64=Base64Encode(blob,blob_length,&encode_length);
347
0
  blob=(unsigned char *) RelinquishMagickMemory(blob);
348
0
  if (base64 == (char *) NULL)
349
0
    ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
350
  /*
351
    Write base64-encoded image.
352
  */
353
0
  (void) FormatLocaleString(message,MagickPathExtent,"data:%s;base64,",
354
0
    GetMagickMimeType(magick_info));
355
0
  (void) WriteBlobString(image,message);
356
0
  (void) WriteBlobString(image,base64);
357
0
  base64=DestroyString(base64);
358
0
  if (CloseBlob(image) == MagickFalse)
359
0
    status=MagickFalse;
360
0
  return(status);
361
0
}