Skip to content

NULL-related ASAN reports #144

@IliaKash1

Description

@IliaKash1

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:

  1. 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
  1. 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.

char *job_user; // Job user or NULL

char *job_title; // Job title or NULL

void *logdata; // User data for logging function, can be NULL

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions