Coverage Report

Created: 2026-07-13 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libtiff/libtiff/tif_write.c
Line
Count
Source
1
/*
2
 * Copyright (c) 1988-1997 Sam Leffler
3
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4
 *
5
 * Permission to use, copy, modify, distribute, and sell this software and
6
 * its documentation for any purpose is hereby granted without fee, provided
7
 * that (i) the above copyright notices and this permission notice appear in
8
 * all copies of the software and related documentation, and (ii) the names of
9
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
10
 * publicity relating to the software without the specific, prior written
11
 * permission of Sam Leffler and Silicon Graphics.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16
 *
17
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22
 * OF THIS SOFTWARE.
23
 */
24
25
/*
26
 * TIFF Library.
27
 *
28
 * Scanline-oriented Write Support
29
 */
30
#include "tiffiop.h"
31
#include <assert.h>
32
#include <stdio.h>
33
34
591
#define NOSTRIP ((uint32_t)(-1)) /* undefined state */
35
36
#define WRITECHECKSTRIPS(tif, module)                                          \
37
201
    (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 0, module))
38
#define WRITECHECKTILES(tif, module)                                           \
39
0
    (((tif)->tif_flags & TIFF_BEENWRITING) || TIFFWriteCheck((tif), 1, module))
40
#define BUFFERCHECK(tif)                                                       \
41
197
    ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) ||            \
42
197
     TIFFWriteBufferSetup((tif), NULL, (tmsize_t)(-1)))
43
44
static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module);
45
static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
46
                             tmsize_t cc);
47
48
int TIFFWriteScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample)
49
0
{
50
0
    static const char module[] = "TIFFWriteScanline";
51
0
    TIFFDirectory *td;
52
0
    int status, imagegrew = 0;
53
0
    uint32_t strip;
54
55
0
    if (!WRITECHECKSTRIPS(tif, module))
56
0
        return (-1);
57
    /*
58
     * Handle delayed allocation of data buffer.  This
59
     * permits it to be sized more intelligently (using
60
     * directory information).
61
     */
62
0
    if (!BUFFERCHECK(tif))
63
0
        return (-1);
64
0
    tif->tif_flags |= TIFF_BUF4WRITE; /* not strictly sure this is right*/
65
66
0
    td = &tif->tif_dir;
67
    /*
68
     * Extend image length if needed
69
     * (but only for PlanarConfig=1).
70
     */
71
0
    if (row >= td->td_imagelength)
72
0
    { /* extend image */
73
0
        if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
74
0
        {
75
0
            TIFFErrorExtR(
76
0
                tif, module,
77
0
                "Can not change \"ImageLength\" when using separate planes");
78
0
            return (-1);
79
0
        }
80
0
        td->td_imagelength = row + 1;
81
0
        imagegrew = 1;
82
0
    }
83
    /*
84
     * Calculate strip and check for crossings.
85
     */
86
0
    if (td->td_rowsperstrip == 0)
87
0
    {
88
0
        TIFFErrorExtR(tif, module,
89
0
                      "Cannot compute strip: RowsPerStrip is zero");
90
0
        return (-1);
91
0
    }
92
0
    if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
93
0
    {
94
0
        uint64_t sample_offset;
95
0
        uint64_t strip64;
96
0
        if (sample >= td->td_samplesperpixel)
97
0
        {
98
0
            TIFFErrorExtR(tif, module, "%lu: Sample out of range, max %lu",
99
0
                          (unsigned long)sample,
100
0
                          (unsigned long)td->td_samplesperpixel);
101
0
            return (-1);
102
0
        }
103
0
        sample_offset =
104
0
            _TIFFMultiply64(tif, sample, td->td_stripsperimage, module);
105
0
        if (sample_offset == 0 && sample != 0 && td->td_stripsperimage != 0)
106
0
            return (-1);
107
0
        strip64 =
108
0
            _TIFFAdd64(tif, sample_offset, row / td->td_rowsperstrip, module);
109
0
        if (strip64 == 0 &&
110
0
            (sample_offset != 0 || (row / td->td_rowsperstrip) != 0))
111
0
            return (-1);
112
0
        strip = _TIFFCastUInt64ToUInt32(tif, strip64, module);
113
0
        if (strip == 0 && strip64 != 0)
114
0
            return (-1);
115
0
    }
116
0
    else
117
0
        strip = row / td->td_rowsperstrip;
118
    /*
119
     * Check strip array to make sure there's space. We don't support
120
     * dynamically growing files that have data organized in separate
121
     * bitplanes because it's too painful.  In that case we require that
122
     * the imagelength be set properly before the first write (so that the
123
     * strips array will be fully allocated above).
124
     */
125
0
    if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
126
0
        return (-1);
127
0
    if (strip != tif->tif_dir.td_curstrip)
128
0
    {
129
        /*
130
         * Changing strips -- flush any data present.
131
         */
132
0
        if (!TIFFFlushData(tif))
133
0
            return (-1);
134
0
        tif->tif_dir.td_curstrip = strip;
135
        /*
136
         * Watch out for a growing image.  The value of strips/image
137
         * will initially be 1 (since it can't be deduced until the
138
         * imagelength is known).
139
         */
140
0
        if (strip >= td->td_stripsperimage && imagegrew)
141
0
            td->td_stripsperimage =
142
0
                TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
143
0
        if (td->td_stripsperimage == 0)
144
0
        {
145
0
            TIFFErrorExtR(tif, module, "Zero strips per image");
146
0
            return (-1);
147
0
        }
148
0
        tif->tif_dir.td_row =
149
0
            (strip % td->td_stripsperimage) * td->td_rowsperstrip;
150
0
        if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
151
0
        {
152
0
            if (!(*tif->tif_setupencode)(tif))
153
0
                return (-1);
154
0
            tif->tif_flags |= TIFF_CODERSETUP;
155
0
        }
156
157
0
        tif->tif_rawcc = 0;
158
0
        tif->tif_rawcp = tif->tif_rawdata;
159
160
        /* this informs TIFFAppendToStrip() we have changed strip */
161
0
        tif->tif_curoff = 0;
162
163
0
        if (!(*tif->tif_preencode)(tif, sample))
164
0
            return (-1);
165
0
        tif->tif_flags |= TIFF_POSTENCODE;
166
0
    }
167
    /*
168
     * Ensure the write is either sequential or at the
169
     * beginning of a strip (or that we can randomly
170
     * access the data -- i.e. no encoding).
171
     */
172
0
    if (row != tif->tif_dir.td_row)
173
0
    {
174
0
        if (row < tif->tif_dir.td_row)
175
0
        {
176
            /*
177
             * Moving backwards within the same strip:
178
             * backup to the start and then decode
179
             * forward (below).
180
             */
181
            /* Coverity Scan warns about a potential division by zero given
182
             * an above check against zero, but I believe this is a false
183
             * positive.
184
             */
185
0
            assert(td->td_stripsperimage != 0);
186
0
            tif->tif_dir.td_row =
187
0
                (strip % td->td_stripsperimage) * td->td_rowsperstrip;
188
0
            tif->tif_rawcp = tif->tif_rawdata;
189
0
        }
190
        /*
191
         * Seek forward to the desired row.
192
         */
193
0
        if (!(*tif->tif_seek)(tif, row - tif->tif_dir.td_row))
194
0
            return (-1);
195
0
        tif->tif_dir.td_row = row;
196
0
    }
197
198
    /* swab if needed - note that source buffer will be altered */
199
0
    tif->tif_postdecode(tif, (uint8_t *)buf, tif->tif_dir.td_scanlinesize);
200
201
0
    status = (*tif->tif_encoderow)(tif, (uint8_t *)buf,
202
0
                                   tif->tif_dir.td_scanlinesize, sample);
203
204
    /* we are now poised at the beginning of the next row */
205
0
    tif->tif_dir.td_row = row + 1;
206
0
    return (status);
207
0
}
208
209
/* Make sure that at the first attempt of rewriting a tile/strip, we will have
210
 */
211
/* more bytes available in the output buffer than the previous byte count, */
212
/* so that TIFFAppendToStrip() will detect the overflow when it is called the
213
 * first */
214
/* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
215
static int _TIFFReserveLargeEnoughWriteBuffer(TIFF *tif, uint32_t strip_or_tile)
216
197
{
217
197
    static const char module[] = "_TIFFReserveLargeEnoughWriteBuffer";
218
197
    TIFFDirectory *td = &tif->tif_dir;
219
220
197
    if (td->td_stripbytecount_p == NULL)
221
0
    {
222
0
        TIFFErrorExtR(tif, module, "Strip bytecount array pointer is NULL");
223
0
        return 0;
224
0
    }
225
226
197
    if (strip_or_tile == NOSTRIP || strip_or_tile >= td->td_nstrips)
227
0
    {
228
0
        TIFFErrorExtR(tif, module, "Strip/tile number not valid");
229
0
        return 0;
230
0
    }
231
232
197
    if (td->td_stripbytecount_p[strip_or_tile] > 0)
233
0
    {
234
        /* The +1 is to ensure at least one extra bytes */
235
        /* The +4 is because the LZW encoder flushes 4 bytes before the limit */
236
0
        uint64_t safe_buffer_size =
237
0
            (uint64_t)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4);
238
0
        if (tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size)
239
0
        {
240
0
            if (!(TIFFWriteBufferSetup(
241
0
                    tif, NULL,
242
0
                    (tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))))
243
0
                return 0;
244
0
        }
245
0
    }
246
197
    return 1;
247
197
}
248
249
/*
250
 * Encode the supplied data and write it to the
251
 * specified strip.
252
 *
253
 * NB: Image length must be setup before writing.
254
 */
255
tmsize_t TIFFWriteEncodedStrip(TIFF *tif, uint32_t strip, void *data,
256
                               tmsize_t cc)
257
201
{
258
201
    static const char module[] = "TIFFWriteEncodedStrip";
259
201
    TIFFDirectory *td = &tif->tif_dir;
260
201
    uint16_t sample;
261
262
201
    if (!WRITECHECKSTRIPS(tif, module))
263
4
        return ((tmsize_t)-1);
264
    /*
265
     * Check strip array to make sure there's space.
266
     * We don't support dynamically growing files that
267
     * have data organized in separate bitplanes because
268
     * it's too painful.  In that case we require that
269
     * the imagelength be set properly before the first
270
     * write (so that the strips array will be fully
271
     * allocated above).
272
     */
273
197
    if (strip >= td->td_nstrips)
274
0
    {
275
0
        if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
276
0
        {
277
0
            TIFFErrorExtR(
278
0
                tif, module,
279
0
                "Can not grow image by strips when using separate planes");
280
0
            return ((tmsize_t)-1);
281
0
        }
282
0
        if (!TIFFGrowStrips(tif, 1, module))
283
0
            return ((tmsize_t)-1);
284
0
        td->td_stripsperimage =
285
0
            TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
286
0
    }
287
    /*
288
     * Handle delayed allocation of data buffer.  This
289
     * permits it to be sized according to the directory
290
     * info.
291
     */
292
197
    if (!BUFFERCHECK(tif))
293
0
        return ((tmsize_t)-1);
294
295
197
    tif->tif_flags |= TIFF_BUF4WRITE;
296
297
197
    tif->tif_dir.td_curstrip = strip;
298
299
    /* this informs TIFFAppendToStrip() we have changed or reset strip */
300
197
    tif->tif_curoff = 0;
301
302
197
    if (!_TIFFReserveLargeEnoughWriteBuffer(tif, strip))
303
0
    {
304
0
        return ((tmsize_t)(-1));
305
0
    }
306
307
197
    tif->tif_rawcc = 0;
308
197
    tif->tif_rawcp = tif->tif_rawdata;
309
310
197
    if (td->td_stripsperimage == 0)
311
0
    {
312
0
        TIFFErrorExtR(tif, module, "Zero strips per image");
313
0
        return ((tmsize_t)-1);
314
0
    }
315
316
197
    tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
317
197
    if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
318
197
    {
319
197
        if (!(*tif->tif_setupencode)(tif))
320
0
            return ((tmsize_t)-1);
321
197
        tif->tif_flags |= TIFF_CODERSETUP;
322
197
    }
323
324
197
    tif->tif_flags &= ~TIFF_POSTENCODE;
325
326
    /* shortcut to avoid an extra memcpy() */
327
197
    if (td->td_compression == COMPRESSION_NONE)
328
197
    {
329
        /* swab if needed - note that source buffer will be altered */
330
197
        tif->tif_postdecode(tif, (uint8_t *)data, cc);
331
332
197
        if (!isFillOrder(tif, td->td_fillorder) &&
333
0
            (tif->tif_flags & TIFF_NOBITREV) == 0)
334
0
            TIFFReverseBits((uint8_t *)data, cc);
335
336
197
        if (cc > 0 && !TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc))
337
0
            return ((tmsize_t)-1);
338
197
        return (cc);
339
197
    }
340
341
0
    sample = (uint16_t)(strip / td->td_stripsperimage);
342
0
    if (!(*tif->tif_preencode)(tif, sample))
343
0
        return ((tmsize_t)-1);
344
345
    /* swab if needed - note that source buffer will be altered */
346
0
    tif->tif_postdecode(tif, (uint8_t *)data, cc);
347
348
0
    if (!(*tif->tif_encodestrip)(tif, (uint8_t *)data, cc, sample))
349
0
        return ((tmsize_t)-1);
350
0
    if (!(*tif->tif_postencode)(tif))
351
0
        return ((tmsize_t)-1);
352
0
    if (!isFillOrder(tif, td->td_fillorder) &&
353
0
        (tif->tif_flags & TIFF_NOBITREV) == 0)
354
0
        TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
355
0
    if (tif->tif_rawcc > 0 &&
356
0
        !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
357
0
        return ((tmsize_t)-1);
358
0
    tif->tif_rawcc = 0;
359
0
    tif->tif_rawcp = tif->tif_rawdata;
360
0
    return (cc);
361
0
}
362
363
/*
364
 * Write the supplied data to the specified strip.
365
 *
366
 * NB: Image length must be setup before writing.
367
 */
368
tmsize_t TIFFWriteRawStrip(TIFF *tif, uint32_t strip, void *data, tmsize_t cc)
369
0
{
370
0
    static const char module[] = "TIFFWriteRawStrip";
371
0
    TIFFDirectory *td = &tif->tif_dir;
372
373
0
    if (!WRITECHECKSTRIPS(tif, module))
374
0
        return ((tmsize_t)-1);
375
    /*
376
     * Check strip array to make sure there's space.
377
     * We don't support dynamically growing files that
378
     * have data organized in separate bitplanes because
379
     * it's too painful.  In that case we require that
380
     * the imagelength be set properly before the first
381
     * write (so that the strips array will be fully
382
     * allocated above).
383
     */
384
0
    if (strip >= td->td_nstrips)
385
0
    {
386
0
        if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
387
0
        {
388
0
            TIFFErrorExtR(
389
0
                tif, module,
390
0
                "Can not grow image by strips when using separate planes");
391
0
            return ((tmsize_t)-1);
392
0
        }
393
        /*
394
         * Watch out for a growing image.  The value of
395
         * strips/image will initially be 1 (since it
396
         * can't be deduced until the imagelength is known).
397
         */
398
0
        if (strip >= td->td_stripsperimage)
399
0
            td->td_stripsperimage =
400
0
                TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip);
401
0
        if (!TIFFGrowStrips(tif, 1, module))
402
0
            return ((tmsize_t)-1);
403
0
    }
404
405
0
    if (tif->tif_dir.td_curstrip != strip)
406
0
    {
407
0
        tif->tif_dir.td_curstrip = strip;
408
409
        /* this informs TIFFAppendToStrip() we have changed or reset strip */
410
0
        tif->tif_curoff = 0;
411
0
    }
412
413
0
    if (td->td_stripsperimage == 0)
414
0
    {
415
0
        TIFFErrorExtR(tif, module, "Zero strips per image");
416
0
        return ((tmsize_t)-1);
417
0
    }
418
0
    tif->tif_dir.td_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
419
0
    return (TIFFAppendToStrip(tif, strip, (uint8_t *)data, cc) ? cc
420
0
                                                               : (tmsize_t)-1);
421
0
}
422
423
/*
424
 * Write and compress a tile of data.  The
425
 * tile is selected by the (x,y,z,s) coordinates.
426
 */
427
tmsize_t TIFFWriteTile(TIFF *tif, void *buf, uint32_t x, uint32_t y, uint32_t z,
428
                       uint16_t s)
429
0
{
430
0
    if (!TIFFCheckTile(tif, x, y, z, s))
431
0
        return ((tmsize_t)(-1));
432
    /*
433
     * NB: A tile size of -1 is used instead of tif_tilesize knowing
434
     *     that TIFFWriteEncodedTile will clamp this to the tile size.
435
     *     This is done because the tile size may not be defined until
436
     *     after the output buffer is setup in TIFFWriteBufferSetup.
437
     */
438
0
    return (TIFFWriteEncodedTile(tif, TIFFComputeTile(tif, x, y, z, s), buf,
439
0
                                 (tmsize_t)(-1)));
440
0
}
441
442
/*
443
 * Encode the supplied data and write it to the
444
 * specified tile.  There must be space for the
445
 * data.  The function clamps individual writes
446
 * to a tile to the tile size, but does not (and
447
 * can not) check that multiple writes to the same
448
 * tile do not write more than tile size data.
449
 *
450
 * NB: Image length must be setup before writing; this
451
 *     interface does not support automatically growing
452
 *     the image on each write (as TIFFWriteScanline does).
453
 */
454
tmsize_t TIFFWriteEncodedTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
455
0
{
456
0
    static const char module[] = "TIFFWriteEncodedTile";
457
0
    TIFFDirectory *td;
458
0
    uint16_t sample;
459
0
    uint32_t howmany32;
460
461
0
    if (!WRITECHECKTILES(tif, module))
462
0
        return ((tmsize_t)(-1));
463
0
    td = &tif->tif_dir;
464
0
    if (tile >= td->td_nstrips)
465
0
    {
466
0
        TIFFErrorExtR(tif, module, "Tile %lu out of range, max %lu",
467
0
                      (unsigned long)tile, (unsigned long)td->td_nstrips);
468
0
        return ((tmsize_t)(-1));
469
0
    }
470
    /*
471
     * Handle delayed allocation of data buffer.  This
472
     * permits it to be sized more intelligently (using
473
     * directory information).
474
     */
475
0
    if (!BUFFERCHECK(tif))
476
0
        return ((tmsize_t)(-1));
477
478
0
    tif->tif_flags |= TIFF_BUF4WRITE;
479
480
0
    tif->tif_dir.td_curtile = tile;
481
482
    /* this informs TIFFAppendToStrip() we have changed or reset tile */
483
0
    tif->tif_curoff = 0;
484
485
0
    if (!_TIFFReserveLargeEnoughWriteBuffer(tif, tile))
486
0
    {
487
0
        return ((tmsize_t)(-1));
488
0
    }
489
490
0
    tif->tif_rawcc = 0;
491
0
    tif->tif_rawcp = tif->tif_rawdata;
492
493
    /*
494
     * Compute tiles per row & per column to compute
495
     * current row and column
496
     */
497
0
    howmany32 = TIFFhowmany_32(td->td_imagelength, td->td_tilelength);
498
0
    if (howmany32 == 0)
499
0
    {
500
0
        TIFFErrorExtR(tif, module, "Zero tiles");
501
0
        return ((tmsize_t)(-1));
502
0
    }
503
0
    tif->tif_dir.td_row = (tile % howmany32) * td->td_tilelength;
504
0
    howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth);
505
0
    if (howmany32 == 0)
506
0
    {
507
0
        TIFFErrorExtR(tif, module, "Zero tiles");
508
0
        return ((tmsize_t)(-1));
509
0
    }
510
0
    tif->tif_dir.td_col = (tile % howmany32) * td->td_tilewidth;
511
512
0
    if ((tif->tif_flags & TIFF_CODERSETUP) == 0)
513
0
    {
514
0
        if (!(*tif->tif_setupencode)(tif))
515
0
            return ((tmsize_t)(-1));
516
0
        tif->tif_flags |= TIFF_CODERSETUP;
517
0
    }
518
0
    tif->tif_flags &= ~TIFF_POSTENCODE;
519
520
    /*
521
     * Clamp write amount to the tile size.  This is mostly
522
     * done so that callers can pass in some large number
523
     * (e.g. -1) and have the tile size used instead.
524
     */
525
0
    if (cc < 1 || cc > tif->tif_dir.td_tilesize)
526
0
        cc = tif->tif_dir.td_tilesize;
527
528
    /* shortcut to avoid an extra memcpy() */
529
0
    if (td->td_compression == COMPRESSION_NONE)
530
0
    {
531
        /* swab if needed - note that source buffer will be altered */
532
0
        tif->tif_postdecode(tif, (uint8_t *)data, cc);
533
534
0
        if (!isFillOrder(tif, td->td_fillorder) &&
535
0
            (tif->tif_flags & TIFF_NOBITREV) == 0)
536
0
            TIFFReverseBits((uint8_t *)data, cc);
537
538
0
        if (cc > 0 && !TIFFAppendToStrip(tif, tile, (uint8_t *)data, cc))
539
0
            return ((tmsize_t)-1);
540
0
        return (cc);
541
0
    }
542
543
0
    sample = (uint16_t)(tile / td->td_stripsperimage);
544
0
    if (!(*tif->tif_preencode)(tif, sample))
545
0
        return ((tmsize_t)(-1));
546
    /* swab if needed - note that source buffer will be altered */
547
0
    tif->tif_postdecode(tif, (uint8_t *)data, cc);
548
549
0
    if (!(*tif->tif_encodetile)(tif, (uint8_t *)data, cc, sample))
550
0
        return ((tmsize_t)-1);
551
0
    if (!(*tif->tif_postencode)(tif))
552
0
        return ((tmsize_t)(-1));
553
0
    if (!isFillOrder(tif, td->td_fillorder) &&
554
0
        (tif->tif_flags & TIFF_NOBITREV) == 0)
555
0
        TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
556
0
    if (tif->tif_rawcc > 0 &&
557
0
        !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc))
558
0
        return ((tmsize_t)(-1));
559
0
    tif->tif_rawcc = 0;
560
0
    tif->tif_rawcp = tif->tif_rawdata;
561
0
    return (cc);
562
0
}
563
564
/*
565
 * Write the supplied data to the specified strip.
566
 * There must be space for the data; we don't check
567
 * if strips overlap!
568
 *
569
 * NB: Image length must be setup before writing; this
570
 *     interface does not support automatically growing
571
 *     the image on each write (as TIFFWriteScanline does).
572
 */
573
tmsize_t TIFFWriteRawTile(TIFF *tif, uint32_t tile, void *data, tmsize_t cc)
574
0
{
575
0
    static const char module[] = "TIFFWriteRawTile";
576
577
0
    if (!WRITECHECKTILES(tif, module))
578
0
        return ((tmsize_t)(-1));
579
0
    if (tile >= tif->tif_dir.td_nstrips)
580
0
    {
581
0
        TIFFErrorExtR(tif, module, "Tile %lu out of range, max %lu",
582
0
                      (unsigned long)tile,
583
0
                      (unsigned long)tif->tif_dir.td_nstrips);
584
0
        return ((tmsize_t)(-1));
585
0
    }
586
0
    return (TIFFAppendToStrip(tif, tile, (uint8_t *)data, cc) ? cc
587
0
                                                              : (tmsize_t)(-1));
588
0
}
589
590
#define isUnspecified(tif, f)                                                  \
591
197
    (TIFFFieldSet(tif, f) && (tif)->tif_dir.td_imagelength == 0)
592
593
int TIFFSetupStrips(TIFF *tif)
594
197
{
595
197
    TIFFDirectory *td = &tif->tif_dir;
596
597
197
    if (isTiled(tif))
598
0
        td->td_stripsperimage = isUnspecified(tif, FIELD_TILEDIMENSIONS)
599
0
                                    ? td->td_samplesperpixel
600
0
                                    : TIFFNumberOfTiles(tif);
601
197
    else
602
197
        td->td_stripsperimage = isUnspecified(tif, FIELD_ROWSPERSTRIP)
603
197
                                    ? td->td_samplesperpixel
604
197
                                    : TIFFNumberOfStrips(tif);
605
197
    td->td_nstrips = td->td_stripsperimage;
606
    /* TIFFWriteDirectoryTagData has a limitation to 0x80000000U bytes */
607
197
    if (td->td_nstrips >=
608
197
        0x80000000U / ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
609
0
    {
610
0
        TIFFErrorExtR(tif, "TIFFSetupStrips",
611
0
                      "Too large Strip/Tile Offsets/ByteCounts arrays");
612
0
        return 0;
613
0
    }
614
197
    if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
615
0
        td->td_stripsperimage /= td->td_samplesperpixel;
616
617
197
    if (td->td_stripoffset_p != NULL)
618
0
        _TIFFfreeExt(tif, td->td_stripoffset_p);
619
197
    td->td_stripoffset_p = (uint64_t *)_TIFFCheckMalloc(
620
197
        tif, td->td_nstrips, sizeof(uint64_t), "for \"StripOffsets\" array");
621
197
    if (td->td_stripbytecount_p != NULL)
622
0
        _TIFFfreeExt(tif, td->td_stripbytecount_p);
623
197
    td->td_stripbytecount_p = (uint64_t *)_TIFFCheckMalloc(
624
197
        tif, td->td_nstrips, sizeof(uint64_t), "for \"StripByteCounts\" array");
625
197
    if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL)
626
0
        return (0);
627
    /*
628
     * Place data at the end-of-file
629
     * (by setting offsets to zero).
630
     */
631
197
    _TIFFmemset(td->td_stripoffset_p, 0,
632
197
                (tmsize_t)((size_t)td->td_nstrips * sizeof(uint64_t)));
633
197
    _TIFFmemset(td->td_stripbytecount_p, 0,
634
197
                (tmsize_t)((size_t)td->td_nstrips * sizeof(uint64_t)));
635
197
    TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
636
197
    TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
637
197
    return (1);
638
197
}
639
#undef isUnspecified
640
641
/*
642
 * Verify file is writable and that the directory
643
 * information is setup properly.  In doing the latter
644
 * we also "freeze" the state of the directory so
645
 * that important information is not changed.
646
 */
647
int TIFFWriteCheck(TIFF *tif, int tiles, const char *module)
648
201
{
649
201
    if (tif->tif_mode == O_RDONLY)
650
0
    {
651
0
        TIFFErrorExtR(tif, module, "File not open for writing");
652
0
        return (0);
653
0
    }
654
201
    if (tiles ^ isTiled(tif))
655
0
    {
656
0
        TIFFErrorExtR(tif, module,
657
0
                      tiles ? "Can not write tiles to a striped image"
658
0
                            : "Can not write scanlines to a tiled image");
659
0
        return (0);
660
0
    }
661
662
201
    _TIFFFillStriles(tif);
663
664
    /*
665
     * On the first write verify all the required information
666
     * has been setup and initialize any data structures that
667
     * had to wait until directory information was set.
668
     * Note that a lot of our work is assumed to remain valid
669
     * because we disallow any of the important parameters
670
     * from changing after we start writing (i.e. once
671
     * TIFF_BEENWRITING is set, TIFFSetField will only allow
672
     * the image's length to be changed).
673
     */
674
201
    if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS))
675
4
    {
676
4
        TIFFErrorExtR(tif, module,
677
4
                      "Must set \"ImageWidth\" before writing data");
678
4
        return (0);
679
4
    }
680
197
    if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif))
681
0
    {
682
0
        tif->tif_dir.td_nstrips = 0;
683
0
        TIFFErrorExtR(tif, module, "No space for %s arrays",
684
0
                      isTiled(tif) ? "tile" : "strip");
685
0
        return (0);
686
0
    }
687
197
    if (isTiled(tif))
688
0
    {
689
0
        tif->tif_dir.td_tilesize = TIFFTileSize(tif);
690
0
        if (tif->tif_dir.td_tilesize == 0)
691
0
            return (0);
692
0
    }
693
197
    else
694
197
        tif->tif_dir.td_tilesize = (tmsize_t)(-1);
695
197
    tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
696
197
    if (tif->tif_dir.td_scanlinesize == 0)
697
0
        return (0);
698
197
    tif->tif_flags |= TIFF_BEENWRITING;
699
700
197
    if (tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
701
0
        tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
702
0
        tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
703
0
        tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
704
0
        tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
705
0
        tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
706
0
        tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
707
0
        tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 &&
708
0
        !(tif->tif_flags & TIFF_DIRTYDIRECT))
709
0
    {
710
0
        TIFFForceStrileArrayWriting(tif);
711
0
    }
712
713
197
    return (1);
714
197
}
715
716
/*
717
 * Setup the raw data buffer used for encoding.
718
 */
719
int TIFFWriteBufferSetup(TIFF *tif, void *bp, tmsize_t size)
720
197
{
721
197
    static const char module[] = "TIFFWriteBufferSetup";
722
723
197
    if (tif->tif_rawdata)
724
0
    {
725
0
        if (tif->tif_flags & TIFF_MYBUFFER)
726
0
        {
727
0
            _TIFFfreeExt(tif, tif->tif_rawdata);
728
0
            tif->tif_flags &= ~TIFF_MYBUFFER;
729
0
        }
730
0
        tif->tif_rawdata = NULL;
731
0
    }
732
197
    if (size == (tmsize_t)(-1))
733
197
    {
734
197
        size = (isTiled(tif) ? tif->tif_dir.td_tilesize : TIFFStripSize(tif));
735
736
        /* Adds 10% margin for cases where compression would expand a bit */
737
197
        if (size < TIFF_TMSIZE_T_MAX - size / 10)
738
197
            size += size / 10;
739
        /*
740
         * Make raw data buffer at least 8K
741
         */
742
197
        if (size < 8 * 1024)
743
197
            size = 8 * 1024;
744
197
        bp = NULL; /* NB: force malloc */
745
197
    }
746
197
    if (bp == NULL)
747
197
    {
748
197
        bp = _TIFFmallocExt(tif, size);
749
197
        if (bp == NULL)
750
0
        {
751
0
            TIFFErrorExtR(tif, module, "No space for output buffer");
752
0
            return (0);
753
0
        }
754
197
        tif->tif_flags |= TIFF_MYBUFFER;
755
197
    }
756
0
    else
757
0
        tif->tif_flags &= ~TIFF_MYBUFFER;
758
197
    tif->tif_rawdata = (uint8_t *)bp;
759
197
    tif->tif_rawdatasize = size;
760
197
    tif->tif_rawcc = 0;
761
197
    tif->tif_rawcp = tif->tif_rawdata;
762
197
    tif->tif_flags |= TIFF_BUFFERSETUP;
763
197
    return (1);
764
197
}
765
766
/*
767
 * Grow the strip data structures by delta strips.
768
 */
769
static int TIFFGrowStrips(TIFF *tif, uint32_t delta, const char *module)
770
0
{
771
0
    TIFFDirectory *td = &tif->tif_dir;
772
0
    uint64_t *new_stripoffset;
773
0
    uint64_t *new_stripbytecount;
774
775
0
    assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
776
0
    new_stripoffset = (uint64_t *)_TIFFreallocExt(
777
0
        tif, td->td_stripoffset_p,
778
0
        (tmsize_t)(((size_t)td->td_nstrips + (size_t)delta) *
779
0
                   sizeof(uint64_t)));
780
    /*
781
     * Update td_stripoffset_p immediately so the old pointer is not left
782
     * dangling if the second realloc fails.
783
     */
784
0
    if (new_stripoffset)
785
0
        td->td_stripoffset_p = new_stripoffset;
786
0
    new_stripbytecount = (uint64_t *)_TIFFreallocExt(
787
0
        tif, td->td_stripbytecount_p,
788
0
        (tmsize_t)(((size_t)td->td_nstrips + (size_t)delta) *
789
0
                   sizeof(uint64_t)));
790
0
    if (new_stripbytecount)
791
0
        td->td_stripbytecount_p = new_stripbytecount;
792
0
    if (new_stripoffset == NULL || new_stripbytecount == NULL)
793
0
    {
794
0
        td->td_nstrips = 0;
795
0
        TIFFErrorExtR(tif, module, "No space to expand strip arrays");
796
0
        return (0);
797
0
    }
798
0
    _TIFFmemset(td->td_stripoffset_p + td->td_nstrips, 0,
799
0
                (tmsize_t)((size_t)delta * sizeof(uint64_t)));
800
0
    _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips, 0,
801
0
                (tmsize_t)((size_t)delta * sizeof(uint64_t)));
802
0
    td->td_nstrips += delta;
803
0
    tif->tif_flags |= TIFF_DIRTYDIRECT;
804
805
0
    return (1);
806
0
}
807
808
/*
809
 * Append the data to the specified strip.
810
 */
811
static int TIFFAppendToStrip(TIFF *tif, uint32_t strip, uint8_t *data,
812
                             tmsize_t cc)
813
197
{
814
197
    static const char module[] = "TIFFAppendToStrip";
815
197
    TIFFDirectory *td = &tif->tif_dir;
816
197
    uint64_t m;
817
197
    int64_t old_byte_count = -1;
818
819
    /* Some security checks */
820
197
    if (td->td_stripoffset_p == NULL)
821
0
    {
822
0
        TIFFErrorExtR(tif, module, "Strip offset array pointer is NULL");
823
0
        return (0);
824
0
    }
825
197
    if (td->td_stripbytecount_p == NULL)
826
0
    {
827
0
        TIFFErrorExtR(tif, module, "Strip bytecount array pointer is NULL");
828
0
        return (0);
829
0
    }
830
197
    if (strip == NOSTRIP)
831
0
    {
832
0
        TIFFErrorExtR(tif, module, "Strip number not valid (NOSTRIP)");
833
0
        return (0);
834
0
    }
835
836
197
    if (tif->tif_curoff == 0)
837
197
        tif->tif_lastvalidoff = 0;
838
839
197
    if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0)
840
197
    {
841
197
        assert(td->td_nstrips > 0);
842
843
197
        if (td->td_stripbytecount_p[strip] != 0 &&
844
0
            td->td_stripoffset_p[strip] != 0 &&
845
0
            td->td_stripbytecount_p[strip] >= (uint64_t)cc)
846
0
        {
847
            /*
848
             * There is already tile data on disk, and the new tile
849
             * data we have will fit in the same space.  The only
850
             * aspect of this that is risky is that there could be
851
             * more data to append to this strip before we are done
852
             * depending on how we are getting called.
853
             */
854
0
            if (!SeekOK(tif, td->td_stripoffset_p[strip]))
855
0
            {
856
0
                TIFFErrorExtR(tif, module, "Seek error at scanline %lu",
857
0
                              (unsigned long)tif->tif_dir.td_row);
858
0
                return (0);
859
0
            }
860
861
0
            tif->tif_lastvalidoff =
862
0
                td->td_stripoffset_p[strip] + td->td_stripbytecount_p[strip];
863
0
        }
864
197
        else
865
197
        {
866
            /*
867
             * Seek to end of file, and set that as our location to
868
             * write this strip.
869
             */
870
197
            td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
871
197
            tif->tif_flags |= TIFF_DIRTYSTRIP;
872
197
        }
873
874
197
        tif->tif_curoff = td->td_stripoffset_p[strip];
875
876
        /*
877
         * We are starting a fresh strip/tile, so set the size to zero.
878
         */
879
197
        old_byte_count = (int64_t)td->td_stripbytecount_p[strip];
880
197
        td->td_stripbytecount_p[strip] = 0;
881
197
    }
882
883
197
    m = tif->tif_curoff + (uint64_t)cc;
884
197
    if (!(tif->tif_flags & TIFF_BIGTIFF))
885
197
        m = (uint32_t)m;
886
197
    if ((m < tif->tif_curoff) || (m < (uint64_t)cc))
887
0
    {
888
0
        TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
889
0
        return (0);
890
0
    }
891
892
197
    if (tif->tif_lastvalidoff != 0 && m > tif->tif_lastvalidoff &&
893
0
        td->td_stripbytecount_p[strip] > 0)
894
0
    {
895
        /* Ouch: we have detected that we are rewriting in place a strip/tile */
896
        /* with several calls to TIFFAppendToStrip(). The first call was with */
897
        /* a size smaller than the previous size of the strip/tile, so we */
898
        /* opted to rewrite in place, but a following call causes us to go */
899
        /* outsize of the strip/tile area, so we have to finally go for a */
900
        /* append-at-end-of-file strategy, and start by moving what we already
901
         */
902
        /* wrote. */
903
0
        tmsize_t tempSize;
904
0
        void *temp;
905
0
        uint64_t offsetRead;
906
0
        uint64_t offsetWrite;
907
0
        uint64_t toCopy = td->td_stripbytecount_p[strip];
908
909
0
        if (toCopy < 1024 * 1024)
910
0
            tempSize = (tmsize_t)toCopy;
911
0
        else
912
0
            tempSize = 1024 * 1024;
913
914
0
        offsetRead = td->td_stripoffset_p[strip];
915
0
        offsetWrite = TIFFSeekFile(tif, 0, SEEK_END);
916
917
0
        m = offsetWrite + (uint64_t)toCopy + (uint64_t)cc;
918
0
        if (!(tif->tif_flags & TIFF_BIGTIFF) && m != (uint32_t)m)
919
0
        {
920
0
            TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
921
0
            return (0);
922
0
        }
923
924
0
        temp = _TIFFmallocExt(tif, tempSize);
925
0
        if (temp == NULL)
926
0
        {
927
0
            TIFFErrorExtR(tif, module, "No space for output buffer");
928
0
            return (0);
929
0
        }
930
931
0
        tif->tif_flags |= TIFF_DIRTYSTRIP;
932
933
0
        td->td_stripoffset_p[strip] = offsetWrite;
934
0
        td->td_stripbytecount_p[strip] = 0;
935
936
        /* Move data written by previous calls to us at end of file */
937
0
        while (toCopy > 0)
938
0
        {
939
0
            tmsize_t chunkSize =
940
0
                toCopy < (uint64_t)tempSize ? (tmsize_t)toCopy : tempSize;
941
0
            if (!SeekOK(tif, offsetRead))
942
0
            {
943
0
                TIFFErrorExtR(tif, module, "Seek error");
944
0
                _TIFFfreeExt(tif, temp);
945
0
                return (0);
946
0
            }
947
0
            if (!ReadOK(tif, temp, chunkSize))
948
0
            {
949
0
                TIFFErrorExtR(tif, module, "Cannot read");
950
0
                _TIFFfreeExt(tif, temp);
951
0
                return (0);
952
0
            }
953
0
            if (!SeekOK(tif, offsetWrite))
954
0
            {
955
0
                TIFFErrorExtR(tif, module, "Seek error");
956
0
                _TIFFfreeExt(tif, temp);
957
0
                return (0);
958
0
            }
959
0
            if (!WriteOK(tif, temp, chunkSize))
960
0
            {
961
0
                TIFFErrorExtR(tif, module, "Cannot write");
962
0
                _TIFFfreeExt(tif, temp);
963
0
                return (0);
964
0
            }
965
0
            offsetRead += (uint64_t)chunkSize;
966
0
            offsetWrite += (uint64_t)chunkSize;
967
0
            td->td_stripbytecount_p[strip] += (uint64_t)chunkSize;
968
0
            toCopy -= (uint64_t)chunkSize;
969
0
        }
970
0
        _TIFFfreeExt(tif, temp);
971
972
        /* Append the data of this call */
973
0
        offsetWrite += (uint64_t)cc;
974
0
        m = offsetWrite;
975
0
    }
976
977
197
    if (!WriteOK(tif, data, cc))
978
0
    {
979
0
        TIFFErrorExtR(tif, module, "Write error at scanline %lu",
980
0
                      (unsigned long)tif->tif_dir.td_row);
981
0
        return (0);
982
0
    }
983
197
    tif->tif_curoff = m;
984
197
    td->td_stripbytecount_p[strip] += (uint64_t)cc;
985
986
197
    if ((int64_t)td->td_stripbytecount_p[strip] != old_byte_count)
987
197
        tif->tif_flags |= TIFF_DIRTYSTRIP;
988
989
197
    return (1);
990
197
}
991
992
/*
993
 * Internal version of TIFFFlushData that can be
994
 * called by ``encodestrip routines'' w/o concern
995
 * for infinite recursion.
996
 */
997
int TIFFFlushData1(TIFF *tif)
998
197
{
999
197
    if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE)
1000
0
    {
1001
0
        if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
1002
0
            (tif->tif_flags & TIFF_NOBITREV) == 0)
1003
0
            TIFFReverseBits((uint8_t *)tif->tif_rawdata, tif->tif_rawcc);
1004
0
        if (!TIFFAppendToStrip(tif,
1005
0
                               isTiled(tif) ? tif->tif_dir.td_curtile
1006
0
                                            : tif->tif_dir.td_curstrip,
1007
0
                               tif->tif_rawdata, tif->tif_rawcc))
1008
0
        {
1009
            /* We update those variables even in case of error since there's */
1010
            /* code that doesn't really check the return code of this */
1011
            /* function */
1012
0
            tif->tif_rawcc = 0;
1013
0
            tif->tif_rawcp = tif->tif_rawdata;
1014
0
            return (0);
1015
0
        }
1016
0
        tif->tif_rawcc = 0;
1017
0
        tif->tif_rawcp = tif->tif_rawdata;
1018
0
    }
1019
197
    return (1);
1020
197
}
1021
1022
/*
1023
 * Set the current write offset.  This should only be
1024
 * used to set the offset to a known previous location
1025
 * (very carefully), or to 0 so that the next write gets
1026
 * appended to the end of the file.
1027
 */
1028
void TIFFSetWriteOffset(TIFF *tif, toff_t off)
1029
0
{
1030
0
    tif->tif_curoff = off;
1031
0
    tif->tif_lastvalidoff = 0;
1032
0
}