OpenPrinting / OpenPrinting/libcupsfilters
NULL-related ASAN reports
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 17
- Forks
- 71
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 13
Description
Hello maintainers! This issue regards several NULL-related ASAN crashes. This is more of a long question, rather than a bug report.
I found several NULL dereferences and a NULL function call. I guess even more might be found, but I currently have 3 examples.
They arise due to some data fields not being initialised when calling, f.e. cfFilterTextToPDF() or cfFilterBannerToPDF(). Has to be noted that some of the examples are also relevant for at least cfFilterImageToPDF()/ cfFilterImageToRaster().
Example 1: data.logfunc
ex1.c:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <cupsfilters/filter.h>
int main(int argc, char** argv)
{
if (argc < 2) return 0;
int fp = open(argv[1], O_RDONLY);
if (!fp) return 0;
int fp_out = open("/dev/null", O_WRONLY);
if (!fp_out) return 0;
cf_filter_data_t data;
memset(&data, 0, sizeof(data));
cfFilterTextToPDF(fp, fp_out, 1, &data, NULL);
close(fp);
close(fp_out);
return 0;
}
Since data.logfunc is not specified the following error occurs, upon an attempt to call it. NULL function call is the cause of <unknown module> in the stacktrace:
==76909==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7ffd0c938a70 sp 0x7ffd0c9383d8 T0)
==76909==Hint: pc points to the zero page.
==76909==The signal is caused by a READ memory access.
==76909==Hint: address points to the zero page.
#0 0x000000000000 (<unknown module>)
#1 0x615b7d8bc7c3 in cfFilterTextToPDF /orig/libcupsfilters/cupsfilters/texttopdf.c:681:3
#2 0x615b7d8bc0e6 in main /orig/libcupsfilters/ex1.c:19:5
#3 0x72a61bc15249 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
==76909==Register values:
rax = 0x000072a618b00000 rbx = 0x00007ffd0c9383e0 rcx = 0x0000000000000000 rdx = 0x0000615b7d91a440
rdi = 0x0000000000000000 rsi = 0x0000000000000000 rbp = 0x00007ffd0c938a70 rsp = 0x00007ffd0c9383d8
r8 = 0x0000000000000000 r9 = 0x00007fffffffff01 r10 = 0x00007fffffffff01 r11 = 0x000072a619102301
r12 = 0x000072a618f008f4 r13 = 0x000072a618f008f0 r14 = 0x000072a618f008d4 r15 = 0x000072a618f008d0
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (<unknown module>)
==76909==ABORTING
Example 2: data.job_title/data.job_user
ex2.c:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <cupsfilters/filter.h>
int main(int argc, char** argv)
{
if (argc < 2) return 0;
int fp = open(argv[1], O_RDONLY);
if (!fp) return 0;
int fp_out = open("/dev/null", O_WRONLY);
if (!fp_out) return 0;
cf_filter_data_t data;
memset(&data, 0, sizeof(data));
data.logfunc = cfCUPSLogFunc;
cfFilterTextToPDF(fp, fp_out, 1, &data, NULL);
close(fp);
close(fp_out);
return 0;
}
Since data.job_title/data.job_user are not specified the following error occurs:
==76916==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x653f0ebbc590 bp 0x7ffd3cfd1f20 sp 0x7ffd3cfd16d8 T0)
==76916==The signal is caused by a READ memory access.
==76916==Hint: address points to the zero page.
#0 0x653f0ebbc590 in __sanitizer::internal_strlen(char const*) (/orig/libcupsfilters/ex2+0xfe590) (BuildId: f45644f102bfcd7f7a2e1c3cd16f9f4f8a5560dc)
#1 0x653f0eb8b52b in strdup (/orig/libcupsfilters/ex2+0xcd52b) (BuildId: f45644f102bfcd7f7a2e1c3cd16f9f4f8a5560dc)
#2 0x653f0ec0f426 in _cfPDFOutAddKeyValue /orig/libcupsfilters/cupsfilters/pdfutils.c:243:32
#3 0x653f0ebf147c in write_prolog /orig/libcupsfilters/cupsfilters/texttopdf.c:1941:3
#4 0x653f0ebee87e in cfFilterTextToPDF /orig/libcupsfilters/cupsfilters/texttopdf.c:999:13
#5 0x653f0ebe4181 in main /orig/libcupsfilters/ex2.c:19:5
#6 0x7525ab41e249 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#7 0x7525ab41e304 in __libc_start_main csu/../csu/libc-start.c:360:3
#8 0x653f0eb04890 in _start (/orig/libcupsfilters/ex2+0x46890) (BuildId: f45644f102bfcd7f7a2e1c3cd16f9f4f8a5560dc)
==76916==Register values:
rax = 0xffffffffffffffff rbx = 0x0000000000000000 rcx = 0x0000502000006c10 rdx = 0x0000000000000006
rdi = 0x0000000000000000 rsi = 0x000000006c746954 rbp = 0x00007ffd3cfd1f20 rsp = 0x00007ffd3cfd16d8
r8 = 0x00007525ab41e201 r9 = 0x0000000000000006 r10 = 0x0000000000000000 r11 = 0x5ed99ddc1815d00d
r12 = 0x0000000000000000 r13 = 0x00007ffd3cfe6360 r14 = 0x0000653f0ec77110 r15 = 0x00007525abce3020
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/orig/libcupsfilters/ex2+0xfe590) (BuildId: f45644f102bfcd7f7a2e1c3cd16f9f4f8a5560dc) in __sanitizer::internal_strlen(char const*)
==76916==ABORTING
Example 3: datadir
ex3.c:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <cupsfilters/filter.h>
int main(int argc, char** argv)
{
if (argc < 2) return 0;
int fp = open(argv[1], O_RDONLY);
if (!fp) return 0;
int fp_out = open("/dev/null", O_WRONLY);
if (!fp_out) return 0;
cf_filter_data_t data;
memset(&data, 0, sizeof(data));
data.logfunc = cfCUPSLogFunc;
data.job_title = "smth";
data.job_user = "smth";
cfFilterBannerToPDF(fp, fp_out, 1, &data, NULL);
close(fp);
close(fp_out);
return 0;
}
Since datadir argument is not passed the following error occurs:
==76940==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7b4f96b20619 bp 0x7ffda741e860 sp 0x7ffda741e018 T0)
==76940==The signal is caused by a READ memory access.
==76940==Hint: address points to the zero page.
#0 0x7b4f96b20619 in __strlen_avx2 string/../sysdeps/x86_64/multiarch/strlen-avx2.S:76
#1 0x560e9c6b43b3 in strlen (/orig/libcupsfilters/ex3+0x4d3b3) (BuildId: 464c7ceaaa2cddd33ae77cb70cb400a670376204)
#2 0x560e9c7801eb in template_path /orig/libcupsfilters/cupsfilters/bannertopdf.c:176:19
#3 0x560e9c77d9c2 in banner_new_from_file /orig/libcupsfilters/cupsfilters/bannertopdf.c:301:31
#4 0x560e9c77ca92 in cfFilterBannerToPDF /orig/libcupsfilters/cupsfilters/bannertopdf.c:973:12
#5 0x560e9c77c327 in main /orig/libcupsfilters/ex3.c:19:5
#6 0x7b4f969f2249 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#7 0x7b4f969f2304 in __libc_start_main csu/../csu/libc-start.c:360:3
#8 0x560e9c69ca20 in _start (/orig/libcupsfilters/ex3+0x35a20) (BuildId: 464c7ceaaa2cddd33ae77cb70cb400a670376204)
==76940==Register values:
rax = 0x0000000000000000 rbx = 0x00000000a741e801 rcx = 0x0000000000000c00 rdx = 0x0000000000000000
rdi = 0x0000000000000000 rsi = 0x0000000000000000 rbp = 0x00007ffda741e860 rsp = 0x00007ffda741e018
r8 = 0x0000521000001500 r9 = 0x00007fffffffff01 r10 = 0x00007fffffffff01 r11 = 0x2430f3c996ba7a01
r12 = 0x0000000000000000 r13 = 0x00007ffda741ee90 r14 = 0x0000000000000000 r15 = 0x00007b4f97380020
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV string/../sysdeps/x86_64/multiarch/strlen-avx2.S:76 in __strlen_avx2
==76940==ABORTING
Steps to reproduce:
- Build project and examples with ASAN:
export CFLAGS="$CFLAGS -g -O0 -fsanitize=address"
export CC=clang
export CXX=clang++
autoreconf -fi
./configure --enable-static --disable-silent-rules --with-mutool-path=/usr/bin/mutool --enable-mutool --without-png
make -j10
$CC $CFLAGS -O0 -o ex1 ex1.c ./.libs/libcupsfilters.a -I./ -lcups -ltiff -ljpeg -lexif -lfontconfig -lm /usr/lib/x86_64-linux-gnu/libjxl.so
$CC $CFLAGS -O0 -o ex2 ex2.c ./.libs/libcupsfilters.a -I./ -lcups -ltiff -ljpeg -lexif -lfontconfig -lm /usr/lib/x86_64-linux-gnu/libjxl.so
$CC $CFLAGS -O0 -o ex3 ex3.c ./.libs/libcupsfilters.a -I./ -lcups -ltiff -ljpeg -lexif -lfontconfig -lm /usr/lib/x86_64-linux-gnu/libjxl.so /usr/local/lib/libpdfio.a -lz -lwebp -lpng -lttf
- Run the examples:
echo "" > test.txt
./ex1 test.txt
./ex2 test.txt
./ex3 test.txt
The question is: are those SEGVs considered to be expected/normal behavior, occurring due to the user's fault, or should something be done about them?
It has to be noted that comments in filter.h explicitly say that data.job_title/data.job_user/data.logfunc can be NULL.
https://github.com/OpenPrinting/libcupsfilters/blob/42d458abe27c6930c7c4bcc42bc115cf33145a96/cupsfilters/filter.h#L59
https://github.com/OpenPrinting/libcupsfilters/blob/42d458abe27c6930c7c4bcc42bc115cf33145a96/cupsfilters/filter.h#L60
https://github.com/OpenPrinting/libcupsfilters/blob/42d458abe27c6930c7c4bcc42bc115cf33145a96/cupsfilters/filter.h#L78
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the nullable-field comments in cupsfilters/filter.h, then inspect the reported paths in cupsfilters/texttopdf.c, cupsfilters/pdfutils.c, and cupsfilters/bannertopdf.c. Rebuild with ASAN and run the three examples from the issue to confirm each failure. Done means the expected behavior for NULL fields is established and the affected examples no longer produce the reported SEGVs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100