A null-pointer dereference in libtiff leads to a crash during directory rewrite on TIFFClose()/TIFFFlush() when handling malformed inputs.

# Bug Report

TIFFWriteDirectoryTagLongLong8Array.zip

## Describe the bug

A null-pointer dereference in libtiff leads to a crash during directory rewrite on TIFFClose()/TIFFFlush() when handling malformed inputs.

When TIFFRewriteDirectorySec%20writes%20StripOffsets/StripByteCounts%20as%20LONG8%20arrays,%20it%20calls%20TIFFWriteDirectoryTagLongLong8Array() with a NULL array pointer. Inside that function, the code unconditionally dereferences the pointer (*ma > 0xFFFF), causing a segmentation fault.

- Impact: Denial of service (process crash). This can be triggered when an application opens a crafted TIFF in update mode ("r+", or otherwise hits the rewrite path) and then closes it.

- CWE: CWE-476 (NULL Pointer Dereference)

- Observed result (ASan):

```

SEGV at TIFFWriteDirectoryTagLongLong8Array (tif_dirwrite.c:2006)

#0 TIFFWriteDirectoryTagLongLong8Array

#1 (closed) TIFFWriteDirectorySec

#2 (closed) TIFFRewriteDirectorySec / TIFFRewriteDirectory

#3 (closed) TIFFFlush

#4 (closed) TIFFCleanup

#5 (closed) TIFFClose

```

# Root Cause Analysis

- During TIFFClose() → TIFFCleanup() → TIFFFlush(), the code may decide to rewrite the directory (e.g., update mode / dirty strip state / force strile arrays).

- TIFFRewriteDirectorySec() → TIFFWriteDirectorySec() attempts to write StripOffsets / StripByteCounts using LONG8 arrays and passes pointers derived from td->td_stripoffset_p / td->td_stripbytecount_p.

- With malformed inputs and certain state transitions, these pointers remain NULL (the directory lacked required fields and no safe allocation was performed).

- TIFFWriteDirectoryTagLongLong8Array() then unconditionally dereferences the array pointer (if (*ma > 0xFFFF) … at tif_dirwrite.c:2006) → NULL deref.

This is a logic/defensive-programming gap: the write path assumes the arrays are valid and non-NULL, but that precondition isn’t enforced when the input is inconsistent.

# Fix suggestions

1. Immediate guard in TIFFWriteDirectoryTagLongLong8Array():

- If value == NULL or count == 0, return error (set tif->tif_errno appropriately) instead of dereferencing.

2. Upstream consistency in TIFFWriteDirectorySec():

- Before calling writers for StripOffsets/StripByteCounts, ensure td_stripoffset_p / td_stripbytecount_p are allocated/initialized (or refuse rewrite with a clear error).

- Alternatively, ensure TIFFForceStrileArrayWriting() (or equivalent) guarantees those arrays are non-NULL before reaching the tag-writer.

# To Reproduce

1. Compile libtiff with AddressSanitizer:

```

export CC="clang -fsanitize=address,fuzzer-no-link -g "

export CFLAGS="-g -O0"

mkdir build_asan

cd build_asan

../code/configure --prefix=$PWD/../bin_asan --enable-static --disable-shared

make -j$(nproc)

make install

```

2. Compile the Fuzz Driver:

- Compile the fuzz driver with the following command:

```

clang ./fuzz_driver_184.c -o ./fuzz_driver_184 -fsanitize=fuzzer,address,undefined -g -O0 -I../bin_asan/include ../bin_asan/lib/libtiff.a -lz -ljpeg -ljbig -llzma -lzstd -ldeflate -lwebp -lsharpyuv -L/usr/local/lib -lLerc -lm -lpthread

```

3. Run the Fuzz Driver:

```

./fuzz_driver_184 ./bug.input

```

# Desktop Environment

- OS and Version: Linux (Ubuntu 24.04.2 LTS)

- libtiff Version and Source:

main branch at commit 5fe20d0e9aba49a6a350ed533459d1505203838f (Fri Sep 12 11:21:38 2025 +0000)(from  https://gitlab.com/libtiff/libtiff.git )

- Compiler and Version: Ubuntu clang version 18.1.3

# ASan Report

=================================================================

INFO: Running with entropic power schedule (0xFF, 100).

INFO: Seed: 2801120172

INFO: Loaded 1 modules (10731 inline 8-bit counters): 10731 [0x5a4601cb4668, 0x5a4601cb7053),

INFO: Loaded 1 PC tables (10731 PCs): 10731 [0x5a4601cb7058,0x5a4601ce0f08),

./fuzz_driver_184: Running 1 inputs 1 time(s) each.

Running: ./bug.input

TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 0 (Tag 0) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFReadDirectory: Warning, Invalid data type for tag TileOffsets.

TIFFReadDirectory: Warning, TIFF directory is missing required "StripByteCounts" field, calculating from imagelength.

TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.

TIFFFetchNormalTag: Warning, IO error during reading of "Tag 0"; tag ignored.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 33023 (Tag 33023) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 59136 (Tag 59136) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 97 (Tag 97) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFReadDirectory: Warning, Invalid data type for tag TileByteCounts.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 16 (Tag 16) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 65280 (Tag 65280) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

MissingRequired: TIFF directory is missing required "StripOffsets" field.

TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 0 (Tag 0) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFReadDirectory: Warning, Invalid data type for tag TileOffsets.

TIFFReadDirectory: Warning, TIFF directory is missing required "StripByteCounts" field, calculating from imagelength.

TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.

TIFFFetchNormalTag: Warning, IO error during reading of "Tag 0"; tag ignored.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 33023 (Tag 33023) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 59136 (Tag 59136) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 97 (Tag 97) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFReadDirectory: Warning, Invalid data type for tag TileByteCounts.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 16 (Tag 16) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 65280 (Tag 65280) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

MissingRequired: TIFF directory is missing required "StripOffsets" field.

TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 0 (Tag 0) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFReadDirectory: Warning, Invalid data type for tag TileOffsets.

TIFFReadDirectory: Warning, TIFF directory is missing required "StripByteCounts" field, calculating from imagelength.

TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.

TIFFFetchNormalTag: Warning, IO error during reading of "Tag 0"; tag ignored.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 33023 (Tag 33023) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 59136 (Tag 59136) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 97 (Tag 97) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFReadDirectory: Warning, Invalid data type for tag TileByteCounts.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 16 (Tag 16) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 65280 (Tag 65280) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

MissingRequired: TIFF directory is missing required "StripOffsets" field.

TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 0 (Tag 0) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFReadDirectory: Warning, Invalid data type for tag TileOffsets.

TIFFReadDirectory: Warning, TIFF directory is missing required "StripByteCounts" field, calculating from imagelength.

TIFFReadDirectoryCheckOrder: Warning, Invalid TIFF directory; tags are not sorted in ascending order.

TIFFFetchNormalTag: Warning, IO error during reading of "Tag 0"; tag ignored.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 33023 (Tag 33023) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 59136 (Tag 59136) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 97 (Tag 97) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFReadDirectory: Warning, Invalid data type for tag TileByteCounts.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 16 (Tag 16) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

TIFFFetchNormalTag: Defined set_get_field_type of custom tag 65280 (Tag 65280) is TIFF_SETGET_UNDEFINED and thus tag is not read from file.

MissingRequired: TIFF directory is missing required "StripOffsets" field.

TIFFVStripSize64: Invalid td_samplesperpixel value.

AddressSanitizer:DEADLYSIGNAL

=================================================================

==4060590==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x5a4601b2e937 bp 0x7ffe129a7410 sp 0x7ffe129a7230 T0)

==4060590==The signal is caused by a READ memory access.

==4060590==Hint: address points to the zero page.

#0 0x5a4601b2e937 in TIFFWriteDirectoryTagLongLong8Array /root/cov_fuzz/testTP/libtiff/build_asan/libtiff/../../code/libtiff/tif_dirwrite.c:2006:17

#1 0x5a4601b1f9ed in TIFFWriteDirectorySec /root/cov_fuzz/testTP/libtiff/build_asan/libtiff/../../code/libtiff/tif_dirwrite.c:717:26

#2 0x5a4601b29644 in TIFFRewriteDirectorySec /root/cov_fuzz/testTP/libtiff/build_asan/libtiff/../../code/libtiff/tif_dirwrite.c:474:12

#3 0x5a4601b278ff in TIFFRewriteDirectory /root/cov_fuzz/testTP/libtiff/build_asan/libtiff/../../code/libtiff/tif_dirwrite.c:485:12

#4 0x5a4601ae5d3a in TIFFFlush /root/cov_fuzz/testTP/libtiff/build_asan/libtiff/../../code/libtiff/tif_flush.c:51:10

#5 0x5a4601a6cfe5 in TIFFCleanup /root/cov_fuzz/testTP/libtiff/build_asan/libtiff/../../code/libtiff/tif_close.c:50:9

#6 0x5a4601a6de26 in TIFFClose /root/cov_fuzz/testTP/libtiff/build_asan/libtiff/../../code/libtiff/tif_close.c:162:9

#7 0x5a4601a6ccbe in LLVMFuzzerTestOneInput /root/cov_fuzz/testTP/libtiff/TIFFWriteDirectoryTagLongLong8Array/./fuzz_driver_184.c:77:9

#8 0x5a460197a2a4 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const\*, unsigned long) (/root/cov_fuzz/testTP/libtiff/TIFFWriteDirectoryTagLongLong8Array/fuzz_driver_184+0xac2a4) (BuildId: ead438d8377c6e41b9c4ffe8a6c28f8f2d2518bd)

#9 0x5a46019633d6 in fuzzer::RunOneTest(fuzzer::Fuzzer\*, char const\*, unsigned long) (/root/cov_fuzz/testTP/libtiff/TIFFWriteDirectoryTagLongLong8Array/fuzz_driver_184+0x953d6) (BuildId: ead438d8377c6e41b9c4ffe8a6c28f8f2d2518bd)

#10 0x5a4601968e8a in fuzzer::FuzzerDriver(int\*, char\*\*_\*, int (\*_)(unsigned char const\*, unsigned long)) (/root/cov_fuzz/testTP/libtiff/TIFFWriteDirectoryTagLongLong8Array/fuzz_driver_184+0x9ae8a) (BuildId: ead438d8377c6e41b9c4ffe8a6c28f8f2d2518bd)

#11 0x5a4601993646 in main (/root/cov_fuzz/testTP/libtiff/TIFFWriteDirectoryTagLongLong8Array/fuzz_driver_184+0xc5646) (BuildId: ead438d8377c6e41b9c4ffe8a6c28f8f2d2518bd)

#12 0x705a5989f1c9 in \__libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

#13 0x705a5989f28a in \__libc_start_main csu/../csu/libc-start.c:360:3

#14 0x5a460195dfa4 in \_start (/root/cov_fuzz/testTP/libtiff/TIFFWriteDirectoryTagLongLong8Array/fuzz_driver_184+0x8ffa4) (BuildId: ead438d8377c6e41b9c4ffe8a6c28f8f2d2518bd)

AddressSanitizer can not provide additional info.

SUMMARY: AddressSanitizer: SEGV /root/cov_fuzz/testTP/libtiff/build_asan/libtiff/../../code/libtiff/tif_dirwrite.c:2006:17 in TIFFWriteDirectoryTagLongLong8Array

==4060590==ABORTING